Lua chopter

Just a game to add as a bonus in the physics game

http://www.youtube.com/watch?v=q480i0kVX5c

Code:

--# Main

-- theCave
widthRatio = 1
heightRatio= 1
displayMode(FULLSCREEN)
-- Use this function to perform your initial setup
function setup()
   cave   = Cave()
   paused = false
   winner = false
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(0)

    -- This sets the line thickness
    strokeWidth(5)

    -- Do your drawing here
    cave:draw()
end

function touched(touch)
    cave:touched(touch)
end

--# CavePlayer
CavePlayer = class()

function CavePlayer:init()
    self.position    = vec2(166*widthRatio, HEIGHT/2)
    self.linearSpeed = vec2(1000,1000) -- trick for the engine  
    self.img         = readImage("SpaceCute:Rocketship") 
    self.sx          = 66*widthRatio
    self.sy          = 66*heightRatio
    self.speed       = 0.02
    self.accel       = 0.01
    self.gravity     = 0.2
    self.motor       = 0.8
end

function CavePlayer:move()
    self.position.y = self.position.y - self.speed
    self.speed      = self.speed + self.accel + self.gravity
    
    if self.position.y <  0 then
        self.position.y = 0
        self.speed      = 0
    end
    
    if self.position.y > HEIGHT then
        self.position.y = HEIGHT
        self.speed      = -0.1*self.speed
    end
end

function CavePlayer:draw()
    if not paused and not winner then
        self:move()
    end
    pushMatrix()
        translate(self.position.x,self.position.y)
       -- rotate(self.angle)
        local angle = -self.speed*5
         if angle > 90 then
            angle = 90
         end
         if angle < -90 then
            angle = -90
         end
        rotate(angle)
        sprite(self.img, 0,0, self.sx, self.sy)
    popMatrix()
end

function CavePlayer:touched(touch)
    if touch.state == BEGAN or touch.state == MOVING then
        self.accel = -self.motor
    elseif touch.state == ENDED then
        self.accel = self.gravity
    end
end

function CavePlayer:destroy()
    -- trick
end

--# Explosion 

Explosion = class()
function Explosion:init(_position, power,r,g,b)
    -- you can accept and set parameters here
    self.duration = 0.6
    self.currentTime = 0
    self.endTime = self.currentTime + self.duration
    self.size = math.random(6,123)
    self.blastSize = self.size + power*6
    self.currentSize = self.size
    self.position = _position
    self.R = r
    self.G = g
    self.B = b
end
 
function Explosion:isDone()
    return self.currentTime > self.endTime*2
end
 
function Explosion:draw()
    self.currentTime = self.currentTime + 1/30
    
    -- Time in the attack, 0 to 1
    glowTime = (self.currentTime)/self.duration
 
    pushStyle()
    
    noFill()
    stroke(self.R, self.G, self.B, 255*(1-glowTime))
    strokeWidth(10*(1-glowTime))
    
    self.currentSize = self.blastSize * glowTime + (self.size * (1-glowTime))
    p = self.position
    ellipse(p.x, p.y, self.currentSize)
    
    popStyle()
end

--# Cave
------ THE CAVE
Cave = class()
function Cave:init()
    self.ball     = CavePlayer()
    self.borders  = {}
    self.obstacles= {}
    self.speed    = 6
    self.frame    = 0
    self.fmod     = math.fmod -- efficience issues
    self.sin      = math.sin
    self.ospeed   = 120 -- obstacles speed
    self.score    = 0
    self.bscore   = readLocalData("cave_score",0)
end

