Skip to content

Instantly share code, notes, and snippets.

@briarfox
Forked from juaxix/EnemyHorde.lua
Created March 13, 2013 22:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save briarfox/5156862 to your computer and use it in GitHub Desktop.
Save briarfox/5156862 to your computer and use it in GitHub Desktop.
-- Class EnemyHorde
-- Speed Shooting Earth
-- A freesource game project using Codea and Google Maps
-- More games: xixgames.com
-- by @juaxix
-- 6/6/2012
ENEMY_SPAWN_EASY = 0
ENEMY_SPAWN_HARD = 1
EnemyHorde = class()
function EnemyHorde:init()
    self.frame = 0
    self.units = {} -- enemy units
    self.heroBullets = {} -- ship's bullets
    self.explosions = {}
    self.enemySize = 50
    self.killCount = 0
    self.spawnPattern = ENEMY_SPAWN_HARD
    self.model = self:generateRandomModel()
end
function EnemyHorde:generateRandomModel()
    local models = {"A","B","C","D","C 1"}
    return "Tyrian Remastered:Enemy Ship "..models[math.random(1,#models)]
    --print(self.model)
end
function EnemyHorde:draw()
    self.frame = (self.frame+1)%128
    -- Spawn random enemy every 100 frames
    if self.frame%100 == 0 then
        spawn = { 
                  pos = vec2( math.random(WIDTH), HEIGHT + self.enemySize ),
                  mod = self.model.."" -- copy
                }
        table.insert( self.units, spawn )    
    end
    noTint()
    for i,v in ipairs(self.units) do
        -- Move unit down
        v.pos.y = v.pos.y - 5    
        -- If hard, move in sine wave
        if self.spawnPattern == ENEMY_SPAWN_HARD then
            -- Compute movement vector
            sideMove = vec2( math.sin(v.pos.y * 0.02) * 5, 0 )
            v.pos = v.pos + sideMove
        end
        -- Cull unit
        culled = false
        if (v.pos.y + self.enemySize) < 0 then
            table.remove(self.units, i)
            culled = true -- no continue statement
        end 
        -- Check if hit by a bullet
        if culled == false then
            for j,b in ipairs(self.heroBullets) do
                local hit = false
                if v.pos:dist(b.position) < self.enemySize/2 then
                    hit = true
                elseif b.px~=0 and v.pos:dist(vec2(b.px,b.position.y))<self.enemySize/2 then
                    hit = true
                end
                if hit then
                    table.remove(self.units, i)
                    table.remove(self.heroBullets, j)
                    
                    -- Explode!
                    table.insert(self.explosions, Explosion(v.pos))
                    -- Update score
                    world.score = world.score + 1000
                end
            end
        end
        -- Draw unit
        sprite(v.mod, v.pos.x, v.pos.y, self.enemySize)
    end
    -- Draw explosions
    for i,e in ipairs(self.explosions) do
        e:draw()
        if e:isDone() then
            table.remove(self.explosions,i)
        end
    end
    
end
-- Explosion Class
Explosion = class()
-- Speed Shooting Earth
-- A freesource game project using Codea and Google Maps
-- More games: xixgames.com
-- by @juaxix
-- 6/6/2012
function Explosion:init(pos)
    self.position = pos
    self.opacity = 255
    self.time = 0
    sound("explode",967)
end
function Explosion:isDone()
    return self.opacity <= 0
end
function Explosion:draw()
    self.time = self.time + 0.5
    self.opacity = 255 * (1 - (self.time/30))
    tint(255,255,255,self.opacity)
    sprite("Tyrian Remastered:Explosion Huge",self.position.x,self.position.y)
    noTint()
end
-- Main script
-- Speed Shooting Earth
-- A freesource game project using Codea and Google Maps
-- More games: xixgames.com
-- by @juaxix
-- 6/6/2012
function setup()
    supportedOrientations(LANDSCAPE_ANY)
    displayMode(FULLSCREEN)
    ----------------------------------------------------
    changeGameMode("Menu")
    ----------------------------------------------------
end
function changeGameMode(newMode)
    GameMode  = newMode
    highscore = readLocalData("highscore")
    if not highscore then
        highscore = 0
    end
    if GameMode == "Menu" then
        world = nil
        menu  = MainMenu()
    elseif GameMode == "Game" then
        menu = nil
        if shipModel == "" then
            shipModel ="Tyrian Remastered:Ship A"
        end
        if not gpsLocation then
            gpsLocation = vec2(40.494677,-3.558841)
        end
        if not gpsSpeed then
            gpsSpeed = .021
        end
        
        world = World()
    end
end
-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(40, 40, 50)
    if GameMode == "Game" then
        world:draw()
    elseif GameMode == "Menu" then
        menu:draw()
    end
end
function touched(touch)
    if GameMode == "Game" then
        world:touched(touch)
    elseif GameMode == "Menu" then
        menu:touched(touch)
    end
end
-- Main Menu Class
MainMenu = class()
-- Speed Shooting Earth
-- A freesource game project using Codea and Google Maps
-- More games: xixgames.com
-- by @juaxix
-- 6/6/2012
function MainMenu:init()
    self.clouds = {}
    self.frame  = 0
    self.ships  = {
      {model="Tyrian Remastered:Ship A",
            position=vec2(WIDTH/3,HEIGHT/2),size=vec2(40,54),
            name="Ship A", menupos = vec2(WIDTH/2,HEIGHT/2)
      },
      {model="Tyrian Remastered:Ship B",
            position=vec2(WIDTH/3,HEIGHT/2.5),size=vec2(40,54),
            name="Ship B", menupos = vec2(WIDTH/2,HEIGHT/2.5)
      },
      {model="Tyrian Remastered:Ship C",
            position=vec2(WIDTH/3,HEIGHT/3.2),size=vec2(40,54),
            name="Ship C", menupos = vec2(WIDTH/2,HEIGHT/3.2)
      },
      {model="Tyrian Remastered:Ship D",
            position=vec2(WIDTH/3,HEIGHT/4.4),size=vec2(40,54),
            name="Ship D", menupos = vec2(WIDTH/2,HEIGHT/4.4)
      }
    }
    self.places  = {
      {model="SpaceCute:Planet",
            position=vec2(WIDTH/4,HEIGHT/2),size=vec2(76,92),
            name="Barajas, Madrid - Spain", menupos = vec2(WIDTH/2,HEIGHT/2),
            gps = vec2(40.494677,-3.558841), speed = .021
      },
      {model="SpaceCute:Planet",
            position=vec2(WIDTH/4,HEIGHT/2.5),size=vec2(76,92),
            name="Sydney, Australia", menupos = vec2(WIDTH/2,HEIGHT/2.5),
            gps = vec2(-33.946111,151.177222), speed = .0227
      },
      {model="SpaceCute:Planet",
            position=vec2(WIDTH/4,HEIGHT/3.2),size=vec2(76,92),
            name="Dublin, Ireland", menupos = vec2(WIDTH/2,HEIGHT/3.2),
            gps = vec2(53.421389,-6.27), speed = .0164
      },
    }
    self.universe = Universe()
    self.mode     = "home"
    self:createBodies()
end
function MainMenu:generateClouds(num)
    for i=1,num do
        table.insert(self.clouds,
         {
            position = vec2(math.random(WIDTH),math.random(-66,-6)),
            model    = "Tyrian Remastered:Space Ice "..math.random(1,9),
            angle    = math.random(360)
         }
        )
    end
end
function MainMenu:drawBasis()
    background(5, 5, 238, 255)
    self.universe:draw()
    self.frame = (self.frame+1)%33
    if self.frame%300 == 0 then
        self:generateClouds(1)
    end
    for i,c in ipairs(self.clouds) do 
        c.position.y = c.position.y + 9
        if c.position.y > HEIGHT+66 then
            table.remove(self.clouds,i)
        else
            pushMatrix()
                tint(255, 255, 255, 168)
                --translate(c.position.x,c.position.y)
                --rotate(c.angle)
                sprite(c.model,c.position.x,c.position.y)
                noTint()
            popMatrix()
        end
    end
    font("Futura-Medium")
    fontSize(66)
    fill(255, 0, 0, 255)
    text("Speed Shooter Earth",WIDTH/2, HEIGHT-100)
end
function MainMenu:drawMainMenu()
    fontSize(66)
    fill(255)
    --font("Georgia-BoldItalic")
    text("PLAY", WIDTH/2,HEIGHT/2)
    text("CREDITS",WIDTH/2,(HEIGHT/2)-66)
    text("Highscore: "..highscore, WIDTH/2,66)
end
function MainMenu:drawPlaces()
    fontSize(33)
    fill(255)
    text("CHOOSE LOCATION",WIDTH/2,HEIGHT/1.5)
    for i,place in ipairs(self.places) do
        text(place.name, place.menupos.x,place.menupos.y)
        sprite(place.model, place.position.x,place.position.y,place.size.x,place.size.y)
    end
end
function MainMenu:drawShipSelection()
    fontSize(33)
    fill(255)
    text("Ship selection",WIDTH/2,HEIGHT/1.5)
    for i,ship in ipairs(self.ships) do
        text(ship.name, ship.menupos.x,ship.menupos.y)
        sprite(ship.model, ship.position.x,ship.position.y,ship.size.x,ship.size.y)
    end
end
function MainMenu:drawCredits()
    fontSize(55)
    fill(255)
    text("Coded by Juan Belón :: xixgames.com ", WIDTH/2,HEIGHT/2)
    text("Graphics by lostgarden.com ", WIDTH/2,HEIGHT/4)
end
function MainMenu:draw()
    self:drawBasis()
    if self.mode == "home" then
        self:drawMainMenu()
    elseif self.mode == "places" then
        self:drawPlaces()
    elseif self.mode == "ships" then
        self:drawShipSelection()
    elseif self.mode == "credits" then
        self:drawCredits()
    end
end
function MainMenu:createBodies()
    self.menuBodies = nil
    if self.mode == "home" then
        self.menuBodies = {
         play    = self:createBox(WIDTH/2,HEIGHT/2,333,33),
         credits = self:createBox(WIDTH/2,(HEIGHT/2)-66,333,33)
        }
    elseif self.mode == "places" then
        self.menuBodies = {
         Barajas = self:createBox(self.places[1].menupos.x,self.places[1].menupos.y,333,33),
         Sydney  = self:createBox(self.places[2].menupos.x,self.places[2].menupos.y,333,33),
         Dublin  = self:createBox(self.places[3].menupos.x,self.places[3].menupos.y,333,33),
        }
    elseif self.mode == "ships" then
        self.menuBodies = {
         A = self:createBox(self.ships[1].menupos.x,self.ships[1].menupos.y,333,33),
         B = self:createBox(self.ships[2].menupos.x,self.ships[2].menupos.y,333,33),
         C = self:createBox(self.ships[3].menupos.x,self.ships[3].menupos.y,333,33),
         D = self:createBox(self.ships[4].menupos.x,self.ships[4].menupos.y,333,33)
        }
    end
end
function MainMenu:createBox(x,y,w,h)
    -- polygons are defined by a series of points in counter-clockwise order
    local box = physics.body(POLYGON, 
        vec2(-w/2,h/2), vec2(-w/2,-h/2), 
        vec2(w/2,-h/2), vec2(w/2,h/2)
    )
    box.interpolate = true
    box.x = x
    box.y = y
    box.restitutions = 0.25
    box.sleepingAllowed = false
    box.type = STATIC
    return box
end
function MainMenu:touched(touch)
    if touch.state == ENDED then return nil end
    if self.menuBodies == nil then return end
    local tpoint = vec2(touch.x,touch.y)
    if self.mode == "home" then
        if self.menuBodies.play:testPoint(tpoint) then
            self.mode = "places"
            self:createBodies()
        elseif self.menuBodies.credits:testPoint(tpoint) then
            self.mode = "credits"
        end
    elseif self.mode == "places" then
        local place = nil
        if self.menuBodies.Barajas:testPoint(tpoint) then
            place = self.places[1]
        elseif self.menuBodies.Sydney:testPoint(tpoint) then
            place = self.places[2]
        elseif self.menuBodies.Dublin:testPoint(tpoint) then
            place = self.places[3]
        
        end
        if place~= nil then
            gpsLocation = place.gps
            gpsSpeed    = place.speed
            self.mode = "ships"
            self:createBodies()
        end  
    elseif self.mode == "ships" then
        local sm = ""
        if self.menuBodies.A:testPoint(tpoint) then
            sm = self.ships[1].model
        elseif self.menuBodies.B:testPoint(tpoint) then
            sm = self.ships[2].model
        elseif self.menuBodies.C:testPoint(tpoint) then
            sm = self.ships[3].model
        elseif self.menuBodies.D:testPoint(tpoint) then
            sm = self.ships[4].model
        end
        if sm ~= "" then
            shipModel = sm
            changeGameMode("Game")
            return
        end
    elseif self.mode == "credits" then
        self.mode = "home"
    end
    self.universe:generatePlasma()
end
Powerups = class()
-- Class PowerUps
-- Speed Shooting Earth
-- A freesource game project using Codea and Google Maps
-- More games: xixgames.com
-- by @juaxix
-- 6/6/2012
function Powerups:init()
    self.time  = 6
    self.units = {} -- enemy units
    self.size  = vec2(44,42)
end
function Powerups:generateRandomModel()
    local models = {
        "Tyrian Remastered:Powerup 7", --triple
        "Tyrian Remastered:Powerup 14", --vfire
        "Tyrian Remastered:Powerup 18", --double
        "Tyrian Remastered:Powerup 1", -- life
        "Tyrian Remastered:Powerup 23" -- points
    }
    local names = {
        "triple", "vfire", "double", "life", "points"
    }
    local r = math.random(1,#models)
    self.model = models[r]
    self.name  = names [r]
end
function Powerups:draw()
    self.time = self.time - 1/100
    
    -- Spawn random enemy every x frames
    if self.time <= 0 then
        self.time = 6
        self:generateRandomModel()
        spawn = { 
                  pos = vec2( math.random(WIDTH), HEIGHT + self.size.y),
                  mod = self.model.."", -- copy    
                  nam = self.name..""
                }
        table.insert( self.units, spawn )
      
    end
    noTint()
    for i,v in ipairs(self.units) do
        -- Move down
        v.pos.y = v.pos.y - 1    
        -- Cull unit
        culled = false
        if (v.pos.y + self.size.y) < 0 then
            table.remove(self.units, i)
            culled = true -- no continue statement
        end 
        -- Check if hit by player
        if culled == false then
            if world.ship~=nil then
                if world.ship.position:dist(v.pos) < self.size.x/2 then
                    table.remove(self.units, i)
                    world.ship:pickPowerUp(v.nam)
                    return
                end
            end
        end
        -- Draw unit
        sprite(v.mod, v.pos.x, v.pos.y,self.size.x,self.size.y)
    end
end
Scroller = class()
-- Scroller class
-- Speed Shooting Earth
-- A freesource game project using Codea and Google Maps
-- More games: xixgames.com
-- by @juaxix
-- 6/6/2012
function Scroller:init()
    self.bg1 = nil -- it's empty for now
    self.bg2 = nil
    self.turn= 1
    self.lim1= 195
    self.lim2= -777
    self.lat = gpsLocation.x -- initial latitude
    self.long= gpsLocation.y -- initial longitude
    self.stor= 1 -- img num, where to store
    -- Start the request
    http.get( 
        "http://maps.googleapis.com/maps/api/staticmap?"..
        "center="..self.lat..","..self.long.."&zoom=15&size="..
        WIDTH.."x".. (HEIGHT*2).."&maptype=satellite&sensor=true"
        , 
        didGetBg
    )
    self.animating = false
    self.position1 = vec2(WIDTH/2,HEIGHT/2)
    self.position2 = vec2(WIDTH/2,HEIGHT*2)
    
end
function Scroller:getNextBgImg(storeNumber)
    self.stor= storeNumber -- store in second image
    self.lat = self.lat + gpsSpeed
    http.get( 
        "http://maps.googleapis.com/maps/api/staticmap?"..
        "center="..self.lat..","..self.long.."&zoom=15&size="..
        WIDTH.."x".. (HEIGHT*2).."&maptype=satellite&sensor=true"
        , 
        didGetBg
    )
    if math.random(1,100)>66 then
        world.enemies.model = world.enemies:generateRandomModel()
        world.enemies.spawnPattern = ENEMY_SPAWN_HARD
    else
        world.enemies.spawnPattern = ENEMY_SPAWN_EASY
    end
end
function didGetBg( img, status, headers )
    local started = false
    --print( "Response Status: " .. status )
    if world.space.bg1~=nil then
        if world.space.stor == 1 then
            world.space.bg1 = img
        else
            world.space.bg2 = img
        end
        started = true
    else
        world.space.bg1 = img
    end
    -- Check if the status is OK (200)
    if status == 200 then
        --print( "Map Image dimensions: " ..  img.width .. "x" .. img.height ) 
        if not started then
            world:createWorld()
        end
    else
        print( "Error downloading map image!" )
    end
end
function Scroller:update()
    if self.animating then
        self.position1.y = self.position1.y - 3
        self.position2.y = self.position2.y - 3
        if self.turn == 1 then
            if math.floor(self.position1.y)==self.lim1 then
                self:getNextBgImg(2)
                self.position2.y = self.position1.y + (HEIGHT*2)
            elseif math.floor(self.position1.y)==self.lim2 then
                self.turn = 2
            end 
        elseif self.turn == 2 then
            if math.floor(self.position2.y) == self.lim1 then
                self:getNextBgImg(1)
                self.position1.y = self.position2.y+(HEIGHT*2)
            elseif math.floor(self.position2.y) == self.lim2 then
                self.turn = 1
            end
        end
    end
end
function Scroller:draw()
    self:update()
    if self.bg1 ~= nil then
        sprite(self.bg1,self.position1.x, self.position1.y, WIDTH ,HEIGHT*2)
        if self.bg2~=nil then
            sprite(self.bg2,self.position2.x, self.position2.y, WIDTH, HEIGHT*2)
        end
    else
        font("Verdana-BoldItalic")
        fontSize(66)
        fill(255)
        text("Loading...",WIDTH/2, HEIGHT/2)
    end
end
function Scroller:startScrolling()
    self.animatime = 6
    self.animating = true    
end
function Scroller:touched(touch)
    if touch.state == ENDED then
        print(self.position1.y)
    end
end
Ship = class()
-- Ship class
-- Speed Shooting Earth
-- A freesource game project using Codea and Google Maps
-- More games: xixgames.com
-- by @juaxix
-- 6/6/2012
function Ship:init(args)
    self.position = args.position
    self.type     = args.type
    self.model    = shipModel
    self.speed    = vec2(0,0)
    self.bullets  = {}
    self.frame    = 0
    self.fireType = "single"
    self.shipmodel= self.model.."" -- copy
    self.health   = 3
    self.damaged  = false
    self.alpha    = 200
end
function Ship:spawnBullet()
    sound(DATA, "ZgBAWghYBHg+HmRTTXT8PQFOQj4AAAAAKgAWfyMMJEsAFAMn")
    local vector = {
        position = vec2( self.position.x, self.position.y + 30 ),
        px       = 0,
        type     = self.fireType
    }
    if self.fireType == "vfire" then
        vector.px = vector.position.x
    end
    table.insert( self.bullets, vector )
end
function Ship:drawBullets()
    -- Spawn bullets
    if self.frame%30 == 0 then
        self:spawnBullet()
    end
    -- Move, draw, cull bullets
    for i,vector in ipairs(self.bullets) do
        local v = vector.position
        v.y = v.y + 3
        --ellipse(v.x, v.y, 10, 10)
        if vector.type == "single" then
            sprite("Tyrian Remastered:Bullet Fire C",v.x,v.y,9,12)
        elseif vector.type == "double" then
            sprite("Tyrian Remastered:Bullet Fire C",v.x-6,v.y,9,12)
            sprite("Tyrian Remastered:Bullet Fire C",v.x+6,v.y,9,12)
        elseif vector.type == "triple" then
            sprite("Tyrian Remastered:Bullet Fire C",v.x-6,v.y,9,12)
            sprite("Tyrian Remastered:Bullet Fire C",v.x+6,v.y,9,12)
            sprite("Tyrian Remastered:Bullet Fire C",v.x,v.y,9,12)
        elseif vector.type == "vfire" then
            v.x = v.x   + 1
            vector.px = vector.px - 1
            sprite("Tyrian Remastered:Bullet Fire C",v.x,v.y,9,12)
            sprite("Tyrian Remastered:Bullet Fire C",vector.px,v.y,9,12)
        else
            displayMode(STANDARD)
            print("fire mode: "..vector.type)
        end
        if v.y > (HEIGHT + 10) then
            table.remove(self.bullets,i)
        end 
    end
end
function Ship:takeDamage()
    if self.damaged then return end
    self.health = self.health - 1
    if self.health == 0 then
        world:shipDestroyed()
        sound(DATA, "ZgFAQABBNyIiak0FgsAuPgD4CT+w9GU+XAAtemtAPkBEDGI/")
    else
        sound(DATA, "ZgFAMABLF00/KXdZghhiv+gLcT+KoQk+XwBYaD9AIEtvR1I3")
    end
    self.damaged = true
end
function Ship:draw()
    self.frame = (self.frame + 1)%128
    self:drawBullets()
    if self.speed.x~=0 or self.speed.y~=0 then
        self.position = self.position + self.speed
        if self.position.x > WIDTH then
            self.position.x = 11
        elseif self.position.x<0 then
            self.position.x = WIDTH - 11
        end
        if self.position.y > HEIGHT then
            self.position.y = HEIGHT
        elseif self.position.y < 0 then
            self.position.y = 1
        end
    end
    if self.damaged then
        if (self.frame)%10000 == 0 then
            self.alpha   = 200
            self.damaged = false
        else
            if self.alpha > 0 then
                self.alpha = self.alpha - 3
            elseif self.alpha == 0 then
                self.alpha = 200
            end
            tint(255,255,255,self.alpha)
        end
    end
    sprite(self.shipmodel, self.position.x,self.position.y,40,54)
    noTint()
    for i=1 ,self.health do
        sprite("Planet Cute:Heart",WIDTH-(60*i) ,HEIGHT-23,50.5, 85.5)
    end
end
function Ship:touched(touch)
    local newspeed = vec2(0,0)
    local distance = 6
    if touch.state == ENDED then
        self.shipmodel = self.model..""
    else
        if touch.x<(self.position.x-10) then
            newspeed.x = -distance
            self.shipmodel = self.model.." L1"
        elseif touch.x>(self.position.x+10) then
            newspeed.x = distance
            self.shipmodel = self.model.." R1"
        end
    
        if touch.y > (self.position.y+50) then
            newspeed.y = distance
            
        elseif touch.y<(self.position.y-50) then
            newspeed.y = -distance
        end
    end
    self.speed = newspeed
end
function Ship:pickPowerUp(type)
    if type == "vfire" or type == "double" or type=="triple" then
        self:changeFireType(type)
    elseif type == "life" then
        if self.health<3 then
            self.health = self.health + 1
        end
    elseif type == "points" then
        world.score = world.score + 5000
    end
    sound(DATA, "ZgFA0gBYP0whCgdfav3IPsYZVj2YCAw/QgB/fjVAPmBAU0UQ")
    world.score = world.score + 50
end
function Ship:changeFireType(name)
    if self.fireType == name then return end
    self.fireType = name
end
Universe = class()
-- Plasma class
rnd = math.random    --I like short names 
------------------------------------
-- Generates a plasma image --------
-- and apply some filters ----------
-- A freesource game project using Codea and Google Maps
------------------------------------
function Universe:init()
    self.resolution = 1
    self.brightness = 0
    self.contrast   = 0
    self.effect     = 3
    
    
    self.contrastLookUpTable = {}    --Well, sometimes 
    self.palette = {}
    self:generatePalette()
end
function Universe:draw()
        --background(0, 0, 0, 255)
        if(self.oldRes ~= self.resolution) then
            self:generatePlasma()
            self.oldRes = self.resolution
        end
        self:filterImage(self.buffer, self.filterBuffer,
         self.brightness, self.contrast, self.bw)    --Apply filters
        sprite(self.filterBuffer, WIDTH * 0.5,HEIGHT * 0.5, WIDTH, HEIGHT)    --Show result
        --sprite(self.buffer, 100, 100, 200, 200)    --Show thumbnail with non filtered image
end
function Universe:touched(touch)
    if (CurrentTouch.state == BEGAN) then self:generatePlasma() end
end
------------------------------------
-- Filters Code --------------------
------------------------------------
function Universe:makeContrastLookUpTable(contrast)
    contrast = ((100 + contrast) / 100) ^ 2
    for n = 0, 255 do
        local v = n / 255
        v = v - .5
        v = v * contrast
        v = v + .5
        v = v * 255
        self.contrastLookUpTable[n] = v
    end
end
function Universe:filterImage(orig, dest, brightness, contrast, bw)
    local newColor
    self:makeContrastLookUpTable(contrast)
    for x = 1, orig.width do
        for y = 1, orig.height do
            local r, g, b = orig:get(x, y)
        --For each color component apply contrast and brightness, then clamp(0, 255)
            r = self.contrastLookUpTable[r] + brightness
            if(r < 0) then r = 0 end
            if(r > 255) then r = 255 end            
            g = self.contrastLookUpTable[g] + brightness
            if(g < 0) then g = 0 end
            if(g > 255) then g = 255 end
            b = self.contrastLookUpTable[b] + brightness
            if(b < 0) then b = 0 end
            if(b > 255) then b = 255 end
            if (self.effect == 0) then
                newColor = color(r, g, b)
            elseif (self.effect == 1) then    --Gray scale
                local c = r * .299 + g * .587 + b * .114
                newColor = color(c, c, c)
            elseif (self.effect == 2) then    --Negative
                newColor = color(255 - r, 255 - g, 255 - b)
            elseif (self.effect == 3) then    --Components shift 1
                newColor = color(b, r, g)
            elseif (self.effect == 4) then    --Components shift 2
                newColor = color(g, b, r)
            elseif (self.effect == 5) then    --Components shift 3
                newColor = color(g, r, b)
            end
            dest:set(x, y, newColor)    --Plot the result
        end
    end
end
------------------------------------
-- Plasma Generator Code -----------
------------------------------------
function Universe:generatePalette()
    local r, g, b
    local c = 0
    local inc = 1 / 400
    for e = 0, 400 do
        if (c < 0.5) then r = c * 2
        else r = (1 - c) * 2 end
        if (c >= 0.3 and c < 0.8) then g = (c - 0.3) * 2
        elseif (c < 0.3) then g = (0.3 - c) * 2
        else g = (1.3 - c) * 2 end
        if (c >= 0.5) then b = (c - 0.5) * 2
        else b = (0.5 - c) * 2 end
        self.palette[e] = color(r * 255, g * 255, b * 255)
        c = c + inc
    end
end
function Universe:generatePlasma()
    self.size = 64 * self.resolution  --Only powers of 2, otherwise we get gaps
    self.buffer = image(self.size, self.size)
    self.filterBuffer = image(self.size, self.size)
    --Start calculating with 4 random corners
    self:divideGrid (self.dest, 0, 0, self.size, rnd(), rnd(), rnd(), rnd())
end
function Universe:divideGrid(dest, x, y, lenght, c1, c2, c3, c4)
    local newLenght = lenght / 2
    if (lenght < 2) then --Keep calculating until size is less than 2
        self.buffer:set(x + 1, y + 1,
             self.palette[math.floor((c1 + c2 + c3 + c4) * 100)]) --Plot the point
    return end
    --Calculate the average of the 4 corners and add a random displacement 
    local middle = (c1 + c2 + c3 + c4) / 4 + (rnd() - 0.5) * newLenght * 3 / self.size
    --Calculate new edges
    local edge1 = (c1 + c2) / 2
    local edge2 = (c2 + c3) / 2
    local edge3 = (c3 + c4) / 2
    local edge4 = (c4 + c1) / 2
    --Clamp middle between 0 and 1
    if (middle < 0) then middle = 0
    elseif (middle > 1) then middle = 1 end
    --Recursevely call this function for each one of the 4 new rectangles
    self:divideGrid(dest, x, y, newLenght, c1, edge1, middle, edge4)
    self:divideGrid(dest, x + newLenght, y, newLenght, edge1, c2, edge2, middle)
    self:divideGrid(dest, x + newLenght, y + newLenght, newLenght, middle, edge2, c3, edge3)
    self:divideGrid(dest, x, y + newLenght, newLenght, edge4, middle, edge3, c4)
end
World = class()
-- World class
-- Speed Shooting Earth
-- A freesource game project using Codea and Google Maps
-- More games: xixgames.com
-- by @juaxix
-- 6/6/2012
function World:init()
    self.space   = Scroller()
    self.ship    = nil
    self.enemies = nil
    self.state   = "game"
    self.score   = 0
    self.frame   = 0
    self.score   = 0
end
function World:createWorld()
    self.ship = Ship(
     {
        position = vec2(WIDTH/2,33),
        type     = "light"
     }
    )
    self.enemies = EnemyHorde()
    self.enemies.heroBullets = self.ship.bullets
    self.space:startScrolling()
    self.explosion = nil
    self.powerups  = Powerups()
end
function World:drawGame()
    if self.ship ~= nil then 
        -- check ship collisions
        for i,v in ipairs(self.enemies.units) do
            if v.pos:dist(self.ship.position) < 30 then
                self.ship:takeDamage()
                -- Explode:
                table.insert(self.enemies.explosions, Explosion(v.pos))
                -- Remove enemy ship from list:
                table.remove(self.enemies.units,i)
                -- Update score
                self.score = self.score + 2000
                return
            end
        end
        self.ship:draw()
        self:drawScore()
    end
end
function World:drawCommon()
    self.space:draw()
    if self.enemies ~= nil then
        self.enemies:draw()
    end
    if self.explosion~=nil then
        self.explosion:draw()
    end
    if self.powerups ~= nil then
        self.powerups:draw()
    end
end
function World:draw()
    self:drawCommon()
    if self.state == "game" then
        self:drawGame()
    elseif self.state == "over" then
        self:drawGameOver()
    end
end
function World:drawScore()
    font("AcademyEngravedLetPlain")
    fontSize(60)
    fill(255)
    textMode(CORNER)
    text(self.score,21,HEIGHT-77)
    textMode(CENTER)
end
function World:drawGameOver()
    fontSize(155)
    font("HoeflerText-BlackItalic")
    fill(245, 3, 20, 255)
    text("GAME OVER",WIDTH/2,HEIGHT/2)
    self.frame = (self.frame + 1)
    if self.frame > 333 then
        changeGameMode("Menu")
    end
    
end
function World:shipDestroyed()
    self.state     = "over"
    self.explosion = Explosion(self.ship.position)
    self.ship      = nil
    self.frame     = 0
    if self.score > highscore then
        saveLocalData("highscore",self.score)
    end
end
function World:touched(touch)
    if self.ship~=nil then
        self.ship:touched(touch)
        self.space:touched(touch)
    end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment