Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --# ExampleA
- ExampleA = class()
- function ExampleA:init()
- self:start()
- end
- function ExampleA:start()
- self.rot = false
- if self.t ~= nil then
- tween.stop(self.t)
- end
- self.t = tween.delay(3, function()
- self.rot = true
- end)
- self.cam = vec2(0, -2)
- self.explosions = {Explosion(vec3(0, 0, 0), true)}
- parameter.action("New Explosion", function()
- table.insert(self.explosions, Explosion(vec3(math.random(-5, 5), 0, math.random(-5, 5))))
- end)
- parameter.boolean("Anarchy", false)
- end
- function ExampleA:draw()
- if self.rot then
- self.cam = self.cam:rotate(math.rad(45 / 60))
- end
- if Anarchy and ElapsedTime % 1 <= 5 / 60 then
- table.insert(self.explosions, Explosion(vec3(math.random(-5, 5), 0, math.random(-5, 5))))
- end
- camera(self.cam.x, 0.5, self.cam.y, 0, 0.5, 0)
- perspective(45)
- for k, v in pairs(self.explosions) do
- v:draw()
- if v.stopped then
- table.remove(self.explosions, k)
- end
- end
- rotate(90, 1, 0, 0)
- scale(0.01)
- sprite("Platformer Art:Block Brick")
- end
- function ExampleA:touched(touch)
- tween.stop(self.t)
- self.rot = false
- self.cam = self.cam:rotate(math.rad(touch.deltaX))
- self.t = tween.delay(3, function()
- self.rot = true
- end)
- end
- --# ExampleB
- ExampleB = class()
- function ExampleB:init()
- self:start()
- end
- function ExampleB:start()
- self.exp = nil
- -- all the unique vertices that make up a cube
- local vertices = {
- vec3(-0.5, -0.5, 0.5), -- Left bottom front
- vec3( 0.5, -0.5, 0.5), -- Right bottom front
- vec3( 0.5, 0.5, 0.5), -- Right top front
- vec3(-0.5, 0.5, 0.5), -- Left top front
- vec3(-0.5, -0.5, -0.5), -- Left bottom back
- vec3( 0.5, -0.5, -0.5), -- Right bottom back
- vec3( 0.5, 0.5, -0.5), -- Right top back
- vec3(-0.5, 0.5, -0.5), -- Left top back
- }
- -- now construct a cube out of the vertices above
- local cubeverts = {
- -- Front
- vertices[1], vertices[2], vertices[3],
- vertices[1], vertices[3], vertices[4],
- -- Right
- vertices[2], vertices[6], vertices[7],
- vertices[2], vertices[7], vertices[3],
- -- Back
- vertices[6], vertices[5], vertices[8],
- vertices[6], vertices[8], vertices[7],
- -- Left
- vertices[5], vertices[1], vertices[4],
- vertices[5], vertices[4], vertices[8],
- -- Top
- vertices[4], vertices[3], vertices[7],
- vertices[4], vertices[7], vertices[8],
- -- Bottom
- vertices[5], vertices[6], vertices[2],
- vertices[5], vertices[2], vertices[1],
- }
- -- all the unique texture positions needed
- local texvertices = { vec2(0.03,0.24),
- vec2(0.97,0.24),
- vec2(0.03,0.69),
- vec2(0.97,0.69) }
- -- apply the texture coordinates to each triangle
- local cubetexCoords = {
- -- Front
- texvertices[1], texvertices[2], texvertices[4],
- texvertices[1], texvertices[4], texvertices[3],
- -- Right
- texvertices[1], texvertices[2], texvertices[4],
- texvertices[1], texvertices[4], texvertices[3],
- -- Back
- texvertices[1], texvertices[2], texvertices[4],
- texvertices[1], texvertices[4], texvertices[3],
- -- Left
- texvertices[1], texvertices[2], texvertices[4],
- texvertices[1], texvertices[4], texvertices[3],
- -- Top
- texvertices[1], texvertices[2], texvertices[4],
- texvertices[1], texvertices[4], texvertices[3],
- -- Bottom
- texvertices[1], texvertices[2], texvertices[4],
- texvertices[1], texvertices[4], texvertices[3],
- }
- -- now we make our 3 different block types
- self.ms = mesh()
- self.ms.vertices = cubeverts
- self.ms.texture = "Planet Cute:Stone Block"
- self.ms.texCoords = cubetexCoords
- self.ms:setColors(255,255,255,255)
- self.md = mesh()
- self.md.vertices = cubeverts
- self.md.texture = "Planet Cute:Dirt Block"
- self.md.texCoords = cubetexCoords
- self.md:setColors(255,255,255,255)
- self.mg = mesh()
- self.mg.vertices = cubeverts
- self.mg.texture = "Planet Cute:Grass Block"
- self.mg.texCoords = cubetexCoords
- self.mg:setColors(255,255,255,255)
- -- currently doesnt work properly without backfaces
- self.mw = mesh()
- self.mw.vertices = cubeverts
- self.mw.texture = "Planet Cute:Water Block"
- self.mw.texCoords = cubetexCoords
- self.mw:setColors(255,255,255,100)
- -- stick 'em in a table
- self.blocks = { self.mg, self.md, self.ms }
- -- our scene itself
- -- numbers correspond to block positions in the blockTypes table
- -- bottom middle top
- self.scene = { { {1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 0, 0}, {0, 0, 0, 0, 0, 0}, },
- { {1, 1, 1, 1, 1, 1}, {1, 1, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, },
- { {1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, },
- { {1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, },
- { {1, 1, 1, 1, 1, 1}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, },
- { {1, 1, 1, 1, 1, 1}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, },
- }
- self.time = 0
- end
- function ExampleB:draw()
- self.time = self.time + DeltaTime
- pushMatrix()
- pushStyle()
- -- Make a floor
- --translate(0,-Size/2,0)
- --rotate(Angle,0,1,0)
- local norm = vec3(0.1, 1, 0):normalize()
- camera(0, 0.23, -0.12, 0, 0.15, 2, norm.x, norm.y, norm.z)
- perspective(45)
- rotate(90,1,0,0)
- --sprite("SpaceCute:Background", 0, 0, 300, 300)
- -- render each block in turn
- for zi,zv in ipairs(self.scene) do
- for yi,yv in ipairs(zv) do
- for xi, xv in ipairs(yv) do
- -- apply each transform need - rotate, scale, translate to the correct place
- resetMatrix()
- --rotate(Angle,0,1,0)
- --local s = Size*0.25
- --scale(s,s,s)
- scale(0.25)
- translate(xi-2, yi-2, zi-2) -- renders based on corner
- -- so -2 fudges it near center
- if xv > 0 then
- self.blocks[xv]:draw()
- end
- end
- end
- end
- popStyle()
- popMatrix()
- if self.exp ~= nil then
- self.exp:draw()
- if self.exp.stopped then
- self.exp = nil
- self.time = 0
- end
- elseif self.time >= 3 then
- self.exp = Explosion(vec3(0, 0, 0.5))
- end
- end
- function ExampleB:touched(touch)
- end
- --# Explosion
- Explosion
- = class() -- I usually move the "= class()" to another line so if it crashes, all you see is "Explosion"
- local expScene = {}
- local expSim = {}
- local fireSim = {}
- local fireTrail = {}
- local rad, sin, cos = math.rad, math.sin, math.cos -- efficiency
- for i = 0, 360 do -- Generate mushroom particles
- local a = i % 90 * 4 -- Angle of particle
- local d = i / 360 -- Distance from center
- local r = rad(a) -- Radian version of angle
- local s, c = sin(r), cos(r) -- Sine and cosine of angle
- table.insert(expSim, {x = s * d, y = 0, z = c * d, m = 3, a = 0, s = 1}) -- Create particle
- end
- for i = 0, 360, 22.5 do -- Generate fire burst particles
- local a = i % 90 * 4 -- Angle of particle
- local d = i / 720 + 0.5 -- Distance from center
- local r = rad(a) -- Radian version of angle
- local s, c = sin(r), cos(r) -- Sine and cosine of angle
- table.insert(fireSim, {x = s * d, y = 0, z = c * d, m = d * 3, a = 0, s = 1.2}) -- Create particle
- end
- pushStyle()
- noStroke()
- for f = 0, 180 do -- Pre-simulate particle physics and pre-render particles for unlimited explosions with no lag
- if f <= 120 then
- for a = 1, 10 do -- Generate stem particles
- table.insert(expSim, {x = sin(f + a * 0.5), y = 0, z = cos(f + a * 0.5), m = 3, a = 0, s = 1}) -- Create particle
- end
- else
- local c = 0 -- Disintegrate particles after prime
- for i = 1, #expSim do
- table.remove(expSim, i)
- c = c + 1
- if c > 32 then -- Limit maximum removals per frame (disintegrate effect)
- break
- end
- end
- end
- for k, v in pairs(expSim) do -- Remove edge particles
- if expSim[k].x <= -10 or expSim[k].x >= 10 then -- Check if on screen edge
- table.remove(expSim, k)
- end
- end
- for k, v in pairs(fireSim) do -- Remove edge particles
- if fireSim[k].y <= -5 then -- Check if on screen edge
- table.remove(fireSim, k)
- end
- end
- local c = 0
- for k, v in pairs(expSim) do -- Disintegrate old particles
- expSim[k].a = expSim[k].a + 1 -- Add age
- if expSim[k].a >= 80 then
- table.remove(expSim, k)
- c = c + 1
- if c > 15 then -- Limit maximum removals per frame (disintegrate effect)
- break
- end
- end
- end
- expScene[f] = image(128, 128) -- Init image for current frame
- setContext(expScene[f]) -- Pre-render all the particles
- for k, v in pairs(fireTrail) do -- Draw smoke trail behind fire
- fireTrail[k].a = fireTrail[k].a + 1
- fill(127)
- ellipse(v.x * 5 + 64, v.y, 5)
- if fireTrail[k].a >= 10 then
- table.remove(fireTrail, k)
- end
- end
- for i = 1, #fireSim do -- Draw fire particles
- fireSim[i].s = fireSim[i].s * 0.993 -- Particle physics
- fireSim[i].x = fireSim[i].x * math.max(1, fireSim[i].s)
- fireSim[i].z = fireSim[i].z * math.max(1, fireSim[i].s)
- fireSim[i].m = fireSim[i].m - 0.15
- fireSim[i].y = fireSim[i].y + fireSim[i].m
- local tbl = {}
- for k, v in pairs(fireSim[i]) do
- tbl[k] = v
- end
- table.insert(fireTrail, tbl)
- fireTrail[#fireTrail].a = 0
- pushStyle()
- local middle = color(255, 255, 255, 255)
- local inner = color(255, 127, 0, 255)
- local rim = color(255, 0, 0, 255)--]]
- local a = math.abs(fireSim[i].x * 5) / 16
- local b = math.abs(fireSim[i].x * 5) / 32
- fill(rim:mix(inner:mix(middle, a), b))
- ellipse(fireSim[i].x * 5 + 64, fireSim[i].y, 5)
- popStyle()
- end
- for i = 1, #expSim do -- Draw the explosion particles
- if expSim[i].y < 50 then -- Particle physics
- expSim[i].x = expSim[i].x * (1.05 * expSim[i].s)
- expSim[i].z = expSim[i].z * (1.05 * expSim[i].s)
- else
- expSim[i].x = expSim[i].x * (0.99 * expSim[i].s)
- expSim[i].z = expSim[i].z * (0.99 * expSim[i].s)
- end
- expSim[i].m = expSim[i].m * 0.95
- expSim[i].y = expSim[i].y + expSim[i].m
- if expSim[i].y >= 50 then
- expSim[i].y = expSim[i].y + 0.1
- end
- pushStyle()
- -- Old colors, just saved for archiving
- --[[local middle = color(255, 255, 255, 255)
- local inner = color(255, 127, 0, 255)
- local rim = color(255, 0, 0, 255)--]]
- -- New colors
- local middle = color(191)
- local inner = color(127)
- local rim = color(63)
- local a = math.abs(expSim[i].x * 5) / 16 -- Color calculation
- local b = math.abs(expSim[i].x * 5) / 32
- fill(rim:mix(inner:mix(middle, a), b))
- ellipse(expSim[i].x * 5 + 64, expSim[i].y, 5)
- popStyle()
- end
- setContext()
- end
- popStyle()
- ----
- -- pos: vec3 (optional, vec3(x, y, z))
- -- loop: boolean (optional, true or false)
- -- speed: number (optional, 0.5 - 2 etc.)
- -- res: number (optional, 0.5 - 2 etc.)
- ----
- function Explosion:init(pos, loop, speed, res)
- self.pos = pos or vec3(0, 0, 0)
- self.loop = loop or false
- self.speed = speed or 1
- self.res = res or 1
- self.time = 0
- self.stopped = false
- self.m = mesh() -- Basic 3D plane mesh
- self.m.vertices = {
- vec3(-0.5, 0, 0), vec3(-0.5, 1, 0), vec3(0.5, 1, 0),
- vec3(-0.5, 0, 0), vec3(0.5, 1, 0), vec3(0.5, 0, 0),
- }
- self.m.texCoords = {
- vec2(0, 0), vec2(0, 1), vec2(1, 1),
- vec2(0, 0), vec2(1, 1), vec2(1, 0),
- }
- self.m:setColors(color(255))
- self.m.shader = shader(Shaders.Discard.vS, Shaders.Discard.fS) -- Simple shader to discard backfaces and non-visible pixels
- end
- function Explosion:draw()
- self.time = self.time + DeltaTime * self.speed -- Increment explosion time
- if self.loop or self.time <= #expScene / 60 then -- If not done
- pushMatrix()
- pushStyle()
- translate(self.pos.x, self.pos.y, self.pos.z)
- smooth()
- self.m.texture = expScene[math.floor(self.time % (#expScene / 60) * 60)] -- Assign current pre-rendered frame to mesh
- for i = 0, 360, 45 / self.res do -- Resoltion for loop
- pushMatrix()
- rotate(i, 0, 1, 0)
- self.m:draw() -- Draw the mesh
- popMatrix()
- end
- popStyle()
- popMatrix()
- else
- self.stopped = true
- end
- end
- --# FPS
- FPS = 0
- local frames = 0
- local time = 0
- tween.delay(0, function()
- local d = draw
- draw = function()
- frames = frames + 1
- if math.floor(ElapsedTime) ~= math.floor(time) then
- FPS = frames - 1
- frames = 1
- end
- time = ElapsedTime
- d()
- end
- end)
- --# Main
- -- 3D Explosion Simulator
- spriteBatching(false)
- -- Use this function to perform your initial setup
- function setup()
- print("Hello World!")
- scenes = {ExampleA(), ExampleB()}
- parameter.integer("Scene", 1, #scenes, 1, function()
- scenes[Scene]:start()
- end)
- parameter.watch("FPS")
- end
- -- This function gets called once every frame
- function draw()
- -- This sets a dark background color
- background(40, 40, 50)
- -- This sets the line thickness
- strokeWidth(5)
- -- Do your drawing here
- scenes[Scene]:draw()
- end
- function touched(touch)
- scenes[Scene]:touched(touch)
- end
- --# Shaders
- Shaders = {
- Discard = {
- vS = [[
- //
- // A basic vertex shader
- //
- //This is the current model * view * projection matrix
- // Codea sets it automatically
- uniform mat4 modelViewProjection;
- //This is the current mesh vertex position, color and tex coord
- // Set automatically
- attribute vec4 position;
- attribute vec4 color;
- attribute vec2 texCoord;
- //This is an output variable that will be passed to the fragment shader
- varying lowp vec4 vColor;
- varying highp vec2 vTexCoord;
- void main()
- {
- //Pass the mesh color to the fragment shader
- vColor = color;
- vTexCoord = texCoord;
- //Multiply the vertex position by our combined transform
- gl_Position = modelViewProjection * position;
- }
- ]],
- fS = [[
- //
- // A basic fragment shader
- //
- //Default precision qualifier
- precision highp float;
- //This represents the current texture on the mesh
- uniform lowp sampler2D texture;
- //The interpolated vertex color for this fragment
- varying lowp vec4 vColor;
- //The interpolated texture coordinate for this fragment
- varying highp vec2 vTexCoord;
- void main()
- {
- if (!gl_FrontFacing) discard; // Discard backfaces
- //Sample the texture at the interpolated coordinate
- lowp vec4 col = texture2D( texture, vTexCoord ) * vColor;
- if (col.a <= 0.8) discard; // Discard non-visible pixels
- //Set the output color to the texture color
- gl_FragColor = col;
- }
- ]],
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement