Craft game. Ship and walls.

I took one on my Craft games and modified it slightly. The previous game was to destroy the green and yellow balls while avoiding the red balls. The object of this game it to fly thru each green ball to destroy it. Sounds easy, but for each green ball you destroy, a wall is create at a random position and length. So the more balls you destroy, the more walls you need to avoid. If you haven’t played my previous Craft game, hold the iPad like a steering wheel and tilt it right or left to fly the ship. You have 5 ships to try and destroy the 100 green balls. Odds are you won’t get them all because I’m sure some walls will be created over a green ball. Have fun trying. This is a stripped down version so it hasn’t been tested too well.

PS. Made some changes to sounds.
PS. Added code for low score.

Update version below

neat, thanks!

Nice! What about a map in the corner?

@West I was thinking about that early on. But then if you knew where the balls were and where they were going you wouldn’t fly around searching for them. The purpose I want is more of a search and destroy feeling. I want you to weave in and out of the walls and force you down dead ends.

@dave1707 - moved on with this game, the walls, fuel display and map add a neat touch to it.

Made more changes. I added a Menu screen that allows you to turn off the Fuel Level and Wall Map. You can also choose your Speed from slow to fast or reset the Low Score. I like playing without the Fuel Level or Wall Map just so I can zip around the screen chasing the green balls and avoiding the walls. The code got too big to post as text, so I had to zip it.

Made more changes. In this version, I added an option to let you fly. When selected, you can fly above the game area to get a birds eye view or avoid the walls. To turn flying on, tap the button in the menu. This also comes with limits. To hit a green ball, you have to fly at an altitude of .5 to 1.5. To avoid walls, fly above 4. If you’re below .5, you’ll hear a low altitude warning. If you fly at 0, you crash into the ground. Your altitude shows on the ship above the green ball count. I keep telling myself that I’m not going to add more, but then I think of something else that sounds fun.

PS. Flying is controlled by the forward, backward tilt of the iPad. Before you start the actual game, hold the iPad at a comfortable position. Once the game starts, tilt the iPad towards you to go up, away from you to go down. While playing, you can tap the screen to reset the forward/backward origin position.

@West Maybe I can do a map that shows just the ship and the walls. That way you still won’t know where the balls are and you’ll have to search for them.

Here’s another version. I added a fuel gauge. As you fly around, you use fuel. Each green ball you hit, you get some fuel back. Each ship comes with a full tank, so when you crash into a wall, the new ship has a full tank. When you run out of fuel, you get the same response as running into a wall. The other thing I added was at @West suggestion. There is a map in the upper right corner that shows the position of the ship and the walls. If you look at the map, you might be able to avoid dead end walls. I didn’t add the balls to the map because I want you to search for them. I haven’t tried this on a larger screen iPad, so I’m not sure how it all looks. Maybe I’ll do that next.

displayMode(FULLSCREEN)

function setup()
    sound(SOUND_PICKUP, 11696)
    assert(craft, "Please include Craft as a dependency")
    setup1()
end

function setup1() 
    pct=1
    maxSpeed=.5
    count=100
    ships=4
    parameter.action("reset low score",resetLowScore)
    youWon,hitWall,youLost=false,false,false
    greenBalls=0
    hgx=Gravity.x

    speed,ey,ang=0,45,0
    cameraX,cameraZ=-205,-205

    scene = craft.scene()
    scene.camera.position = vec3(cameraX,0,cameraZ)
    scene.camera.eulerAngles=vec3(ex,ey,ez)
    scene.sun.rotation = quat.eulerAngles(45,0,45)
    scene.ambientColor = color(90,90,90)

    skyMaterial = scene.sky.material
    skyMaterial.horizon = color(0, 203, 255, 255)    

    tab={}
    for z=1,count do    -- green
        xx=math.random(-10,10)/200
        zz=math.random(-10,10)/200
        if xx==0 and zz==0 then
            xx=.1
            zz=.1
        end
        createSphere(math.random(-200,200),math.random(-200,200),.5,0,255,0,xx,zz)
        greenBalls=greenBalls+1
    end

    mtl = craft.material(asset.builtin.Materials.Standard)
    img = readImage(asset.builtin.Surfaces.Basic_Bricks_AO)

    createFloor()
    wallTab={}
    outsideWall(0,210,420,2)
    outsideWall(210,0,2,420)
    outsideWall(0,-210,420,2)
    outsideWall(-210,0,2,420)
    lowScore=readProjectData("Low_Score",count)
end

function update(dt)
    scene:update(dt)
    scene.camera.position = vec3(cameraX,1,cameraZ)
    scene.camera.eulerAngles=vec3(0,ey,0)
end

function draw()
    background(0)
    if youLost then
        youLostFunc()
    elseif hitWall then
        hitWallFunc()
    elseif youWon then
        youWonFunc()
    else  
        update(DeltaTime)
        scene:draw()  
        if paused then  
            text("PAUSED",WIDTH/2,HEIGHT*.7)
            text("Triple tap to restart.",WIDTH/2,HEIGHT*.7-20)
        else
            text("Triple tap to pause.",WIDTH/2,HEIGHT-10)
            text("Low Score  "..string.format("%d",lowScore),80,HEIGHT-60)
            updateCameraPos()        
            checkCollisions()
            checkTilt()  
            drawShip()
            drawShipLevels()
            drawFuelLevel()
            drawMap()
        end
    end
end

function drawMap()
    fill(255)
    strokeWidth(1)
    rect(WIDTH-220,HEIGHT-220,210,210)
    fill(255,0,0)
    ellipse(WIDTH-10-(cameraX+210)/2,(cameraZ+210)/2+HEIGHT-220,8)
    stroke(0)
    strokeWidth(1)
    for a,b in pairs(wallTab) do
        xPos=b.x+210
        yPos=b.y+210
        xLen=b.z/2
        if xLen==1 then
            xLen=0
        end
        yLen=b.w/2
        if yLen==1 then
            yLen=0
        end
        line(WIDTH-10-(xPos-xLen)/2,(yPos-yLen)/2+HEIGHT-220,
                WIDTH-10-(xPos+xLen)/2,(yPos+yLen)/2+HEIGHT-220)
    end
end

function touched(t)
    if t.state==BEGAN then
        if t.tapCount==3 then
            ang=0
            paused=not paused
        end
        if t.tapCount==2 then
            if youWon then
                setup1()
            elseif youLost then
                setup1()
            elseif hitWall then
                hitWall=false
                hgx=Gravity.x
                cameraX,cameraZ=-205,-205
                ships=ships-1
                speed,ey,ang=0,45,0
                pct=1
            end
        else
            ang=0
            if speed==0 then
                speed=maxSpeed
            end
        end
    end
end

function youLostFunc()
    fill(255,0,0)
    text("YOU LOST!",WIDTH/2,HEIGHT/2+150)
    text("Balls left "..greenBalls,WIDTH/2,HEIGHT/2+100)
    text("Low score   "..string.format("%d",lowScore),WIDTH/2,HEIGHT/2+50)
    text("Hold the ipad level then",WIDTH/2,HEIGHT/2)
    text("Double tap the screen to play again.",WIDTH/2,HEIGHT/2-50)
end

function hitWallFunc()
    sprite(asset.builtin.Tyrian_Remastered.Explosion_Huge,WIDTH/2,HEIGHT/2,500,500)
    fill(255,0,0)
    text("Hold the ipad level then",WIDTH/2,HEIGHT/2+50)
    text("Double tap the screen to continue.",WIDTH/2,HEIGHT/2)
end

function youWonFunc()
    fill(255,0,0)
    text("YOU WON!",WIDTH/2,HEIGHT/2+100)
    text("Hold the ipad level then",WIDTH/2,HEIGHT/2+50)
    text("Double tap the screen to play again.",WIDTH/2,HEIGHT/2)
end

function drawShipLevels()
    for z=1,ships do
        sprite(asset.builtin.Tyrian_Remastered.Boss_A,z*50,HEIGHT-30,40)
    end
end

function drawFuelLevel()
    if speed>0 then
        pct=pct-.0002
    end
    fill(255)
    rect(20,HEIGHT/2+100,20,200)
    if pct<.1 then
        fill(255, 0, 0)
    elseif pct<.25 then
        fill(255, 255, 0)
    else
        fill(0,255,0)
    end
    rect(20,HEIGHT/2+100,20,200*pct)
    fill(0, 0, 255)
    text(string.format("%3.1f",pct*100),30,HEIGHT/2+90)
    if pct<=0 then
        hitWall=true
    end
end

function updateCameraPos()
    ey=ey-ang
    x=speed*math.sin(math.rad(ey))
    z=speed*math.cos(math.rad(ey)) 
    cameraX=cameraX+x
    cameraZ=cameraZ+z
end

function checkCollisions()
    for a,b in pairs(tab) do    -- green balls
        if cameraX>b.ent.position.x-b.size and 
                cameraX<b.ent.position.x+b.size and
                cameraZ>b.ent.position.z-b.size and 
                cameraZ<b.ent.position.z+b.size then
            b.ent:destroy()
            table.remove(tab,a)
            count=count-1
            sound(SOUND_HIT, 19423)
            greenBalls=greenBalls-1
            createWall()
            if pct<1 then
                pct=pct+.02
            end
            if greenBalls<lowScore then
                lowScore=greenBalls
                saveProjectData("Low_Score",greenBalls)
            end
        end
    end
    for a,b in pairs(wallTab) do    -- walls
        if cameraX>b.x-(b.z)/2 and cameraX<b.x+(b.z)/2 and 
                cameraZ>b.y-(b.w)/2 and cameraZ<b.y+(b.w)/2 then
            if ships==0 then
                sound(SOUND_POWERUP, 20465)
                youLost=true
            else
                sound(SOUND_EXPLODE, 20445)
                hitWall=true
            end
        end
    end
    if greenBalls==0 then
        youWon=true
    end
    if speed==0 then
        text("Tap screen to start.",WIDTH/2,HEIGHT*.75)
    end
    
    if count<50 then
        for a,b in pairs(tab) do
            xx=b.ent.position.x
            zz=b.ent.position.z
            xx=xx+b.xv
            zz=zz+b.zv
            if xx<-200 or xx>200 then
                b.xv=-b.xv
            end
            if zz<-200 or zz>200 then
                b.zv=-b.zv
            end
            b.ent.position=vec3(xx,1,zz)
        end
    end
end

function resetLowScore()
    clearLocalData()
    lowScore=count
end

function checkTilt()
    gx=Gravity.x
    ang=ang+(gx-hgx)*4
    hgx=gx
    if gx>-.001 and gx<.001 then
        ang=0
    end
end

function drawShip()
    pushMatrix()
    translate(WIDTH/2,HEIGHT/2-100)
    rotate(ang*-30)
    sprite(asset.builtin.Tyrian_Remastered.Boss_A,0,0,300)
    fill(0,255,0)
    text(greenBalls,0,0)
    translate()
    popMatrix()
end

function createFloor(x,z)
    c1=scene:entity()
    c1.model = craft.model.cube(vec3(400,1,400))
    c1.position=vec3(x,-.5,z)
    c1.material = craft.material(asset.builtin.Materials.Standard)
    c1.material.map = readImage(asset.builtin.Surfaces.Desert_Cliff_Color)
    c1.material.offsetRepeat=vec4(0,0,50,50)
end

function createSphere(x,z,size,r,g,b,xv,zv)
    sphere1=scene:entity()
    sphere1.model = craft.model.icosphere(size,1)
    sphere1.position=vec3(x,1,z)
    sphere1.material = craft.material(asset.builtin.Materials.Specular)
    sphere1.material.diffuse=color(r,g,b)
    table.insert(tab,{ent=sphere1,xv=xv,zv=zv,size=size})
end

function createWall()
    local c1=scene:entity()
    local xPos=math.random(-175,175)
    local zPos=math.random(-175,175)
    local xSize=50
    local zSize=2
    if math.random(100)<51 then
        xSize=2
        zSize=50
    end
    c1.material=mtl
    c1.material.map=img
    c1.model=craft.model.cube(vec3(xSize,4,zSize))
    c1.position=vec3(xPos,2,zPos)
    table.insert(wallTab,vec4(xPos,zPos,xSize,zSize))
end

function outsideWall(xp,zp,xs,zs)
    local c2=scene:entity()
    local xPos=xp
    local zPos=zp
    local xSize=xs
    local zSize=zs
    c2.material=mtl
    c2.material.map=img
    c2.model=craft.model.cube(vec3(xSize,4,zSize))
    c2.position=vec3(xPos,2,zPos)
    table.insert(wallTab,vec4(xPos,zPos,xSize,zSize))
end

Made more changes. There is now a wall surrounding the games area so you can’t go zooming off into space and coming back in. There is a buffer area so you have a little room off the edges. Also, I changed the way the green ball move. Instead of choosing if you want them to move or not, they are stationary until you destroy 50 of them. The last 50 will move. That way you’ll have a chance at any balls inside or too close to a wall. If you have any suggestions, let me know and if it’s doable, I’ll give it a try.

displayMode(FULLSCREEN)

function setup()
    sound(SOUND_PICKUP, 11696)
    assert(craft, "Please include Craft as a dependency")
    setup1()
end

function setup1() 
    maxSpeed=.5
    count=100
    ships=4
    parameter.action("reset low score",resetLowScore)
    youWon,hitWall,youLost=false,false,false
    greenBalls=0
    hgx=Gravity.x

    speed,ey,ang=0,45,0
    cameraX,cameraZ=-205,-205

    scene = craft.scene()
    scene.camera.position = vec3(cameraX,0,cameraZ)
    scene.camera.eulerAngles=vec3(ex,ey,ez)
    scene.sun.rotation = quat.eulerAngles(45,0,45)
    scene.ambientColor = color(90,90,90)

    skyMaterial = scene.sky.material
    skyMaterial.horizon = color(0, 203, 255, 255)    

    tab={}
    for z=1,count do    -- green
        xx=math.random(-10,10)/200
        zz=math.random(-10,10)/200
        if xx==0 and zz==0 then
            xx=.1
            zz=.1
        end
        createSphere(math.random(-200,200),math.random(-200,200),.5,0,255,0,xx,zz)
        greenBalls=greenBalls+1
    end

    mtl = craft.material(asset.builtin.Materials.Standard)
    img = readImage(asset.builtin.Surfaces.Basic_Bricks_AO)

    createFloor()
    wallTab={}
    outsideWall(0,210,420,2)
    outsideWall(210,0,2,420)
    outsideWall(0,-210,420,2)
    outsideWall(-210,0,2,420)
    lowScore=readProjectData("Low_Score",count)
end

function update(dt)
    scene:update(dt)
    scene.camera.position = vec3(cameraX,1,cameraZ)
    scene.camera.eulerAngles=vec3(0,ey,0)
end

function draw()
    background(0)
    if youLost then
        youLostFunc()
    elseif hitWall then
        hitWallFunc()
    elseif youWon then
        youWonFunc()
    else  
        update(DeltaTime)
        scene:draw()  
        if paused then  
            text("PAUSED",WIDTH/2,HEIGHT*.7)
            text("Triple tap to restart.",WIDTH/2,HEIGHT*.7-20)
        else
            text("Triple tap to pause.",WIDTH/2,HEIGHT-10)
            text("Low Score  "..string.format("%d",lowScore),80,HEIGHT-60)
            updateCameraPos()        
            checkCollisions()
            checkTilt()  
            drawShip()
            drawShipLevels()
        end
    end
end

function touched(t)
    if t.state==BEGAN then
        if t.tapCount==3 then
            ang=0
            paused=not paused
        end
        if t.tapCount==2 then
            if youWon then
                setup1()
            elseif youLost then
                setup1()
            elseif hitWall then
                hitWall=false
                hgx=Gravity.x
                cameraX,cameraZ=-205,-205
                ships=ships-1
                speed,ey,ang=0,45,0
            end
        else
            ang=0
            if speed==0 then
                speed=maxSpeed
            end
        end
    end
end

function youLostFunc()
    fill(255,0,0)
    text("YOU LOST!",WIDTH/2,HEIGHT/2+150)
    text("Balls left "..greenBalls,WIDTH/2,HEIGHT/2+100)
    text("Low score   "..string.format("%d",lowScore),WIDTH/2,HEIGHT/2+50)
    text("Hold the ipad level then",WIDTH/2,HEIGHT/2)
    text("Double tap the screen to play again.",WIDTH/2,HEIGHT/2-50)
end

function hitWallFunc()
    sprite(asset.builtin.Tyrian_Remastered.Explosion_Huge,WIDTH/2,HEIGHT/2,500,500)
    fill(255,0,0)
    text("Hold the ipad level then",WIDTH/2,HEIGHT/2+50)
    text("Double tap the screen to continue.",WIDTH/2,HEIGHT/2)
end

function youWonFunc()
    fill(255,0,0)
    text("YOU WON!",WIDTH/2,HEIGHT/2+100)
    text("Hold the ipad level then",WIDTH/2,HEIGHT/2+50)
    text("Double tap the screen to play again.",WIDTH/2,HEIGHT/2)
end

function drawShipLevels()
    for z=1,ships do
        sprite(asset.builtin.Tyrian_Remastered.Boss_A,z*50,HEIGHT-30,40)
    end
end

function updateCameraPos()
    ey=ey-ang
    x=speed*math.sin(math.rad(ey))
    z=speed*math.cos(math.rad(ey)) 
    cameraX=cameraX+x
    cameraZ=cameraZ+z
end

function checkCollisions()
    for a,b in pairs(tab) do    -- green balls
        if cameraX>b.ent.position.x-b.size and 
                cameraX<b.ent.position.x+b.size and
                cameraZ>b.ent.position.z-b.size and 
                cameraZ<b.ent.position.z+b.size then
            b.ent:destroy()
            table.remove(tab,a)
            count=count-1
            sound(SOUND_HIT, 19423)
            greenBalls=greenBalls-1
            createWall()
            if greenBalls<lowScore then
                lowScore=greenBalls
                saveProjectData("Low_Score",greenBalls)
            end
        end
    end
    for a,b in pairs(wallTab) do    -- walls
        if cameraX>b.x-(b.z)/2 and cameraX<b.x+(b.z)/2 and 
                cameraZ>b.y-(b.w)/2 and cameraZ<b.y+(b.w)/2 then
            if ships==0 then
                sound(SOUND_POWERUP, 20465)
                youLost=true
            else
                sound(SOUND_EXPLODE, 20445)
                hitWall=true
            end
        end
    end
    if greenBalls==0 then
        youWon=true
    end
    if speed==0 then
        text("Tap screen to start.",WIDTH/2,HEIGHT*.75)
    end
    
    if count<50 then
        for a,b in pairs(tab) do
            xx=b.ent.position.x
            zz=b.ent.position.z
            xx=xx+b.xv
            zz=zz+b.zv
            if xx<-200 or xx>200 then
                b.xv=-b.xv
            end
            if zz<-200 or zz>200 then
                b.zv=-b.zv
            end
            b.ent.position=vec3(xx,1,zz)
        end
    end
end

function resetLowScore()
    clearLocalData()
    lowScore=count
end

function checkTilt()
    gx=Gravity.x
    ang=ang+(gx-hgx)*4
    hgx=gx
    if gx>-.001 and gx<.001 then
        ang=0
    end
end

function drawShip()
    pushMatrix()
    translate(WIDTH/2,HEIGHT/2-100)
    rotate(ang*-30)
    sprite(asset.builtin.Tyrian_Remastered.Boss_A,0,0,300)
    fill(0,255,0)
    text(greenBalls,0,0)
    translate()
    popMatrix()
end

function createFloor(x,z)
    c1=scene:entity()
    c1.model = craft.model.cube(vec3(400,1,400))
    c1.position=vec3(x,-.5,z)
    c1.material = craft.material(asset.builtin.Materials.Standard)
    c1.material.map = readImage(asset.builtin.Surfaces.Desert_Cliff_Color)
    c1.material.offsetRepeat=vec4(0,0,50,50)
end

function createSphere(x,z,size,r,g,b,xv,zv)
    sphere1=scene:entity()
    sphere1.model = craft.model.icosphere(size,1)
    sphere1.position=vec3(x,1,z)
    sphere1.material = craft.material(asset.builtin.Materials.Specular)
    sphere1.material.diffuse=color(r,g,b)
    table.insert(tab,{ent=sphere1,xv=xv,zv=zv,size=size})
end

function createWall()
    local c1=scene:entity()
    local xPos=math.random(-175,175)
    local zPos=math.random(-175,175)
    local xSize=50
    local zSize=2
    if math.random(100)<51 then
        xSize=2
        zSize=50
    end
    c1.material=mtl
    c1.material.map=img
    c1.model=craft.model.cube(vec3(xSize,4,zSize))
    c1.position=vec3(xPos,2,zPos)
    table.insert(wallTab,vec4(xPos,zPos,xSize,zSize))
end

function outsideWall(xp,zp,xs,zs)
    local c2=scene:entity()
    local xPos=xp
    local zPos=zp
    local xSize=xs
    local zSize=zs
    c2.material=mtl
    c2.material.map=img
    c2.model=craft.model.cube(vec3(xSize,4,zSize))
    c2.position=vec3(xPos,2,zPos)
    table.insert(wallTab,vec4(xPos,zPos,xSize,zSize))
end

i can nearly do it at about 1/4 speed. :slight_smile:

More changes. When you do the fly option, the balls and walls are at different heights.

Another change. I modified the camera a little. Now when you’re flying over walls and you dive down after a green ball, I tilt the camera down so it feels like you’re diving down instead of floating down. When you go up, I tilt the camera up, but it’s not the same feeling as going down. I keep thinking I’m done adding more options, but then I think of something else. I also fixed the map. It wasn’t drawing the wall positions correct after a previous change.

Here’s another update. I added the ability to fly instead of staying close to the ground. In the menu, select “allow flying”. Before pressing “play”, hold the iPad level and tilt the iPad a little away from you. Tilting the iPad left or right turns the ship left or right. Tilting the iPad away from you causes the ship to go down. Tilting towards you causes the ship to go up. Max height is 40. Just like in the original game, the object is to fly through the green balls to remove them. There are 100 balls at various stationary positions and height. Once the ball count is less than 50, the remaining balls will start to move. Each time you run through a ball, 10 buildings of random size will appear at random positions. If you run into them, you explode. The more balls you hit, the more buildings you have to avoid. Anytime during play, you can tap the screen 1 time to reset the forward/backward tilt.

Tap the zip file below to send it to the Files app into the Download folder. Tap the zip file there to create a Codea file. Tap the Codea file to run the code in Codea.

PS. Corrected an error when you lose the game and try to play again. It’s was crashing when restarted.

@dave1707 this is neat!

If I may I’d like to make some suggestions!

  1. In my opinion the fuel-per-ball reward is too low. I imagine you set it that way to be challenging, but you already have two mechanics that ramp up difficulty as time goes on: growing scarcity of the balls themselves and the walls appearing. The game becomes very challenging very fast, which I like, but in general you want the beginning of a game to make it seem like it’s going to be easy. :wink:
  2. There should, I think, be a more significant visual indicator that you’ve hit a ball than just the fuel gauge going up. Like many people, I imagine, I usually have my iPad muted by default, so because the only indicator that you’ve hit a ball is an audio cue, I didn’t really understand what was going on. It could be an animation of the balls growing in size as they grow rapidly more transparent, sort of like a cheap popping effect, for a very simple example. I think making the ship itself have some kind of “power-up” effect would be best, like making it momentarily glow, or have a pulsing green outline for a second, but I imagine that’s harder to do.
  3. I think it’s cool that the balls start moving after 50 are left, but since there’s no in-game hint that this will happen, the game seems less interesting, at first, than it ultimately will be. I have two suggestions: give the balls a little bounce-in-place animation, as a hint that they move, and rather than having them be in just two states—moving or not moving—have them only fixed at the very first, and very gradually increase their wandering radius with every ball collected.
  4. The walls-appearing mechanic is cool and interesting, but again, I didn’t realize it was happening until I read it here (I just thought I wasn’t noticing the walls in the first place because the map is so large (which I like). You could do a couple things to make this effect more evident: a) make the screen shake a tiny bit as each wall appears, indicating a kind of rumbling-ground effect, and (if you like) include a rumbling sound, and b) have the walls animate rising out of the ground instead of just appearing. You might be animating this already and I just didn’t notice, and if that’s the case, I suggest you make them rise more slowly so there’s a greater likelihood the player will notice if. When you’re flying it would look really cool to have the walls rise from the floor and then levitate upwards too.
  5. In the same spirit as suggestion 3, I think you should have at least one or two interior walls visible at the very start of the game, as a visual hint that the game isn’t only a fly-around-on-a-featureless-plane game, which it currently appears to be at first.
  6. I like how the ship animates as you turn, and if you wanted to make the ship seem a little more “lifelike” in general you could occasionally have it rumble a little, itself, or even just give it a slow, slight bobbing.
  7. The way the ground disappears near the walls is disconcerting. It looks like the ship will fall through it. And then, when the ship doesn’t fall through it, it’s confusing. I think it’s a good idea to give a visual indication that the player is nearing a boundary wall, but maybe do this another way. Have the ground colored red near the walls maybe. Or have it glow.
  8. Speaking of glow, I’d really really really like to see the balls have a glow effect.
  9. I’d also like to see a visual effect on the whole scene, such as a vignette effect, or darkness that obscures things farther away (this would be a cool combination with the glow) (or you have a dark/light cycle as if a sun is riding and setting), or a fog (maybe that thickens and lessens?), or a blur that increases with distance, or all three in some combination.
  10. You appear to be using a single wall texture no matter the size of the wall, which can look really funky on the larger walls, and particularly on the border walls. I suggest tiling the texture instead of stretching it.
  11. Height map on the walls to make them look rockier? That’s a bit outside my understanding, so I don’t know how hard that is. If it’s not too hard, it would make a lot of difference in the feeling of being in an actual place.
  12. Is a shadow under the ship too hard, since you’re doing a 3D/2D mix?
  13. You could have a more effective UI choice than putting the green score numbers on the back of the ship itself imho. Having the numbers there also distances the player from a feeling of immersion. Using a large bold font, and putting those numbers at the upper left and right of the screen, would not only help with immersion and clarity, it would let you put labels above or below them to make clearer what they are.
  14. I get the point of having a white tilt indicator while the ship flies, and I like it, but I think it should clip behind the ship, not in front of it. Again, it helps with immersion.
  15. IMHO the tilt indicator line should be a bit thicker, and a color other than white, and semi-transparent so that it seems a little like an in-world cockpit readout.
  16. Speaking of which, maybe be able to toggle on/off an in-cockpit POV view? That seems like a tall order though, and personally it would be the lowest item on my wish list.
  17. When flying mode is active, the boundary walls should be as high as the maximum ship altitude, I think.
  18. Maybe a bit after the balls are moving a significant amount, like maybe when there are 20 balls left, you could have the walls slowly start moving too. In fact having the walls verrrrrry slowly moving from the start might be another way to hint to the player that further interesting things will happen as the game goes on.
  19. I get that an actual collision animation might be too much to get involved with, but cutting to a fully black screen with just the explosion effect is jarring. I’d like to see maybe a dark overlay, and that explosion effect, while it could still be frozen, looking like it’s happening in-world. Having the whole world shaking a lot behind the dark overlay would be a cheap way to make it feel like a big collision happened
  20. The opening UI would look cool if it also used the game world as a backdrop, perhaps with the buttons having a semi-transparent effect too. If you want to go whole hog you could have the ship slowly driving around the gameplay area, in the background, on auto-pilot, while the user is at the starting selection screen.
  21. A ground texture would also help a lot with immersion. It doesn’t have to be anything fancy. It also gives the player a stronger feeling of motion and better understanding of their momentum.
  22. If you go with a darkness effect, the ship could have headlights.
  23. The map UI could also have an effect that makes it look more like an in-world cockpit heads-up display. I’m thinking something shimmery and blue, like how Lecia’s hologram looked in the first Star Wars, but maybe that’s a lot to ask. At minimum using a color other than white and a transparency effect would be good. It would probably be a nice touch to have the map and the tilt-indicator use the same color, making them seem like they’re both part of the same in-world cockpit UI.
  24. I know this is last, but I think it’s one of the ones near the top of my wish list: I think you should start the player in the middle of the map, or somewhere close to the middle.