function Cave:createObstacle()
    local last = self.borders[#self.borders-1]
    local obstacle = vec2( WIDTH, 0)
    if last then
        obstacle.x = last.x
        obstacle.y = math.random(last.y+77, HEIGHT-last.y-77)
        obstacle.y = math.min ( 
            obstacle.y, 
            HEIGHT - last.y - 77*2
        )
        obstacle.y = math.max (
            obstacle.y, 
            last.y + 77*2
        )
    end
    
    table.insert(self.obstacles, obstacle)
end


function Cave:createBorder()
    local last   = self.borders[#self.borders-1]
    if last and last.x>WIDTH+100 then return end
    local border = vec2( WIDTH/2,
      (HEIGHT/3)/2 - self.sin(ElapsedTime)*25 - 77
    )
    if last then
        border.x = last.x + 77*widthRatio
    end
    
    table.insert(self.borders, border)
end

function Cave:pointInsideRect(x,y,sx,sy,tx,ty)
    local sx = math.floor(sx/2)
    local sy = math.floor(sy/2)
    return 
     tx>= (x-sx) and tx<=(x+sx) and
     ty<= (y+sy) and ty>=(y-sy)
end

function Cave:update()
    self.frame = self.frame + 1
    if self.fmod(self.frame, self.speed/3)==0 then
        self:createBorder()
        self.score = self.score + 1
    end
    if self.fmod(self.frame, self.ospeed)==0 then
        self:createObstacle()
    end
    local dMin = 1000
    for i,o in ipairs(self.obstacles) do
        o.x = o.x - self.speed 
        if o.x < -77 then
            table.remove(self.obstacles, i)
        else
            local d = o:dist(self.ball.position)
            if dMin > d then dMin = d end
        end
    end
    
    local df = 77*widthRatio
    local px = self.ball.position.x
    local py = self.ball.position.y
    for i,w in ipairs(self.borders) do
        w.x = w.x - self.speed
        if w.x<-df then
            table.remove(self.borders, i)     
        elseif 
            self:pointInsideRect(w.x,w.y,df,df*2,px,py) or
            self:pointInsideRect(w.x,HEIGHT - w.y,df,df*2,px,py)
        then
            dMin = 0
            
        end
    end
    
    return math.floor(dMin)
end

function Cave:drawBorders()
    if not paused and not winner then
        local d = self:update()
        if d <78 then 
            winner = true
            self.explosion = Explosion(self.ball.position, 60, 200,11,11)
            if self.score > self.bscore then
                self.bscore = self.score 
                saveLocalData("cave_score", self.score)
            end
        end   
        fill(43, 77, 226, 255)
        text("Score:"..self.score, 166, 166)
        text("Best:"..self.bscore, WIDTH-166, 166)
        
    elseif winner then
        text("Score:".. self.score..". Press restart", WIDTH/2, HEIGHT/2)
    end
    fill(60, 235, 30, 255)
    noStroke()
    rectMode(CENTER)
    for i,w in ipairs(self.borders) do 
        rect(w.x,w.y,77*widthRatio, w.y*2)
        rect(w.x,HEIGHT-w.y,77*widthRatio, w.y*2)
    end
    
    for i,o in ipairs(self.obstacles) do
        rect(o.x, o.y, 77, 77*2)
    end
end
function Cave:draw()
    self:drawBorders()
    self.ball:draw()
    if self.explosion then
      if self.explosion:isDone() then
           self.explosion = nil
      else
           self.explosion:draw()
      end
    end
end

function Cave:touched(touch)
    self.ball:touched(touch)
end

Nice job.

Badlands and Pong got married and had a baby…
Cool

nice @juaxix

Added an explosion from my first game with Codea (2011) :slight_smile:

Actually, it looks more like a marriage between Scramble and Choplifter. Which isn’t a bad thing at all.

Any idea why i get a black screen!? Ipad 1 - created new project and pasted the code in…

uhm, maybe you have to put files in another order, try to copy paste in a single tab

@akiva sure i have an idea!
Try this: https://gist.github.com/JMV38/6015514
And let me know the result

@Jvm38 – the fix runs and says finished
@juaxix – if I paste in a single tab I get the same error I mention below

Tried it – now I get an error message in Cave:

Line 133

Function arguments expected near ’

What is your line 133?

in Cave:draw()

self:explosion.draw()

should be self.explosion:draw()
:slight_smile:

that works. Thanks

Really nice – I lowered the movement sensitivity a bit. (Changed 0.01 to 0.005)

On question: How are you checking collision detection? the ship can overlap with obstacles a noticeable amount before it counts as a collision.

it takes the size of the ship, you may need to adjust size in x and y in cavePlayer , self.sx, self.sy, the same for the obstacles, it just check if a point is inside a rectangle