Follow the arrow starter game

Messing about with using iPad rotation as a game input mechanism.

Turn the iPad to follow the direction of the arrow. No end of game conditions yet, just for fun.


-- Only support one orientation so you can tilt a lot
--used the gravity example as a starter for 10
--turn the ipad to follow the arrow
--by West
displayMode(FULLSCREEN)
supportedOrientations(CurrentOrientation)

-- Use this function to perform your initial setup
function setup()
    
    targetangle=math.random(360)
    newtargetangle=targetangle
    trackcounter=0
    star={}
    for i=1,100 do
        table.insert(star,{x=math.random(1200),y=math.random(1200),s=3+math.random(8),a=math.random(360),fade=100+math.random(155)})
    end
    spd=0.3
    
    arrow=image(100,200)
    setContext(arrow)
    local pts={
    vec2(30,0),
    vec2(30,100),
    vec2(0,100),
    vec2(50,200),
    vec2(100,100),
    vec2(70,100),
    vec2(70,0)
    
    }
    local  m=mesh()
    m.vertices=triangulate(pts)
    m:setColors(0,255,0)
    m:draw()
    setContext()
    
    ship=image(100,100)
    setContext(ship)
    local pts={
    vec2(10,0),
    vec2(50,100),
    vec2(90,0),
    vec2(60,10),
    vec2(40,10)
    
    }
    local  m=mesh()
    m.vertices=triangulate(pts)
    m:setColors(255,0,0)
    m:draw()
    setContext()
    
    thrust=image(10,10)
    setContext(thrust)
    local pts={
    vec2(10,0),
    vec2(10,10),
    vec2(0,10)
    
    }
    local  m=mesh()
    m.vertices=triangulate(pts)
    m:setColors(255,255,255)
    m:draw()
    setContext()
    
    singlestar=image(10,10)
    setContext(singlestar)
    local pts={
    vec2(5,0),
    vec2(4,4),
    vec2(0,5),
    vec2(4,6),
    vec2(5,10),
    vec2(6,6),
    vec2(10,5),
    vec2(6,4)
    }
    local  m=mesh()
    m.vertices=triangulate(pts)
    m:setColors(255,255,255)
    m:draw()
    setContext()
    particles={}
    fontSize(40)
    font("Copperplate-Bold")
end

-- This function gets called once every frame
function draw()
    background(55, 31, 75, 255)
    --draw the starfield
    for i,s in pairs(star) do
        s.y = s.y + s.s*spd
        if s.y>1200 then s.y=-100 end
        pushMatrix()
        translate(WIDTH/2, HEIGHT/2)
        rotate(-targetangle)
        translate(s.x,s.y)
        translate(-WIDTH/2, -HEIGHT/2)
        tint(255,255,255,s.fade)
        sprite(singlestar,0,0,s.s)
        noTint()
        popMatrix()
    end
    --draw current thrust particles
    for i,p in pairs(particles) do
        p.x = p.x + p.spd*math.cos(p.a)
        p.y = p.y + p.spd*math.sin(p.a)
        pushMatrix()
        translate(p.x,p.y)
        rotate(p.spin)
        tint(p.col.r,p.col.g,p.col.b,p.fade)
        sprite(thrust,0,0,p.size,p.size)
        noTint()
        popMatrix()
        p.fade = p.fade - 3
        if p.fade<0 then
            p.active=0
        end
    end
    grav = vec2(Gravity.x * 300, Gravity.y * 300)
    down = vec2(1, 0)
    orient = down:angleBetween(grav)
    --target arrow
    pushMatrix()
    translate(WIDTH/2, HEIGHT/2)
    targ = vec2(300*math.sin(math.rad(targetangle)), 300*math.cos(math.rad(targetangle)))
    diff = math.abs(math.deg(targ:angleBetween(grav)))
    d=255*((180-diff)/180)
    pushMatrix()
    resetMatrix()
    translate(WIDTH/2, HEIGHT/2)
    translate(-targ.x*0.75, -targ.y*0.75)
    rotate(-targetangle)
    rotate(-180)    
    tint(trackcounter*2,155+trackcounter,trackcounter*2,d)
    sprite(arrow,0,0,150,150)
    noTint()
    popMatrix()
    popMatrix()
    --check to see if ship and target arrow align
    if diff<5 then
        trackcounter = trackcounter + 1
        --add a thrust particle
        local r=100+math.random(155)
        local g=math.min(r,math.random(255))
        table.insert(particles,{x=WIDTH/2,y=HEIGHT/2,a=orient-math.rad(3)+math.rad(math.random(70)/10),fade=255,size=7+math.random(8),spd=5*math.random(50)/10,active=1,spin=math.random(360),col=color(r,g,0)})
        spd=spd+0.0005
    else
        spd = spd - 0.0005
        if spd<0.3 then spd=0.3 end
    end
    --if the target has been tracked for 100 instances then calculate a new position
    if trackcounter>100 then
        trackcounter=0
        newtargetangle=math.random(360)
        spd = spd + 0.1
    end
    --move arrowtowards then new target
    if targetangle<newtargetangle-1 then
        targetangle = targetangle + 1
    elseif targetangle>newtargetangle+1 then
        targetangle = targetangle - 1
    else
        targetangle=newtargetangle
    end
    --draw the ship and the speed marker
    pushMatrix()
    translate(WIDTH/2,HEIGHT/2)
    rotate(math.deg(orient)+90)
    sprite(ship,0,0)
    fill(255)
    local spdtxt=math.floor(spd*100)
    text(spdtxt,0,350)
    popMatrix()
    --clean up particles
    for i=#particles,1,-1 do
        if particles[i].active==0 then
            table.remove(particles,i)
        end
    end