…I know that’s a lot of ideas!

But I think each one is itself not a big challenge, making it easy for you to pick and choose which (if any) you feel like doing.

Also I think they all accentuate the game you’ve made, as opposed to the thing that happens sometimes, in my experience, where people make suggestions that would basically require programming an entirely different game. In quite the opposite spirit I think and hope all my suggestions clearly aim to support and enhance your own intentions with the game, and emphasize the soundness of what you’ve already done.

And all that said, I like it a lot even without any changes!

P.S. It’s for-real cool that you made an icon for it.

@UberGoober Thanks for all the suggestions. The problem is I don’t like to play games, so this was just something to do. It started out as just moving the camera over a large area. Then when Craft was included, I added the balls to hit and then the ship. After awhile, I add walls to go around. Then I added the ability to fly and then added height to the walls. I also have the sound on my iPad muted, but I didn’t add any indication of the balls exploding because I figured everyone else has their sound on. I’ll go thru your list and see what’s the easiest and go from there.

@UberGoober Here’s an early version of the game. Fly thru the stationary green balls to eliminate them, avoid the stationary red balls. Each time you hit a green ball, a moving yellow ball appears somewhere. Each time a yellow ball is hit, a red ball disappears. So the object is to eliminate all the balls.

@dave1707 for a guy who doesn’t like games you’re pretty darn good at making them.

@UberGoober If I get bored enough, I’ll start coding anything.

Well as a gamer, let me say with tongue-in-cheek: may you be bored often. :slight_smile: