It’s time to put the final touches to our game, namely animating the player sprite. Previously I’ve shown you how to do this for the enemies, and also how to create the enemies as objects, so we’re combining those for this task.
Part 10: Player Animation
As before, we need to draw some frames of animation to use. I’ve created some additional frames in sprite slots 2, 3 and 4 to carry on from 1.
Again, it’s pretty simple but is just for illustration.
Now, we need to create the player as an object. We could have a function to house this, make_player() like we have make_enemy(), but we only need to create one player so that’s overkill. Instead, we’ll create it in one go in the _init() function, replacing the x and y we had there before:
-- create player object player = {} player.x = 64 player.y = 64 player.sprite = 1 player.frame = 0 player.framemax = 3 player.ticks = 0 player.ticksmax = 4 player.draw = function(this) this.ticks += 1 if this.ticks == this.ticksmax then if this.frame == this.framemax then this.frame = 0 else this.frame += 1 end this.ticks = 0 end spr(this.sprite+this.frame, this.x, this.y) end
You’ll notice I’ve put a player.draw function in there, which works just like the enemy draw function from last time.
Now we need to replace all references to x and y in the code, with player.x and player.y. You’ll find some in the button press check code (e.g. if btn(0) and x > 0 then…), in the collision check routine (if checkcol(x,y,en.x,en.y)) and in the en.move function (if x < this.x then…).
if btn(0) and player.x > 0 then player.x -= 1 end if btn(1) and player.x < 120 then player.x += 1 end if btn(2) and player.y > 0 then player.y -= 1 end if btn(3) and player.y < 120 then player.y += 1 end
if checkcol(player.x,player.y,en.x,en.y) then stop() end
en.move = function(this) if player.x < this.x then this.x -= this.d end if player.x > this.x then this.x += this.d end if player.y < this.y then this.y -= this.d end if player.y > this.y then this.y += this.d end end
Finally, we need to replace the code in _draw() that drew the player sprite. It was spr(1,x,y), but now we just call:
player:draw()
Save, deep breath, run!
And that’s it. We have a complete, working game with enemies, movement, collisions and animation. Sure, we don’t have any sound, a title screen, lives or a game over sequence, but the game logic is there and you can see it’s a place to build from.
Here’s the final code. Skip past it to play the actual game!
function _init() -- create player object player = {} player.x = 64 player.y = 64 player.sprite = 1 player.frame = 0 player.framemax = 3 player.ticks = 0 player.ticksmax = 4 player.draw = function(this) this.ticks += 1 if this.ticks == this.ticksmax then if this.frame == this.framemax then this.frame = 0 else this.frame += 1 end this.ticks = 0 end spr(this.sprite+this.frame, this.x, this.y) end ticks = 0 tickstrigger = 200 dinc = 0.05 -- score score = 0 -- initialise enemies table enemies = {} -- make first enemy make_enemy(17,120,120,0.05,3,0,5) end function _update() -- check for collision foreach(enemies, function(en) if checkcol(player.x,player.y,en.x,en.y) then stop() end end) --[[ check button presses and screen edge btn(0) is left btn(1) is right btn(2) is up btn(3) is down ]] if btn(0) and player.x > 0 then player.x -= 1 end if btn(1) and player.x < 120 then player.x += 1 end if btn(2) and player.y > 0 then player.y -= 1 end if btn(3) and player.y < 120 then player.y += 1 end -- move enemies foreach(enemies, function(en) en:move() end) -- increment score score += 1 -- if ticks are triggered, make enemy faster ticks += 1 if ticks > tickstrigger then foreach(enemies, function(en) en.d += dinc end) ticks = 0 make_enemy(17,rnd(128),rnd(128),0.05,3,0,4) end end function _draw() cls(2) -- clear the screen to mauve print(score,100,0,7) -- print score player:draw() -- draw player -- draw all enemies foreach(enemies, function(en) en:draw() end) end function checkcol(ax,ay,bx,by) if bx+8>ax and bx<ax+8 and by+8>ay and by<ay+8 then return true else return false end end function make_enemy(espr,ex,ey,ed,eframemax,eticks,eticksmax) en = {} en.sprite = espr en.x = ex en.y = ey en.d = ed en.frame = 0 en.framemax = eframemax en.ticks = eticks en.ticksmax = eticksmax en.draw = function(this) this.ticks += 1 -- increment ticks if this.ticks == this.ticksmax then -- have we hit the last tick? -- if so, inc the frame if this.frame == this.framemax then -- have we hit the last frame? this.frame = 0 -- set back to first frame else this.frame += 1 -- inc the frame end this.ticks = 0 end spr(this.sprite+this.frame,this.x,this.y) end en.move = function(this) if player.x < this.x then this.x -= this.d end if player.x > this.x then this.x += this.d end if player.y < this.y then this.y -= this.d end if player.y > this.y then this.y += this.d end end add(enemies,en) end
[includeme src=”https://lofi-gaming.org.uk/gamedev/firstgame/firstgame.html” frameborder=”0″ width=”400″ height=”400″]