Skip to content

Instantly share code, notes, and snippets.

@peteroyle
Created April 12, 2012 11:53
Show Gist options
  • Save peteroyle/2366800 to your computer and use it in GitHub Desktop.
Save peteroyle/2366800 to your computer and use it in GitHub Desktop.
Noise Works Codea Project
--# CircleMask
CircleMask = class()
function CircleMask:init(rad, sides)
-- you can accept and set parameters here
self.mesh = mesh()
local verts = {}
local tex = {}
for i=1,sides do
local r1 = (i-1)/sides * math.pi * 2
local r2 = i/sides * math.pi * 2
local p1 = vec2( math.cos(r1), math.sin(r1) )
local p2 = vec2( math.cos(r2), math.sin(r2) )
-- Verts
table.insert(verts, p1 * rad)
table.insert(verts, p2 * rad)
table.insert(verts, vec2(0,0)) -- center
-- Tex Coords
table.insert(tex, (p1 + vec2(1,1)) * 0.5)
table.insert(tex, (p2 + vec2(1,1)) * 0.5)
table.insert(tex, vec2(0.5,0.5))
end
self.mesh.vertices = verts
self.mesh.texCoords = tex
self.mesh:setColors( 255,255,255 )
end
function CircleMask:setDrawFunction(func, w, h)
self.mesh.texture = image(w,h)
self.drawFunction = func
end
function CircleMask:setTexture(tex)
self.mesh.texture = tex
self.drawFunction = nil
end
function CircleMask:draw()
if self.drawFunction ~= nil then
setContext( self.mesh.texture )
pushMatrix()
resetMatrix()
self.drawFunction()
popMatrix()
setContext()
end
self.mesh:draw()
end
--# Main
supportedOrientations(LANDSCAPE_ANY)
-- Use this function to perform your initial setup
function setup()
iparameter("numTiles", 2, 64, 12)
parameter("noiseScale", 1/30, 1, 1/5)
parameter("noiseSpeedX", 0, 20, 0)
parameter("noiseSpeedZ", 0, 20, 0)
parameter("rnd", 0, 20)
parameter("minShade", 0, 255, 100)
parameter("maxShade", 0, 255, 200)
iparameter("circularFrame", 0, 1, 0)
iparameter("frameSides", 4, 64, 64)
iparameter("mesh_or_image", 0, 1, 1)
parameter("size", 0, 1, 1)
frameDim = vec2(WIDTH, HEIGHT)
bgMesh = mesh()
bgMesh:addRect(0,0,frameDim.x,frameDim.y)
colA = color(0, 0, 0, 255)
colB = color(123, 141, 172, 255)
bgMesh:color(1, colB)
bgMesh:color(2, colA)
bgMesh:color(3, colA)
bgMesh:color(4, colB)
bgMesh:color(5, colA)
bgMesh:color(6, colB)
reinit()
end
function reinit()
local nSpeed = vec3(noiseSpeedX, 0, noiseSpeedZ)
local loc = vec2(0, 0)
local minShadeC = color(minShade,minShade,minShade,255)
local maxShadeC = color(maxShade,maxShade,maxShade,255)
doTranslate = circularFrame == 0
if mesh_or_image == 0 then
if circularFrame == 0 then
noiseView = MeshNoiseView(frameDim, loc, numTiles, noiseScale, nSpeed,
rnd, minShadeC, maxShadeC)
else
noiseView = PlanetViewFactory.meshNoise(loc, frameDim.x, frameSides,
minShadeC, maxShadeC, noiseScale, numTiles, nSpeed, rnd)
end
else
if circularFrame == 0 then
noiseView = ImgNoiseView(frameDim, loc, numTiles, noiseScale, nSpeed,
rnd, minShadeC, maxShadeC)
else
noiseView = PlanetViewFactory.imgNoise(loc, frameDim.x, frameSides,
minShadeC, maxShadeC, noiseScale, numTiles, nSpeed, rnd)
end
end
end
-- This function gets called once every frame
function draw()
pushMatrix()
translate(frameDim.x/2, frameDim.y/2)
bgMesh:draw()
scale(size)
if doTranslate then
translate(0-frameDim.x/2, 0-frameDim.y/2)
end
noiseView:draw()
popMatrix()
fill(255, 0, 0, 255)
text(1/DeltaTime, WIDTH*0.2, HEIGHT*0.2)
text("TAP TO RESET", WIDTH*0.8, HEIGHT*0.2)
end
function touched(touch)
if touch.state == ENDED then
reinit()
end
end
--# NoiseView
NoiseView = class()
function NoiseView:init(frameDim, loc, numTiles, nScale, nSpeed,
nRnd, nMinShade, nMaxShade)
self.frameDim = frameDim
self.loc = loc
self.numTiles = numTiles
self.nScale = nScale
self.nSpeed = nSpeed
self.nRnd = nRnd
self.nMinShade = nMinShade
self.nMaxShade = nMaxShade
self:initView()
end
function NoiseView:initView()
self.tileSize = self.frameDim.x/self.numTiles
-- +1 to fill remaining space lost by int devision and mult
self.numXs = (self.frameDim.x/self.tileSize)+1
self.numYs = (self.frameDim.y/self.tileSize)+1
self.tiles = {}
self.noisePos = vec3(1,1,1)
for x = 1, self.numXs+1 do
self.tiles[x] = {}
self:initViewForX(x)
for y = 1, self.numYs+1 do
local lum = self:calcNoise(x, y, 1)
self.tiles[x][y] = lum
if x <= self.numXs and y <= self.numYs then
self:initViewForXY(x, y)
end
end
end
end
function NoiseView:moveNoise()
self.noisePos = self.noisePos + self.nSpeed * DeltaTime
for x = 1, self.numXs+1 do
for y = 1, self.numYs+1 do
if x <= self.numXs and y <= self.numYs then
self:updateViewForXY(x, y)
end
self.tiles[x][y] = self:calcNoise(x, y, 1)
end
end
end
function NoiseView:draw()
self:moveNoise()
self:drawView()
end
function NoiseView:calcNoise(x, y, z)
local lum = 0
if self.nRnd > 0 then
lum = noise((x+math.random()*(self.nRnd*self.nScale)) * self.nScale + self.noisePos.x,
(y+math.random()*(self.nRnd*self.nScale)) * self.nScale + self.noisePos.y,
(z+math.random()*(self.nRnd*self.nScale)) * self.nScale + self.noisePos.z)
else
lum = noise(x * self.nScale + self.noisePos.x,
y * self.nScale + self.noisePos.y,
z * self.nScale + self.noisePos.z)
end
lum = (lum + 1)/2
return self:blend(self.nMinShade, self.nMaxShade, lum)
end
function NoiseView:blend(c1, c2, a)
return color(c1.r * a + c2.r * (1-a),
c1.g * a + c2.g * (1-a),
c1.b * a + c2.b * (1-a),
c1.a)
end
MeshNoiseView = class(NoiseView)
function MeshNoiseView:init(frameDim, loc, numTiles, nScale, nSpeed,
nRnd, nMinShade, nMaxShade)
self.meshIndexes = {}
self.noiseMesh = mesh()
self.meshIndex = 1
NoiseView.init(self, frameDim, loc, numTiles, nScale, nSpeed,
nRnd, nMinShade, nMaxShade)
end
function MeshNoiseView:initViewForX(x)
self.meshIndexes[x] = {}
end
function MeshNoiseView:initViewForXY(x, y)
self.noiseMesh:addRect((x-1)*self.tileSize, (y-1)*self.tileSize,
self.tileSize, self.tileSize)
self.noiseMesh:setRectColor(self.meshIndex, self.tiles[x][y])
self.meshIndexes[x][y] = self.meshIndex
self.meshIndex = self.meshIndex + 1
end
function MeshNoiseView:updateViewForXY(x, y)
local sqrOffset = 1
local firstInd =(((x-1)*self.numXs + y)*6)-5
local lum = self.tiles[x][y+sqrOffset]
self.noiseMesh:color(firstInd, lum)
lum = self.tiles[x][y]
self.noiseMesh:color(firstInd+1, lum)
lum = self.tiles[x+sqrOffset][y]
self.noiseMesh:color(firstInd+2, lum)
lum = self.tiles[x][y+sqrOffset]
self.noiseMesh:color(firstInd+3, lum)
lum = self.tiles[x+sqrOffset][y]
self.noiseMesh:color(firstInd+4, lum)
lum = self.tiles[x+sqrOffset][y+sqrOffset]
self.noiseMesh:color(firstInd+5, lum)
end
function MeshNoiseView:drawView()
pushMatrix()
self.noiseMesh:draw()
popMatrix()
end
ImgNoiseView = class(NoiseView)
function ImgNoiseView:init(frameDim, loc, numTiles, nScale, nSpeed,
nRnd, nMinShade, nMaxShade)
self.noiseImg = image(numTiles+1, numTiles+1)
NoiseView.init(self, frameDim, loc, numTiles, nScale, nSpeed,
nRnd, nMinShade, nMaxShade)
end
function ImgNoiseView:initViewForX(x)
end
function ImgNoiseView:initViewForXY(x, y)
self.noiseImg:set(x, y, self.tiles[x][y])
end
function ImgNoiseView:updateViewForXY(x, y)
self.noiseImg:set(x, y, self.tiles[x][y])
end
function ImgNoiseView:drawView()
pushMatrix()
translate(self.frameDim.x/2, self.frameDim.y/2)
local sc = self.frameDim.x / self.numTiles
scale(sc)
sprite(self.noiseImg)
popMatrix()
end
--# PlanetView
PlanetView = class()
function PlanetView:init(loc, diameter, sides, innerView, animated)
self.loc = loc
self.diameter = diameter
self.radius = self.diameter/2
self.sides = sides
self.innerView = innerView
self.animated = animated
self.viewMask = CircleMask(self.radius, sides)
if self.animated then
self.viewMask:setDrawFunction(function()
self.innerView:draw()
end, self.diameter, self.diameter)
else
self:createStillImage(self.diameter, self.diameter)
end
end
function PlanetView:createStillImage( w, h )
if self.stillImg ~= nil then
return
end
pushMatrix()
resetMatrix()
local i = image(w, h)
setContext(i)
self.innerView:draw()
pushStyle()
ellipseMode(CENTER)
fill(5, 5, 5, 1)
ellipse(w*0.5, h*0.8, w*1.5, h)
popStyle()
popMatrix()
setContext()
self.viewMask:setTexture(i)
local j = image(w, h)
setContext(j)
local planetRatio = 0.8
self:drawShade(w, planetRatio*w)
pushMatrix()
translate(w/2, h/2)
scale(planetRatio)
self.viewMask:draw()
popMatrix()
setContext()
self.stillImg = j
end
function PlanetView:drawShade(imgW, innerW)
pushStyle()
local shadeDiam = imgW
local shadeW = shadeDiam - innerW
local numShades = shadeW/16
for i=1, numShades do
local ratio = i/numShades
local w = innerW + ratio * shadeW
fill(0,5)
ellipseMode(CENTER)
ellipse(imgW*0.5, imgW*0.4, w, w*0.8)
end
popStyle()
end
function PlanetView:draw()
if self.animated then
self.viewMask:draw()
else
sprite(self.stillImg)
end
end
-----------------------------------------
PlanetViewFactory = class()
function PlanetViewFactory.meshNoise(loc, diameter, sides, baseColor, mainColor,
nScale, resolution, nSpeed, nRnd)
local innerView = MeshNoiseView(vec2(diameter, diameter), loc, resolution, nScale, nSpeed,
nRnd, baseColor, mainColor)
local animated = nSpeed ~= vec3(0,0,0)
local planetView = PlanetView(loc, diameter, sides, innerView, animated)
return planetView
end
function PlanetViewFactory.imgNoise(loc, diameter, sides, baseColor, mainColor,
nScale, resolution, nSpeed, nRnd)
local innerView = ImgNoiseView(vec2(diameter, diameter), loc, resolution, nScale, nSpeed,
nRnd, baseColor, mainColor)
local animated = nSpeed ~= vec3(0,0,0)
local planetView = PlanetView(loc, diameter, sides, innerView, animated)
return planetView
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment