Simple lemmings type game

Re-visited a stripped down version of lemmings after learning about clip() from a recent @Ignatz post
Only implemented bombers, floaters and diggers and constraining to using the built in assets with Codea.

Let’s Go!

http://youtu.be/GAD7kNTI3r0

--simple lemmings clone with bombers, floaters and diggers
--by West
displayMode(FULLSCREEN)
function setup()
    FALL=1
    WALK=2
    DOWNDIG=3
    FLOAT=4
    img=image(WIDTH,HEIGHT)
    bg1=CreateLandscape(WIDTH,HEIGHT/6,color(255,122,6),50)
    bg2=CreateLandscape(WIDTH,HEIGHT/6,color(55,122,60),80)
    setContext(img)
    background(0)
    sprite(bg1,WIDTH/2,HEIGHT/4)
    sprite(bg2,WIDTH/2,HEIGHT/2)
    fill(40, 118, 35, 255)
    rect(0,5*HEIGHT/12,300,200)
    setContext()
    manimg={}
    manimg[1]=readImage("Platformer Art:Guy Standing")
    manimg[2]=readImage("Platformer Art:Guy Look Right")
    manimg[3]=readImage("Platformer Art:Guy Standing")
    manimg[4]=readImage("Platformer Art:Guy Standing")
    man={}
    particles={}
    startx=150
    starty=650
    endx=850
    endy=220
    release=300
    saved=0
    
    minFPS=60
    buttons={}
    numbuttons=4
    butimg=readImage("Tyrian Remastered:Ring")
    for i=1,numbuttons do
        table.insert(buttons,{x=200+(i-0.5)*(WIDTH-400)/numbuttons,y=HEIGHT-50,sel=0,img=butimg})
    end
    buttons[1].img=readImage("Tyrian Remastered:Explosion Huge")
    buttons[2].img=readImage("Tyrian Remastered:Drill")
    buttons[3].img=readImage("Platformer Art:Cloud 1")
    buttons[4].img=readImage("Platformer Art:Mushroom")
end

function draw()
    sprite(img,WIDTH/2,HEIGHT/2)
    releaseMen()
    drawMen()
    drawParticles()
    sprite("Cargo Bot:Crate Yellow 1",startx,starty,40,40)
    sprite("Small World:Flag",endx,endy,30,40)
    drawMenu()
    fps()
end

function drawMenu()
    for i,b in pairs(buttons) do
        if b.sel==1 then
            sprite("Cargo Bot:Crate Goal Yellow",b.x,b.y,75,75)
        else
            sprite("Cargo Bot:Crate Goal Blue",b.x,b.y,75,75)
        end
        sprite(b.img,b.x,b.y,30,30)
    end
end

function fps()
    --borrowed from @Ignatz
    FPS=(FPS or 60)*0.9+0.1/DeltaTime
    minFPS=math.min(minFPS,FPS)
    fontSize(14)
    text("FPS "..math.floor(FPS),WIDTH-100,HEIGHT-30)
    text("min FPS "..math.floor(minFPS),WIDTH-100,HEIGHT-50)
    text("Saved "..saved,100,HEIGHT-30)
end

function releaseMen()
    release = release + 1
    if release>200 then
        table.insert(man,{x=startx,y=starty,f=1,fuse=0,state=FALL,a=0,adir=1,action=0,fall=0,floater=0})
        release=0
    end
end

function drawMen()
    fill(255)
    noStroke()
    noSmooth()
    for i,p in pairs(man) do
        if p.fuse>0 then
            tint(255,255-p.fuse,255-p.fuse)
            p.fuse = p.fuse + 2
            if p.fuse>254 then
                explode(p.x,p.y+5)
                p.fuse=0
                table.remove(man,i)
                sound("Game Sounds One:Pop 2")
            end
        end
        pushMatrix()
        translate(p.x,p.y+7)
        rotate(p.a)
        sprite(manimg[p.state],0,0,p.f*65/5,92/5)
        popMatrix()
        noTint()
    end
    
    for i,p in pairs(man) do
        if p.y>1 and p.x>1 and p.x<WIDTH-1 then
            if p.x==endx-7 and math.abs(p.y-endy)<30 then
                saved = saved + 1
                table.remove(man,i)
                sound("Game Sounds One:Female Cheer 2")
            end
            local r,g,b,a=img:get(p.x,p.y)
            local rl,gl,bl,al=img:get(p.x-1,p.y+1)
            local s=r+g+b
            local sl=rl+gl+bl
            if s==0 then
                if p.floater==1 then
                    if p.state~=FLOAT then
                        p.a=0
                    end
                    p.state=FLOAT
                    p.fall=0
                else
                    p.state=FALL
                    p.fall = p.fall + 1
                end
                local rb,gb,bb,ab=img:get(p.x,p.y-1)
                if rb+gb+bb==0 then
                    if p.state==FALL then
                        p.y = p.y - 2
                        p.a = p.a - p.f*3
                    else
                        p.y = p.y -1
                        p.a = p.a + p.adir
                        if p.a>30 or p.a<-30 then
                            p.adir = p.adir * -1
                        end
                    end
                else
                    p.y = p.y -1
                end
            elseif p.state==DOWNDIG then
                --have a delay between digging actions
                p.action = p.action + 1
                if p.action>10 then
                    p.y = p.y - 1
                    downdig(p.x,p.y)
                    p.action=0
                    sound("Game Sounds One:Kick")
                end
            else
                if p.fall>100 then
                    splut(p.x,p.y)
                    table.remove(man,i)
                    sound("A Hero's Quest:Drink 1")
                end
                p.fall=0
                p.state=2
                p.a=0
                local rs,gs,bs,as=img:get(p.x+1*p.f,p.y+5)
                local rr,gr,br,ar=img:get(p.x+1*p.f,p.y+1)
                local ss=rs+gs+bs
                local sr=rr+gr+br
                if ss==0 then
                    p.x = p.x + 1*p.f
                    if sr~=0 then
                        p.y = p.y + 1
                    end
                else
                    p.f = p.f * -1
                end
            end
        end
        if p.x>WIDTH-3 or p.x<3 then
            p.f = p.f * -1
            p.x = p.x + 1*p.f
        end
    end
end

function drawParticles()
    for i,p in pairs(particles) do
        tint(p.r,p.g,p.b,p.fade)
        sprite("Cargo Bot:Star",p.x,p.y,3)
        p.x=p.x+p.spd*math.sin(math.rad(p.a))
        p.y=p.y+p.spd*math.cos(math.rad(p.a))
        p.y = p.y - p.grav
        p.grav = p.grav + 1
        noTint()
        p.fade = p.fade - 5
        if p.fade<0 then
            table.remove(particles,i)
        end
    end
end

function touched(t)
    if t.state==ENDED then
        if t.y>HEIGHT-100 then
            for i,b in pairs(buttons) do
                b.sel=0
                if math.abs(t.x-b.x)<75/2 then
                    b.sel=1
                    if i==4 then
                        --armageddon
                        for i,p in pairs(man) do
                            p.fuse=1
                        end
                    end
                end
            end
        else
            for i,p in pairs(man) do
                if vec2(p.x,p.y):dist(vec2(t.x,t.y))<20 and p.fuse==0 then
                    if buttons[1].sel==1 then
                        p.fuse=1
                    elseif buttons[2].sel==1 then
                        p.state=DOWNDIG
                    elseif buttons[3].sel==1 then
                        p.floater=1
                    end
                end
            end
        end
    end
    
    --for destroying scenery
    --[[
    if t.state==ENDED or t.state==MOVING then
    setContext(img)
    clip(t.x-10,t.y-10,21,21)
    fill(0)
    ellipse(t.x,t.y,20)
    clip()
    setContext()
end
    ]]--
end

function explode(ex,ey)
    setContext(img)
    clip(ex-20,ey-20,41,41)
    fill(0)
    ellipse(ex,ey,40)
    clip()
    setContext()
    for i=0,360,10 do
        table.insert(particles,{x=ex,y=ey,a=i,spd=10+math.random(10),fade=255,r=math.random(255),g=math.random(255),b=math.random(255),grav=0})
    end
end

function splut(ex,ey)
    for i=-90,90,5 do
        table.insert(particles,{x=ex,y=ey,a=i,spd=5+math.random(5),fade=255,r=math.random(255),g=math.random(255),b=math.random(255),grav=0})
    end
end

function downdig(ex,ey)
    setContext(img)
    clip(ex-10,ey,21,5)
    fill(0)
    rect(ex-10,ey,21,5)
    clip()
    setContext()
end

--code from @Ignatz for mountain generation
--x,y is start tile; ww,hh are width and height of landscape
--in tiles; c is colour, rr is roughness of landscape (I used rr=2)
function CreateLandscape(w,h,c,r)
    --create blank image and draw landscape
    local i=image(w,h)
    setContext(i)
    strokeWidth(1)
    stroke(c)
    --use a random number to make the results slightly different
    --each time, by adding it to the x value we provide
    local z=math.random()
    --draw a series of vertical lines. pixel by pixel
    for c=1,w do
        local a=h-r+r*noise(z+c/200)
        line(c,1,c,a)
    end
    --add in a vertical wall obstacle
    rect(200+math.random(WIDTH-400),0,10,600)
    setContext()
    return i
end

just needs the music, lol

I loved that game :x

Me too! So much character contained in those tiny sprites!

excellent?cute and interesting game

You need the right animation though

Yes, I’ve looked at that before :wink: There’s also a public domain version - Lix
http://asdfasdf.ethz.ch/~simon/sprites.php

I’ve also had a couple of runs at doing the images myself from scratch with mixed results

http://youtu.be/Ipv5-pg8r9s
http://youtu.be/6kRJMM0DPhg

Now with all the original skills implemented - code available here

https://gist.github.com/Westenburg/58fe562ebee3db4ef562

http://youtu.be/h89P-3YXv4s

I like the donkeykong version and the pipemania version :slight_smile: