160. 2D platform game #5 – Managing images
Half the fun of a sidescroller is all the objects you meet, so the images are pretty important.
Loading and creating the images
For this demo, I chose images from the libraries provided with Codea, and animated them in various ways.
First, I used a function I called LoadSprites to collect all the images that might be useful and read them into a table.
SS_Sprites={ BattorFlap={readImage("Platformer Art:Battor Flap 1"), readImage("Platformer Art:Battor Flap 2")}, BlockBrick=readImage("Platformer Art:Block Brick"), BlockGrass=readImage("Platformer Art:Block Grass"), BlockSpecialBrick=readImage("Platformer Art:Block Special Brick"), RainDrop=readImage("Small World:Raindrop"), -- etc
So basically, I read in the images and gave them the names I wanted. Note that for the Battorflap images (there are two, to allow you to flap its wings), I read them into their own little table within the image table.
I also created a section of brick wall that I could tile across a surface if I wanted. I copied part of an image for this.
local i=readImage("Planet Cute:Door Tall Open") SS_Sprites.BrickWall=i:copy(4,30,95,45)
I also wrote a function to draw a ladder image, and another function to edit the player images, to remove the little round mouth on one of them because it looked odd.
All of this happens when the program starts up.
So my basic idea was to read all the images I might need, into a table to start with, and then the object classes could use any that they wanted.
Managing the drawing of images
This is the code that draws the images – see the numbered lines and the notes underneath
pushMatrix() --translate to player position --[1] translate(SS_Offset.x,SS_Offset.y) --draw backgrounds first --[2] for i,o in pairs(SS_Images) do sprite(o[1],o[2]*SS_w,o[3]*SS_h) end --now all the interactive (class) objects --[3] for i,o in pairs(SS_Objects) do o:draw() o:collide(player) end --now the fixed blocks --[4] for i,o in pairs(SS_FixedObjects) do SS_DrawSprite(o[1],o[2],o[3],o[4],o[4],o[5]) end player:draw() --[5] SS_Dark.draw(SS_Offset.y) --[6] SS_Message.draw(player) --[7] popMatrix()
1 – First, we translate to a position that puts the player in the lower middle of the screen.
Then we draw
2 – the backgrounds, eg scenery, walls
3 – the objects that interact with the player (eg coins)
4 – the objects that don’t interact with the player (eg grass blocks)
5 – the player
6 – the special darkness and lighting
7 – any messages to the player
Each of 2, 3, and 4 has its own table. This makes the code above very simple.
It means that when we first read in the level, and figure out what goes where, we need to store all the objects in the correct table, depending on what they are. After that, the code above will draw them.
Note that the objects in SS_Objects (item 3 above) are classes, and each has its own draw function and collide function. The other tables just contain images that are drawn normally.
This makes it extremely easy to design a new level. You create a new map with characters showing where you want objects placed, and then simply run the program.