end


@West Interesting. Maybe after so many points, you can start subtract points when the arrow isn’t following the first one. Game over when points is 0.

Yeah, it currently slows down when you don’t follow the arrow. That sounds like a good idea

wonderful?very creative and addictive?i almost drop and break ipad while playing

Added a bit more in terms of visuals and the aim to reach hyperspeed!

http://youtu.be/rddEtZV4-e4

Now with sound. Can you reach hyperspeed?


-- Only support one orientation so you can tilt a lot
--used the gravity example as a starter for 10
--turn the ipad to follow the arrow
--by West
displayMode(FULLSCREEN)
supportedOrientations(CurrentOrientation)

-- Use this function to perform your initial setup
function setup()
    hyperspeed=0
    targetangle=math.random(360)
    newtargetangle=targetangle
    trackcounter=0
    star={}
    for i=1,100 do
        table.insert(star,{x=math.random(1200),y=math.random(1200),s=3+math.random(8),a=math.random(360),fade=100+math.random(155)})
    end
    spd=1.0
    
    arrow=image(100,200)
    setContext(arrow)
    local pts={
    vec2(30,0),
    vec2(30,100),
    vec2(0,100),
    vec2(50,200),
    vec2(100,100),
    vec2(70,100),
    vec2(70,0)
    }
    local  m=mesh()
    local cols={}
    m.vertices=triangulate(pts)
    for i=1,#m.vertices do
        if m.vertices[i].y==0 then
            table.insert(cols,color(0,255,0,25))
        else
            table.insert(cols,color(0,255,0,255))
        end
    end
    m.colors=cols
    --   m:setColors(0,255,0)
    m:draw()
    setContext()
    
    ship=image(100,100)
    setContext(ship)
    local pts={
    vec2(10,0),
    vec2(50,100),
    vec2(90,0),
    vec2(60,10),
    vec2(40,10)
    
    }
    local  m=mesh()
    local cols={}
    m.vertices=triangulate(pts)
    for i=1,#m.vertices do
        if m.vertices[i].y<1 then
            table.insert(cols,color(255,0,0,125))
        else
            table.insert(cols,color(255,0,0,255))
        end
    end
    m.colors=cols
    --   m:setColors(255,0,0)
    m:draw()
    setContext()
    
    thrust=image(10,10)
    setContext(thrust)
    local pts={
    vec2(10,0),
    vec2(10,10),
    vec2(0,10)
    
    }
    local  m=mesh()
    m.vertices=triangulate(pts)
    m:setColors(255,255,255)
    m:draw()
    setContext()
    
    singlestar=image(10,10)
    setContext(singlestar)
    local pts={
    vec2(5,0),
    vec2(4,4),
    vec2(0,5),
    vec2(4,6),
    vec2(5,10),
    vec2(6,6),
    vec2(10,5),
    vec2(6,4)
    }
    local  m=mesh()
    m.vertices=triangulate(pts)
    m:setColors(255,255,255)
    m:draw()
    setContext()
    
    tail=image(10,10)
    setContext(tail)
    local pts={
    vec2(0,10),
    vec2(5,0),
    vec2(10,10)
    }
    local cols={
    
    color(255, 0, 0, 0),
    color(255, 0, 0, 255),
    color(255, 0, 0, 255)
    }
    local  m=mesh()
    m.vertices=triangulate(pts)
    m.colors=cols
    m:draw()
    setContext()
    
    particles={}
    fontSize(40)
    font("Copperplate-Bold")
    soundcount=0
