--*********************************************************** --** THE INDIE STONE ** --** Author: turbotutone ** --*********************************************************** require "ISUI/ISPanel" ISSineWaveDisplay = ISPanel:derive("ISSineWaveDisplay"); function ISSineWaveDisplay:initialise() ISPanel.initialise(self) end function ISSineWaveDisplay:createChildren() end function ISSineWaveDisplay:update() ISPanel.update(self); local isPaused = UIManager.getSpeedControls() and UIManager.getSpeedControls():getCurrentGameSpeed() == 0 if isPaused then return end if self.isOn then local p,w,h = self.waveParams, self:getWidth(), self:getHeight(); -- sine wave local ticks = UIManager.getSecondsSinceLastUpdate() * 30 self.waveCntr = self.waveCntr + ticks if (not self.wave) or self.waveCntr >= self.waveUpdInt or self.hasChanged then local height = ZombRand((h/2)*p.minH,(h/2)*p.maxH); self.wave = self:getWaveData(ZombRand(100*p.minLen,100*p.maxLen),-height,height); self.waveUpdInt = ZombRand(p.minSpeed,p.maxSpeed); self.offsetUpdInt = ZombRand(p.minUpd,p.maxUpd); self.waveCntr = 0; self.hasChanged = false; end self.offsetCntr = self.offsetCntr + ticks; if self.offsetCntr >= self.offsetUpdInt then self.offsetCntr = 0; self.offset = self.offset + 1; if self.offset >= #self.wave-1 then self.offset = 0; end end end end function ISSineWaveDisplay:prerender() ISPanel.prerender(self); end function ISSineWaveDisplay:toggleOn( _b ) self.isOn = _b; end function ISSineWaveDisplay:render() ISPanel.render(self); local p,w,h = self.waveParams, self:getWidth(), self:getHeight(); -- grid lines if self.doGridLines then local c = self.isOn and self.gridColor or self.greyCol; local interval = h/self.gridVertSpacing; for i = 1, self.gridVertSpacing-1 do self:drawRect(1, i*interval, w-2, 1, c.a, c.r, c.g, c.b); end interval = w/self.gridHorzSpacing; for i = 1, self.gridHorzSpacing-1 do self:drawRect(i*interval, 1, 1, h-2, c.a, c.r, c.g, c.b); end end -- sine wave --[[ self.waveCntr= self.waveCntr + 1; if (not self.wave) or self.waveCntr >= self.waveUpdInt or self.hasChanged then local height = ZombRand((h/2)*p.minH,(h/2)*p.maxH); self.wave = self:getWaveData(ZombRand(100*p.minLen,100*p.maxLen),-height,height); self.waveUpdInt = ZombRand(p.minSpeed,p.maxSpeed); self.offsetUpdInt = ZombRand(p.minUpd,p.maxUpd); self.waveCntr = 0; self.hasChanged = false; end self.offsetCntr = self.offsetCntr + 1; if self.offsetCntr >= self.offsetUpdInt then self.offsetCntr = 0; self.offset = self.offset + 1; if self.offset >= #self.wave-1 then self.offset = 0; end end --]] -- It's possible update() hasn't been called yet. if not self.wave then return end if self.isOn then local mean = (h/2); for i = 0, w-1 do local index = ((i+self.offset) % (#self.wave-1))+1; if self.wave[index] then self:drawRect(i, mean+self.wave[index], 1, 1, 1.0, 0.0, 1.0, 0.0); else print("Missing index: "..tostring(index).." max indexes: "..tostring(#self.wave)); end end end end function ISSineWaveDisplay:setWaveParameters(_minLen, _maxLen,_minHeight, _maxHeight, _minUpdFreq, _maxUpdFreq, _minScrollSpeed, _maxScrollSpeed) self.waveParams.minLen = _minLen; self.waveParams.maxLen = _maxLen; self.waveParams.minH = _minHeight; self.waveParams.maxH = _maxHeight; self.waveParams.minUpd = _minUpdFreq; self.waveParams.maxUpd = _maxUpdFreq; self.waveParams.minSpeed = _minScrollSpeed; self.waveParams.maxSpeed = _maxScrollSpeed; self.hasChanged = true; end local function clerp( _t, _a, _b ) local t2 = (1-math.cos(_t*math.pi))/2; return(_a*(1-t2)+_b*t2); end function ISSineWaveDisplay:getWaveData(_len,_minH,_maxH) local tab = {}; local flip = false; for i = 1, _len do if(i>_len/2) then flip = true; end local ii = flip and i-(_len/2) or i; table.insert(tab, clerp(ii*(1/(_len/2)),flip and _maxH or _minH, flip and _minH or _maxH)); end return tab; end function ISSineWaveDisplay:new (x, y, width, height) local o = ISPanel:new(x, y, width, height); setmetatable(o, self) self.__index = self o.x = x; o.y = y; o.background = true; o.backgroundColor = {r=0, g=0, b=0, a=1.0}; o.borderColor = {r=0.8, g=0.8, b=0.8, a=1}; o.gridColor = {r=0.0, g=0.3, b=0.0, a=1}; o.greyCol = { r=0.4,g=0.4,b=0.4,a=1}; o.width = width; o.height = height; o.anchorLeft = true; o.anchorRight = false; o.anchorTop = true; o.anchorBottom = false; o.doGridLines = true; o.gridHorzSpacing = 20; o.gridVertSpacing = 2; o.waveParams = { minLen = 0.2, maxLen = 0.6, minHeight = 0.1, maxHeight = 1.0, minUpd = 1, maxUpd = 10, minSpeed = 1, maxSpeed = 10 }; o.offsetCntr = 0; o.offsetUpdInt = 4; o.offset = 0; o.waveCntr = 0; o.waveUpdInt = 30; o.hasChanged = false; o.isOn = true; return o end