Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Lockdown

edited March 28 in Code Sharing Posts: 1,840

Hi All
If you are anything like me, and probably are - wherever you are, you are either very busy fighting CVD19, ill with it or subject to Lockdown. So I am posting some incomplete code which I started a few months ago and shelved. It’s based on a 1K challenge to make a Space Invaders game up. I didn’t intend limiting it to 1K but I tried to use the principle by using emojis as an alternative to sprites.

Got the base system up and running, not cleaned up or optimised, and haven’t yet added the touch control interactions and scores - so I am hoping that you can fill those in. This is intended to give users a target, entertain/distract/frustrate them in a hope what is happening in the World for most of us can be put on hold for a while. If you do get anywhere with this please post with your ideas/problems so other users can learn from it. Also if anyone else has similar half finished projects - Now’s the time to share the work. Code below:


-- 1KSpaceInvaders displayMode(FULLSCREEN) function setup() W,H = WIDTH,HEIGHT N={5,5,5,5,5,5,5,5,5,5,5} S,B,V,D,I,O,P = W/24,350,0,300,1,0,0,0 buttons = {""} vaders = {{""}, {""}, {""}, {""} } bpos = vec2(350,160) x,y,bw,vh,mv = 350,W/24,S+44,980,12 blimL,blimR = 128,638 bmv = 8 blts = {x={},y={}} dark = fill(76, 37, 129, 255) ground = fill(118, 78, 37, 255) myMesh = mesh() myMesh.vertices = {vec2(0,1024),vec2(0,0),vec2(768,0),vec2(0,1024),vec2(768,0),vec2(768,1024)} myMesh.colors = {color(94, 22, 241, 255),color(60, 120, 38, 255),color(50,120,38,255), color(94,22,241,255),color(50,120,38,255), color(94,22,241,255)} end function draw() background(1, 132, 254, 255) -- S is image size, H is screen Height, W is screen Width -- P is -- V is -- I is -- O is myMesh:draw() y = H-S if I < 1 then O = O +.5 else O = O -.5 end if O > S then I = 1 P = P+S end if O < -S then I = 0 P = P+S end V = V-1 fontSize(84) fill(254, 254, 254, 255) pushMatrix() -- 160 text(buttons[1],40,100) text(buttons[3],726,100) text(buttons[2],bpos.x,bpos.y) noFill() strokeWidth(5) fill(240, 42, 65, 255) ellipse(720,240,80,80) fill(220, 228, 201, 31) strokeWidth(1) rect(84,72,600,40) popMatrix() -- D is -- i is column number -- j is row number -- B is -- N{} is if V < 0 then D = 1 end for i = 1,10 do for j = 1,4 do tmp = 2*i*S if B > tmp+O and B < tmp+S and V > tmp+P and V < tmp+P+S then if N[i] > j and D < 1 then D = 1 N[i] = N[i]-1 end end fontSize(54) fill(255, 255, 255, 255) for si =1,4 do for sv = 1,10 do if vaders[si][sv] > "-" then text(vaders[si][sv],sv*66+20+O,vh-si*64-P+S) end end end if N[i] > j then end end end strokeWidth(5) for f = 1, #blts do line(blts[f].x,blts[f].y+bmv,bmv,5,bmv) end end function touched(t) if t.state ~ ENDED then if t.y >= 60 and t.y <= 190 then -- print(t.x,t.y) bpos.x = t.x if bpos.x <= blimL then bpos.x = blimL elseif bpos.x >= blimR then bpos.x = blimR end elseif t.x >= 680 and t.y >= 200 and t.y <= 280 then -- print("fire") -- table.insert(blts,x=bpos.x,y=bpos.y+8) end else end end

p.s. the buttons and invaders have been removed as they can not be printed in the format. I have posted an image below and will post a little code later with the character codes for the aliens and buttons. I may try another approach with another image to achieve this.

Comments

  • edited April 14 Posts: 1

    Hi there,

    Space Invaders, nice! Thanks for the inspiration.

    I used this as a starting point to try to make a simple game and try out codea and lua.
    The structure is about the same.
    You can play with touch control but also with an external keyboard.

    -- Rocky Invaders
    -- very simple game for Codea
    
    function setup()
        --  showKeyboard() -- enable for keyboard to work
        displayMode(FULLSCREEN)
        spriteMode(RADIUS)
        block = (WIDTH - 100) / 12
        size_img = block/2 -- size_imgze images
        x_rock, y_rock, rocksDirection = 0, HEIGHT - 4 * block, 0
        x_ship, shipDirection = WIDTH/2, 0
        x_bullet, y_bullet = WIDTH/2, 0
        x_cloud, y_cloud = 0,0
        fired = 0
        as, clouds = {}, {}
        rocks = math.random(22,44)
        for i=1,rocks do as[i]={s=math.random(0,2),y=-100} end
        for i=1,100 do clouds[i]={s=math.random(0,1),y=-100} end
    
        --configure
        bulletSpeed = 15
        rocksSpeed = 0.35
        shipSpeed = 4
    end
    
    function draw()
        background(80, 50, 100)
    
        -- draw cloud bg
        for i = 1,#clouds do
            col = 1+(i % 13); row = 1+(i % 9)
            x = x_cloud + (col * block)
            y = y_cloud + (row * block)
            z = size_img/(y/1000)
            if (clouds[i].s == 1) then
                sprite(asset.builtin.Space_Art.Cloudy_Nebula,x,y,z,z)
            end
        end
        --calculate rocks movement
        if rocksDirection == 1 then
            x_rock = x_rock - rocksSpeed
            y_rock = y_rock - rocksSpeed/2
        else
            x_rock = x_rock + rocksSpeed
            y_rock = y_rock - rocksSpeed/2
        end
        -- change rocks direction and SFX
        if x_rock > size_img then
            rocksDirection = 1; y_rock = y_rock - block/10
            sound(SOUND_EXPLODE, 24800)
        end
        if x_rock < -size_img then
            rocksDirection = 0; y_rock = y_rock - block/10
            sound(SOUND_EXPLODE, 24800)
        end
        if math.ceil(x_rock)==0 then 
            sound(SOUND_PICKUP, 24845)
        end
    
        -- draw rocks
        for i = 1,rocks do
            col = 1.3+(i % 11); row = 1+(i % 4); even = i % 2
            x = x_rock + (col * block)
            y = y_rock + (row * block)
            if (even==0) then x = x + size_img/2 end
            -- hit something?
            if (x_bullet>x-size_img and x_bullet<x+size_img and
                y_bullet>y-size_img and y_bullet<y+size_img) and as[i].s < 2 then
                fired=0; y_bullet=0; as[i].s=as[i].s+1; as[i].y=y
                sprite(asset.builtin.Space_Art.Red_Explosion,x,as[i].y,size_img,size_img)
                sound(SOUND_EXPLODE, 36059)
                -- have we won
                if winner() then
                    sound(SOUND_POWERUP, 47448); restart()
                end
            end
            --change sprite when hit
            if (as[i].s==0) then
                sprite(asset.builtin.Space_Art.Asteroid_Large,x,y,size_img,size_img)
            elseif (as[i].s==1) then
                sprite(asset.builtin.Space_Art.Asteroid_Small,x,y,size_img/2,size_img/2)
                if (y < 150) then -- below this you die
                    sound(SOUND_EXPLODE, 36028);background(255);restart()
                end
            elseif (as[i].s > 1) then
                as[i].s = as[i].s+.1
                sprite(asset.builtin.Space_Art.Star,x-x_rock,as[i].y,size_img/as[i].s,size_img/as[i].s)
            end
        end
    
        --draw ship
        x_ship = x_ship + shipSpeed * shipDirection
        if (x_ship < size_img) then
            x_ship = size_img
        elseif (x_ship > WIDTH - size_img) then
            x_ship = WIDTH - size_img
        end
        sprite(asset.builtin.Space_Art.Red_Ship,x_ship,100,size_img,size_img)
    
        -- draw bullet
        if fired == 1 then
            y_bullet = y_bullet + bulletSpeed
            sprite(asset.builtin.Space_Art.Beam,x_bullet,y_bullet,10,size_img)
        end
        if (y_bullet > HEIGHT) then fired = 0 end
    
        function winner()
            for i=1,#as do
                if as[i].s < 2 then return false end
            end
            return true
        end
    
        function fire()
            if fired == 0 then
                sound(SOUND_HIT, 36708)
                x_bullet = x_ship; shipDirection = 0; y_bullet = 200; fired = 1
            end
        end
    
        --control
        function touched(touch)
            if touch.x < 140 then shipDirection = -1 end
            if touch.x > 140 and touch.x < 220 then shipDirection = 1 end
            if touch.state == BEGAN then
                if touch.x > WIDTH-140 then fire() end
            end
        end
    
        --control by keys (enable keyboard first in setup)
        function keyboard(key)
            if (key=="," or key=="<") then shipDirection = -1 end
            if (key=="." or key==">") then shipDirection = 1 end
            if (key==" ") then fire() end
        end
    
        fontSize(60);fill(255, 50)
        ellipse(100,300,80); ellipse(180,300,80); ellipse(WIDTH-100,300,80)
        text("‹", 100, 305); text("›", 180, 305); text("•", WIDTH-100, 300)
    
    end 
    
  • Posts: 1,840

    @Atopia - excellent, very neat game. I was begining to think no-one would contribute to this but your program is a good example. Tnnk I'll start to add a few exxtras on the one I started. Tanks.

  • Posts: 23

    Great stuff guys, I've zero game writing experience and just starting to dabble with Codea and using invaders type things to experiment with so this will be invaluable.

    Probably started too hard as going with voxels too and that is bending my head.

  • Posts: 1,840
    @RaggedTooth - your welcome. Don't hesitate to post queries, this is a great forum to help. I'd stick to non Craft until you have built up a basic understanding of Lua and Codea. It's a good package and easy to absorb.
  • Posts: 23

    @Bri_G Ha, I'm sure you're right, but I'm a glutton for punishment and will go a little way down the path, probably before seeing sense and coming back with my tail between my legs...

    I think it's fun trying!

  • dave1707dave1707 Mod
    edited April 15 Posts: 8,625

    Here’s a space invaders version that I had. Tilt the iPad left or right to move the ship. Tap the screen to shoot. Play in portrait orientation for more room up/down. Each time you shoot all the enemy players, the game will restart at a faster pace. If the enemy reaches near the bottom, the game restarts starting with the slow speed. There isn’t much to this, so don’t expect much.

    displayMode(FULLSCREEN)
    
    function setup()
        v=10
        limit=30
        setup1()
    end
    
    function setup1()
        v=10
        mis={}
        h=HEIGHT-50
        w=0
        tab={}
        for z=1,60 do
            tab[z]=0
        end
        delay=0
        limit=limit-3
        gx=WIDTH/2
    end
    
    function draw()
        background(40, 40, 50)    
        drawEnemy()
        checkDelay()
        moveShip()
        checkHit()
        checkEnemy()
        removeMis()
    end
    
    function touched(t)
        if t.state==BEGAN then
            gy=200
            table.insert(mis,vec2(gx,gy))
        end
    end
    
    function drawEnemy()
        cnt=0
        for x=1,12 do
            for y=1,5 do
                cnt=cnt+1
                if tab[cnt]==0 then
                    sprite(asset.builtin.Space_Art.Part_Gray_Hull_4,x*60-30+w,h-y*40,20)
                    if h-y*40<250 then
                        setup()
                    end
                end
            end
        end
    end
    
    function checkDelay()
        delay=delay+1
        if delay>limit then
            if w>105 or w<0 then
                v=-v
                h=h-30
            end
            w=w+v
            delay=0
            sound(SOUND_SHOOT, 30208)
        end
    end
    
    function moveShip()
        sprite(asset.builtin.Space_Art.Red_Ship,gx,200)
        gx=gx+Gravity.x*20
    end
    
    function checkHit()
        for a,b in pairs(mis) do
            b.y=b.y+10
            sprite(asset.builtin.Space_Art.Red_Explosion,b.x,b.y,20)
            cnt=0
            for x=1,12 do
                for y=1,5 do
                    cnt=cnt+1
                    xp=x*60-30+w
                    yp=h-y*40
                    if b.x>xp-10 and b.x<xp+10 and b.y>yp-10 and b.y<yp+10 then
                        if tab[cnt]==0 then
                            tab[cnt]=1
                            table.remove(mis,a)
                            sound(SOUND_HIT, 30217)
                        end
                    end
                end
            end
        end
    end
    
    function checkEnemy()
        cnt=0
        for z=1,#tab do
            if tab[z]==1 then
                cnt=cnt+1
            end
            if cnt==60 then
                setup1()
                return            
            end
        end
    end
    
    function removeMis()
        for z=#mis,1,-1 do
            if mis[z].y>HEIGHT+100 then
                table.remove(mis,z)
            end
        end
    end
    
  • Posts: 1,840

    @dave1707 - sorry I’ve been slow to reply to this, family matters!! This is a very neat and concise code, keeps all the features needed despite it’s size. Must admit I tend not to think of the gyroscope for controlling movement but it works well here. Now in my useful demos list. Thanks for that.

  • edited April 28 Posts: 1,840

    Hi All,

    Thanks for the contributions here, didn’t get the progressive development I hoped for here but thanks for your posts. I’ve decided to post a project which is almost finished, just needs a little tidying - something I started years ago got to work then messed up and shelved. Largely fixed, grandkids love it. You have all probably seen this especially at Christmas. When I finished was going to offer to 2LL as a finished demo. Here it is in bits, I have posted some of the sprites to get it working.

    Here is the main tab:


    --# Main function setup() -- load resources init() end function draw() -- set up the background and fixed sprites spriteMode(CENTER) sprite(back,cW,cH,sW,sH) sprite(absent,sW-200,200,96) sprite(present,200,200,chW,chH) sprite(absent,568,200,chW,chH) font("Georgia-bold") fontSize(84) fill(130, 39, 59) text("MAGIC NUMBER",cW-4,sH-124) fill(252, 91, 8) text("MAGIC NUMBER",cW,sH-120) -- display number cards stationary or in motion for lp =1,#card do if sorted < 5 then if card[lp].pos.y < 100 then card[lp].pos.y = 100 end if card[lp].pos.y > 710 then card[lp].pos.y = 710 end if card[lp].vis == true then adjust = 0 sprite(card[lp].pic,card[lp].pos.x,card[lp].pos.y,card[lp].size) end end end if sorted == 5 then -- show result and repeat or exit pushMatrix() strokeWidth(3) stroke(0,0,0,255) fill(255,255,255,255) rect(cW-90,116,180,136) fill(0,0,0,255) fontSize(18) text("your number is: ", cW, 220) fill(0,0,0,fade) fontSize(72) font("Georgia-bold") text(total,cW,170) if fade > 254 then fade = 255 else fade = fade + 1 end if fade > 254 then sprite(reStart,cW,cH) end popMatrix() end end function touched(touch) -- touch routine where all the magic is done local x,y = touch.x,touch.y if touch.state == BEGAN then check = checkInside(touch.pos) elseif touch.state == MOVING and check > 0 then card[check].pos = vec2(x+touch.deltaX,y+touch.deltaY) card[check].size = card[check].size+touch.deltaY/10 elseif touch.state == ENDED then if check > 0 then card[check].pos = vec2(cLoc*check,cHeight) card[check].size = cSize for cp = 1,2 do test1 = math.abs(CurrentTouch.y - chest[cp].pos.y) if test1 < 60 then test2 = math.abs(CurrentTouch.x - chest[cp].pos.x) if test2 < 60 and cp == 1 then print("test1 : "..check,cp,test1,test2) if card[check].vis == true then total = total + card[check].value sorted = sorted + 1 end card[check].vis = false elseif test2 < 60 and cp == 2 then print("test2 : "..check,cp,test1,test2) sorted = sorted + 1 card[check].vis = false end test1, test2 = 0,0 end end else if sorted == 5 then sprite(reStart,cW,cH) if CurrentTouch.x > cW-resW/2 and CurrentTouch.x < cW+resW/2 and CurrentTouch.y > cH-resH/2 and CurrentTouch.y < cH+resH/2 then check = 0 init() end end end end end

    Here is the utils/resources code:


    --# Utils function init() -- sW,sH,cW,cH = WIDTH, HEIGHT, WIDTH/2, HEIGHT/2 cLoc = WIDTH//6 cHeight = 700 cSize = 124 card = {} chest = {} total = 0 sorted = 0 fade = 0 check = 0 more = false panel1 = readImage(asset.documents.Dropbox.magicno.panel1) panel2 = readImage(asset.documents.Dropbox.magicno.panel2) panel3 = readImage(asset.documents.Dropbox.magicno.panel4) panel4 = readImage(asset.documents.Dropbox.magicno.panel8) panel5 = readImage(asset.documents.Dropbox.magicno.panel16) reStart = readImage(asset.documents.Dropbox.magicno.restart) resW,resH = spriteSize(reStart) mystic = readImage(asset.documents.Dropbox.magicno.mystic) back = readImage(asset.builtin.Cargo_Bot.Game_Area) present = readImage(asset.documents.Dropbox.magicno.Present) absent = readImage(asset.documents.Dropbox.magicno.Absent) chW,chH = spriteSize(present) card[1] = cards(1,1,panel1,vec2(cLoc,cHeight),true,cSize) card[2] = cards(2,2,panel2,vec2(cLoc*2,cHeight),true,cSize) card[3] = cards(3,4,panel3,vec2(cLoc*3,cHeight),true,cSize) card[4] = cards(4,8,panel4,vec2(cLoc*4,cHeight),true,cSize) card[5] = cards(5,16,panel5,vec2(cLoc*5,cHeight),true,cSize) chest[1] = chests(1,present,vec2(200,200),96) chest[2] = chests(2,absent,vec2(560,200),96) end function checkInside(ct) -- for lp = 1,#card do if ct.x > card[lp].bl.x and ct.x < card[lp].tr.x then if ct.y > card[lp].bl.y and ct.y < card[lp].tr.y then return math.floor((ct.x+60)/cLoc) else return 0 end end end end

    Finally here are the classes involved:


    --# CardClass cards = class() function cards:init(id,val,px,pos,vis,size) -- self.cardID = id self.value = val self.pic = px self.pos = pos self.vis = vis or true self.size = size half = size/2 self.bl = vec2(self.pos.x-half,self.pos.y-half) self.tr = vec2(self.pos.x+half,self.pos.y+half) end function cards:draw() -- local lp for lp = 1,5 do sprite(self.pic,self.pos.x,self.pos.y,self.size) end end --# ChestClass chests = class() function chests:init(id,pic,pos,size) -- self.id = id self.pos = pos self.pic = pic self.size = size local half = math.floor(size/2) self.cbl = vec2(self.pos.x-half,self.pos.y-half) self.ctr = vec2(self.pos.x+half,self.pos.y+half) end

    I am sure many of you will be able to suggest refinements, simplifications, bug fixes!!! All would be welcome.

  • edited April 28 Posts: 1,840

    Hi All,

    Finally images of how it should look, and my own setup for it.

    Oh, for all who have not seen this you have to select a number between 1 and 32 then drag the cards which contain that number to the present chest, and the other to the absent chest. Then your iPad will tell you which number you chose.

    I’m looking at increasing the cards to six and selecting number for 1 to 64.

    Any issues - just post em.

    Edit: A little bit of colour helps, see attached pics. Your main edits will be to set up the path links to the graphic sprites either in the text form “Dropbox:..panel1” or with the asset.path list method asset.documents.Dropbox. .. panel1 or similar.

  • Posts: 1,840

    All - just been fiddling with @Jarc ’s loader and thinking about text size/colour display to make formatting in it easier? Came up with this - needs a little more polishing to make it generally applicable but - here it is:


    function setup() -- sW,sH,cW,cH = WIDTH,HEIGHT,WIDTH/2,HEIGHT/2 -- a few thought provoking ideas story = {} table.insert(story,"Red is my favourite colour") table.insert(story,"My knee hurts") table.insert(story,"Always look on the bright side of life") table.insert(story,"A Song of Ice and Fire") table.insert(story,"Books can be dangerous") table.insert(story,"Stars can't shine without darkness") table.insert(story,"I can, I will, end of story") table.insert(story,"A smooth sea never made a skillful sailor") table.insert(story,"Take the risk or lose the chance") table.insert(story,"Don't stop until your proud") table.insert(story,"Never make permanent decisions on temporary feelings") table.insert(story,"The eyes are useless when the mind is blind") -- cycling the font colour fs = 40 colours = { color(234, 22, 10), color(234, 138, 10), color(234, 232, 10), color(135, 255, 0), color(0, 255, 156), color(10, 228, 234), color(0, 122, 255), color(10, 24, 234), color(125, 10, 234), color(210, 10, 234), color(234, 10, 133), color(211, 162, 209), color(234, 22, 10), color(183, 62, 72), color(112, 206, 145) } end function draw() -- background(0) textMode(CENTER) font("Georgia") for lp = 1,#story do fontSize(sW*2/string.len(story[lp])) fill(colours[lp]) text(story[lp],cW,sH-lp*80) end end

    Anyone any ideas on pushing this further?

Sign In or Register to comment.