end

-- This function gets called once every frame
function draw()
    background(68-math.floor(spd*10), 28, 138-math.floor(spd*20), 255)
    
    grav = vec2(Gravity.x * 300, Gravity.y * 300)
    down = vec2(1, 0)
    orient = down:angleBetween(grav)
    
    if spd>5 and hyperspeed==0 then
        hyperspeed=1
    end
    --draw current thrust particles
    for i,p in pairs(particles) do
        p.x = p.x + p.spd*math.cos(p.a)
        p.y = p.y + p.spd*math.sin(p.a)
        pushMatrix()
        translate(p.x,p.y)
        rotate(p.spin)
        tint(p.col.r,p.col.g,p.col.b,p.fade)
        sprite(thrust,0,0,p.size,p.size)
        noTint()
        popMatrix()
        p.fade = p.fade - 3
        if p.fade<0 then
            p.active=0
        end
    end
    
        soundcount = soundcount + 1    
    if hyperspeed==0 then

        if spd~=0 then
        if soundcount>50/spd then
                local v=0.5+spd/10
          sound("Game Sounds One:Menu Back",v,v,1.0)

            soundcount=0
        end
        end
        --draw the starfield
        for i,s in pairs(star) do
            s.y = s.y + s.s*spd
            if s.y>1200 then s.y=-100 end
            pushMatrix()
            translate(WIDTH/2, HEIGHT/2)
            rotate(-targetangle)
            translate(s.x,s.y)
            translate(-WIDTH/2, -HEIGHT/2)
            tint(255,255,255,s.fade)
            sprite(singlestar,0,0,s.s)
            noTint()
            popMatrix()
        end
        
        
        
        --target arrow
        pushMatrix()
        translate(WIDTH/2, HEIGHT/2)
        targ = vec2(300*math.sin(math.rad(targetangle)), 300*math.cos(math.rad(targetangle)))
        diff = math.abs(math.deg(targ:angleBetween(grav)))
        d=255*((180-diff)/180)
        pushMatrix()
        resetMatrix()
        translate(WIDTH/2, HEIGHT/2)
        translate(-targ.x*0.75, -targ.y*0.75)
        rotate(-targetangle)
        rotate(-180)
        tint(trackcounter*2,155+trackcounter,trackcounter*2,d)
        sprite(arrow,0,0,150,150)
        noTint()
        popMatrix()
        popMatrix()
        --check to see if ship and target arrow align
        if diff<5 then
            trackcounter = trackcounter + 1
            --add a thrust particle
            local r=150+math.random(105)
            local g=math.min(r,math.random(255))
            table.insert(particles,{x=WIDTH/2,y=HEIGHT/2,a=orient-math.rad(3)+math.rad(math.random(70)/10),fade=255,size=7+math.random(8),spd=5*math.random(50)/10,active=1,spin=math.random(360),col=color(r,g,0)})
            --       spd=spd+0.005
            spd=spd+0.002
        else
            spd = spd - 0.001
            if spd<0 then spd=0 end
        end
        --if the target has been tracked for 100 instances then calculate a new position
        if trackcounter>100 then
            trackcounter=0
            newtargetangle=math.random(360)
            spd = spd + 0.02
            for j=1,21 do
                table.insert(particles,{x=WIDTH/2,y=HEIGHT/2,a=orient+math.rad(-10+j),fade=255,size=7+math.random(8),spd=5*math.random(50)/10,active=1,spin=math.random(360),col=color(255,255,255)})
            end
        end
        --move arrowtowards then new target
        if targetangle<newtargetangle-1 then
            targetangle = targetangle + 1
        elseif targetangle>newtargetangle+1 then
            targetangle = targetangle - 1
        else
            targetangle=newtargetangle
        end
        --draw the ship and the speed marker
        pushMatrix()
        translate(WIDTH/2,HEIGHT/2)
        rotate(math.deg(orient)+90)
        local xadj=0
        local yadj=0
        if spd>2 then
            
            xadj=-spd-1+math.random(math.floor(2*spd))
            yadj=-spd-1+math.random(math.floor(2*spd))
            
            
            
        end
        sprite(ship,xadj,yadj)
        if spd>0 and diff<7 then
            tint(255,255,255,math.random(255))
            spriteMode(CORNER)
            sprite(tail,-39+xadj,-49+yadj-100*spd,2,100*spd)
            sprite(tail,37+xadj,-49+yadj-100*spd,2,100*spd)
            spriteMode(CENTER)
            noTint()
        end
        fill(255)
        local spdtxt=math.floor(spd*100)
        text(spdtxt,0,350)
        popMatrix()
        
    elseif hyperspeed<20 then
        --hyperspace
        hyperspeed = hyperspeed + 1
        for j=1,359,10 do
            table.insert(particles,{x=WIDTH/2,y=HEIGHT/2,a=orient+math.rad(-10+j),fade=255,size=7+math.random(8),spd=5*math.random(50)/10,active=1,spin=math.random(360),col=color(255,0,0)})
        end
        if hyperspeed==3 then
            sound("Game Sounds One:Explode Big")
        end
    else
        hyperspeed = hyperspeed + 1
        fontSize(100)
        fill(255,math.min(255,hyperspeed))
        pushMatrix()
        translate(WIDTH/2,HEIGHT/2)
        rotate(math.deg(orient)+90)
        text("HYPERSPEED!",0,0)
        popMatrix()
    end
    
    --clean up particles
    for i=#particles,1,-1 do
        if particles[i].active==0 then
            table.remove(particles,i)
        end
        
    end
end


@Redvelvet this is something that grew out of the built in Gravity example. I took the basic approach and used one of the in built sprites rather than the arrow. I then looked to see if I could add a goal (a target angle to meet) and added that in, at first playing a sound when I reached the desired angle (which was hard coded) then adding the function to reset the target angle to something new after it had been met. I got the basic functionality working the added the “pretty” effects afterwards.

To understand vec2 and push/pop matrix read the instructions, have a look at @Ignatz book and mess about with simple examples. Below is a very early example of the above which just looks at the ship movement and is based very heavily on the Gravity example.


-- Only support one orientation so you can tilt a lot
--used the gravity example as a starter for 10
--turn the ipad to follow the arrow
--by West
displayMode(FULLSCREEN)
supportedOrientations(CurrentOrientation)

-- Use this function to perform your initial setup
function setup()
    
--small rotine for creating a ship sprite
    --[[
    ship=image(100,100)
    setContext(ship)
    local pts={
    vec2(10,0),
    vec2(50,100),
    vec2(90,0),
    vec2(60,10),
    vec2(40,10)

    }
    local  m=mesh()
    m.vertices=triangulate(pts)
    m:setColors(255,0,0)
    m:draw()
    setContext()
    ]]--
--substitute for one of the stock images
    ship=readImage("Space Art:Part Gray Hull 1")

end

-- This function gets called once every frame
function draw()
    background(55, 31, 75, 255)
    grav = vec2(Gravity.x * 300, Gravity.y * 300)
    down = vec2(1, 0)
    orient = down:angleBetween(grav)
    --draw the ship and the speed marker
    pushMatrix()
    translate(WIDTH/2,HEIGHT/2)
    rotate(math.deg(orient)+90)
    sprite(ship,0,0)
    fill(255)
    popMatrix()
end


As a beginner, I think it’s a great, simple game! But could you give me a shirt explanation of the steps you went through to code a game like this? I still don’t understand what all the “vec” and the “pushMatrix” stand for…

@Redvelvet - you will need more than a short explanation to understand all that, as I found when I learned Codea.

I’ve written up what I learned in an ebook on Codea, here. I’ve also written about vectors here

nice little game, @West, playing to the strengths of the iPad

Wow, thanks for the early version @West , the game looks so much easier to understand. I’ll check out @Ignatz 's book, thanks you all for the tips!