Hello Anon, Login?
This is an attempt at learning lua and at the same time, GameCake documentation / tutorial because why not.
I keep forgetting to post the link to the finished game that has lived on the Google Play store since the last time I updated this blog. I found that writing the blog post took a lot longer than the programming spent before it. Doing a recount and summarising (and explaining) what I did and why I made the design decisions felt less important and so seemed like I was wasting time when I could be programming instead. I've placed comments to bits of my code in bitbucket so hopefully that will be enough.

source - https://bitbucket.org/xixs/gamecakejam/src/tip/gthang/
play - https://play.google.com/store/apps/details?id=com.wetgenes.gthang

Have fun and if you have been reading, hope this blog somehow helps you in understanding more about game design.
Apart from a couple of cosmetic changes where I changed the background image and different bullets for different enemy types, I've also added a new enemy type - the "blocker". I guess blockers are more passive aggressive than its counterparts since all they do is shield their master (the "Vader") or collide into the hero ship since they do not shoot or move towards the hero ship independently.

My latest commits are in two parts:
1. https://bitbucket.org/xixs/gamecakejam/commits/c82ed3631c261df08db7e7228e5d5aa265c27940
2. https://bitbucket.org/xixs/gamecakejam/commits/f817e7bed4c90c609ad8ac78633032cc5b461807

And the new changes are as follows:

  • Added new enemy - Blocker.
  • Changed level progression.
  • Resorted scoring for enemy types.
  • Organised all bullet gfx into a proper sprite table.
  • Different enemy types now shoot different looking bullets.
  • Changed background parallax image.

Blocker image The blockers come in cluster and only during alternate levels where Vaders are present. They only have one master at the moment and their main purpose is to shield Vader from the hero's bullets. If you manage to kill Vader, all remaining blockers will also self-destruct. Otherwise, they can be rather annoying :}

Presenting the levels this way has totally changed the game in its entirety. Now the Vader levels have a purpose and become levels you look forward to if, like me, you lose your powerup shield as soon as you acquire them.

I'm thinking perhaps I could change the levels to exponentially introduce the Vader levels so those become bonus levels instead. This way the normal levels become spurts of endurance and juggling becomes a true art. *guffaws*

By the way, I've added a NativeClient version of the game in its current state (I think) so if you're running Chrome, you should be able to play it online via http://play.4lfa.com/gamecake/gthang?play.
I've added a juggling feature where you can now make the powerups stay on the screen by shooting at them.

I really like the idea of having options when it comes to upgrades. Where previously, my shots get upgraded each time I consume a powerup, this new juggling mechanic allows me the option to trigger the powerups only when I want to. Of course, there are certain skills involved and you also compromise vulnerability in exchange for this option.

Thing is, this changed the entire game of dodge and shoot to "dodge, shoot, juggle, strategy" all rolled into a large and, mostly, confusing whole.

What's more, I've also doubled the powerup as a shield; or an extra life if you prefer. Now you have an option of prolonging your turn by keeping powerups on the screen for as long as you can whilst dodging and shooting. The game gets more interesting as you face situations where you could keep one more powerup on the screen and rush for it when you've lost a current shield. Such chaining events could be very advantageous for certain tight spots.

You can view my latest commit here - https://bitbucket.org/xixs/gamecakejam/commits/e53e810a6120476b09896b71290d56adc709f947

Unless I have forgotten what I did, new changes are as follows:

  • Added new enemy - Seeker.
  • Added new powerup - Smartbomb.
  • Fixed table deletion bug.
  • Organised all seperate gfx into proper sprite tables.
  • Added juggling powerup feature.
  • Powerup now also doubles as 1up (one extra life or a shield, depending on how you view it).
  • Tighten the wrap when enemies fall off the screen so there is no more waiting.

Seeker image So we have this new enemy - the Seeker. It, well, seeks you by divebombing towards the hero ship, pauses and then literally lunges towards the direction of the hero ship. I find the best way to avoid the Seeker is to either shoot it down before it reaches too close or just avoid it completely when it gets too close. It's still a little bugger either way.

Smartbomb image The new powerup is a Smartbomb; a very useful but temporary ally. I guess this is more of a relieve button for times when the screen fills up with too many creeps, especially so when you have 3 on the screen thanks to your awesome juggle-fu.

From a few plays, I find the best scenario is to have a powerup equipped whilst juggling a Smartbomb and possibly another powerup as a backup. Of course this all depends on the powerups that Vader leaves behind.
Today was all about the powerups - 3, infact. Technically it's just two different formations since one is similar to the normal shots except twice as frequent.

It was pretty easy to create fancy bullet formations so I'm pretty stoked about wanting to do more of these just because they create such interesting patterns on the screen. In fact, I might even change the entire game so it's all about the interesting patterns. Maybe.

You can view my latest commit here - https://bitbucket.org/xixs/gamecakejam/commits/7fcaf9ccc174763a8e8a8b0d841c8918c665c10b

Unless I have forgotten what I did, new changes are as follows:

  • Added 3 powerups - slipshot, singleshot and sureshot.
  • Slipshot: Diagonal shots, Singleshot: Twice the frequency of normal shots, Sureshot: Awesome shotgun-like effect.
  • Each powerup has different formations.
  • Added a horrible title screen and a new ogg to play when powerups are collected.
  • Extra scores for each powerup consumed.
  • Halved the frequency of default bullet shots.

I may or may not add a lot more poweups and enemies just for the hell of it and see what happens. Hopefully not too many things at once on the screen as I find that the difficulty level of the game is increasing with each new inclusion! My mind can't seem to keep up with the juggling duties of dodging and collecting.
I decided that it was time to add a different type of enemy into the mix; a special enemy that moved differently and shot bullets that had an interesting pattern.
Ultimately, I would like this special enemy to give out powerups when you successfully shoot it.

You can view my latest commit here - https://bitbucket.org/xixs/gamecakejam/commits/ca4a5781dcccf19a39bd86afca1597da451ab327

Here is the list of new changes:

  • Added a new enemy.
  • New enemy has different movement behaviours to normal enemies.
  • New enemy has different bullet formation to normal enemies.
  • Fixed a bug where explosions were not rendered when hero ship collided with enemies.

Since this is just another type of enemy, all I did was make a flava variable for the enemy setup and gave different instructions for the different types of enemy.

Most of today was spent on bullet formation and this included mostly simple algebra, radians and pi.
So tonight I added some much needed sound effects to the game which made it seem more "game-like". All of the sound effects are licensed as public domain from http://freesound.org/ and the theme music is from http://archive.org/.

I made a new file called beep.lua that contains all of the sound files and made sure to add references to the top of each file that will need sound effects (enemies.lua, ship.lua, bullets.lua and main_game.lua).

You can view my latest commit here - https://bitbucket.org/xixs/gamecakejam/commits/b60aed6cd5bddab52f47f53edfdeb08f8b8384cf

The new changes are as follows:

  • Added sfx for enemies death event.
  • Added two sfx for hero ship death event.
  • Added sfx for hero ship bullet shots.
  • Added sfx for new level event.
  • Added theme music.

The default setting for Gamecake is 4 sound effects channel and 2 streaming channels. You can change the number of channels by editing init.lua found one directory up and adding these settings: for example - sfmax=6 and strmax=6. However, there is no way of knowing if this works in certain hardware as some builds may require that number to be below a certain value (iPhone supports 32, windows Direct Sound supports 31, Ubuntu claims to support 255) but it's best to keep this number low with the safest limit at 8.

For the majority of the time, I was playing around with the sound effects and replacing them to make the game sound coherent as a combined whole. This is because you can't really tell if a sound will fit in with the other sounds or the theme music if that particular sound effect is heard in isolation. At times you might even have to replace entire sets of sound effects due to this dissonance.

Throughout this exercise, I was particularly unimpressed with my lack of basic mathematical understanding.
I'm adding some visual feedback to the game. In this case - explosions - and it's strange how a small visual clue changes the whole feel of the game by a mile; music and sound effects will add more miles which I'm really excited about but more on that much later.

I've just made some really rudimentary images as explosions and as for the debris, all I did was seperate the parts of the ships and put the individual bits into a 4x4 grid.

Before adding the various behaviours, the explosions made it seem as if I was squishing bugs on a windscreen instead of squashing alien ships in space.

You can view my latest commit here - https://bitbucket.org/xixs/gamecakejam/commits/385c1bd9f26e6d586e8df35a679ee573c24327d7

They should be easy enough to understand but here, in no particular order, are the new bits I've added:

  • Added safe removal for tables which fixed an 'unnoticeable' bug where the table was being edited at access.
  • Added explosions for both enemies and hero ship.
  • Each explosion comes with a bang followed by floating debris that disperses outwards for a random number of seconds.
  • Different explosion setup for enemies and ship.

The numbers that I've added to each variables are more estimations by trial and error until I was happy with the results than an exact science. I'm currently happy with the way the debris is behaving but I'm still at odds with the bang that appears during explosion.

I will be changing all the graphics for the final version so I'm not going be too particular about this.
Time flies when you're not doing anything. Thanks to recent crunch time, a hackathon and a debut reveal of our very own distribution system in alfa stage, lua lessons were put on hold until today. Meh.

Upon reflection, I suppose they are justified excuses. Also after reading through this massive wall of text, I'm changing my approach to this whole "learning through detailed blogging". Instead, I'll just be summarising what I achieved at the end of the lesson and then point you to my latest code commits.

They've got a pretty nifty commenting system on bitbucket so it will be much easier to follow the changes I've made and how.

Not to say that my original approach was superfluous, not at all. It has seeded my understanding of this whole process which has steadily improved each time I re-read my posts but I think, at this moment right now - I may be fluent enough to 'decode' lua when I see it. At least up to the point that I am able to.

And so, today I have added quite a chunk of things to the code base; mostly the interaction between the enemies and just tightening the collision on level 3. It's mostly tweaking numbers.

You can view my latest commit here - https://bitbucket.org/xixs/gamecakejam/commits/f21ca5cf05956b6e80c9bd859da81aa73e847754

They should be easy enough to understand but here, in no particular order, are the new bits I've added:

  • Added a waves function - This adds one more enemy to the new wave (level) with 5 being the base. So at level 20, there are 25 enemies.
  • Changed enemies formation to random - There is now a rather small but specific area offscreen for the enemies to start coming down from. The rules (random+collision) make for interesting dispersal formations.
  • The hero can only shoot enemies that are within the screen.
  • Enemies will only shoot when they are on screen but I have also removed bullets offscreen.
  • I have limited the bullet directions from the enemies to mostly down instead of those crazy diagonal bullets of death.
  • Enemies now bounce back when they move beyond the bounding area (512x768) and also off each other when they are close enough.
  • I have also tightened collision between the hero and enemy bullets so it's harder to hit the hero. This also makes for fun close encounters during dodging.

Here is an in-game capture so you can hopefully, see what I've done up to this point.
Today's task was similar to yesterday - making things shoot at other things then make those things disappear. So all we do is recycle the same bits of code that make those things happen to enemies.lua. However if I just left the similar bits of code in as it is, the bullets that the enemies shoot are technically the same ones that the hero ship is shooting which in turn, will remove the enemies themselves. What we need to do next is make different sets of bullets for different sets of things; in this case - the enemies.

For bullet.setup:
it.flava=opt.flava or "ship"

I've added a new variable flava and set its state to whatever I set it to later when it's called. Otherwise, it defaults back to the ship. This will make it easier to assign bullets to different items later on; ie. end of level boss, different types of enemies, more hero ships and so forth. Also, since I will be referencing the ship functions here, I will add local ship=oven.rebake(oven.modgame..".ship") to M.bake=function.

For bullet.update:
if it.flava=="ship" then
	for i,v in ipairs(enemies.tab) do
		local dx=it.px-v.px
		local dy=it.py-v.py
		if dx*dx+dy*dy<=40*40 then
			enemies.add({px=math.random(0,512),	py=-math.random(0,512)})
elseif it.flava=="enemy" then
	local dx=it.px-ship.px
	local dy=it.py-ship.py
	if dx*dx+dy*dy<=40*40 then

I shove the previous code for the bullets into an if statement to check if the ship was shooting them. If it was the enemy instead, a different set of instructions will be carried out; namely to remove the bullets and retire the hero. I've also edited the distance of collision for the "enemy" to be the difference between the bullet and the hero ship instead. The other thing I had to change was omit the second enemies.add line that was previously there as not only did it overload the program with assets, the game got ridiculously hard.

At this point, the next thing to do is make sure the bullets that the enemies shoot look different than the hero ship ones. Of course, you can always keep them the same colour if you wanted.

For bullet.draw:
if it.flava=="ship" then
elseif it.flava=="enemy" then

The code is pretty obvious - I assign the different profiles accordingly.

Now we head on to ship.lua and add a new variable ship.state="alive" to the ship.setup function which brings us to the next bit - adding the new ship.die function.

	if ship.state=="dead" then return end

Here we tell the program to check that when the ship is "dead", it should just stay where it is and not do anything. At this point, I have also defined the state of the ship at this point to be, well, "dead" and that the value of it is 0. Or rather, this ship.diefunction to mean as such. See, it's at moments like these that the whole programming logic just seem gobbledygook to me. Anyway, the point of this is to make a "paused" state after the hero ship is destroyed so that I can put in some sort "game over" screen instead of going straight to the main menu.

For ship.update:
if ship.state=="dead" then
	if ship.dead>240 then

I place this at the top most part of the code as it is a priority check. Here I tell the program to wait 4 seconds before going to the main menu screen, where it counts up a frame(ship.dead+1) until it reaches 241 frames (240 being 240/60 seconds). As an added bonus, I also tell the program to rotate the ship during this waiting period.

At this point, the next thing to do is to assign the right bullets to the right item.

if ship.fire then
	if ship.cool<=0 then
for i,v in ipairs(enemies.tab) do
	local dx=ship.px-v.px
	local dy=ship.py-v.py
	if dx*dx+dy*dy<=32*32 then

Again, pretty obvious what the code does. All I did was add in the flava variable and set its state to ship to the end of that table. I've also edited the next bit of code to call the ship.die function when the game is over instead of going to the main menu screen.

Finally, we head over to the enemies.lua file and add local bullets=oven.rebake(oven.modgame..".bullets") to M.bake=function since we will be referring to the bullets function.

Right, so I add a cooldown variable to the enemy.setup function but set it to random like so - it.cool=math.random(100,200). This is more like a timer so the enemies don't shoot straightaway.

For enemy.update:

if it.cool<=0 then
	local dx=ship.px-it.px
	local dy=ship.py-it.py
	local dd=dx*dx+dy*dy
	local  d=math.sqrt(dd)
	if d==0 then d=1 end

Here is where that similar bit of code we did yesterday comes back in but instead of the enemy ship firing only when a spacebar is held down, the enemies just start firing away on their own accord. Well, not technically since I've explicitly told the program to randomly assign the shooting to happen during a time period between 100 to 200 frames.

Velocity is a unit vector; a magnitude with direction whose length is 1. As we are working in 2 dimensional space, there are just two parts to the vector - 8 and (dy/d,dx/d), speed and direction respectively. Since I wanted the enemies to shoot at the direction of the ship, wherever it may be at the time, I've enlisted the help of Pythogoras to figure out the direction and distance between the ship from the enemies to direct the enemy bullets at the hero with 8 frames being the speed of the bullet.

At first I made it so the enemies literally tracked me with bullets but this really made the game too hardcore for me. Instead, I have "soften" the blow with a little randomness.

Probably the most vital bit for this code and the whole game to not break is if d==0 then d=1 end because we all know what happens if you divide by zero.

Before the end, I edited the enemies.setup function like so:
local sx=85
local sy=64
local sya=-128

enemies.tab = {}
enemies.add({px=0*sx,	py=sya+1*sy})
enemies.add({px=1*sx,	py=sya+2*sy})
enemies.add({px=2*sx,	py=sya+3*sy})
enemies.add({px=3*sx,	py=sya+4*sy})
enemies.add({px=4*sx,	py=sya+3*sy})
enemies.add({px=5*sx,	py=sya+2*sy})
enemies.add({px=6*sx,	py=sya+1*sy})

I added the variable sya and adjusted the vertical positions of all the enemies since they were far too low down on the screen at startup.
So it seems I've officially made a game - https://bitbucket.org/xixs/gamecakejam/src/tip/gthang?at=default and you can poke at it if you want.

Tonight I made randomly coloured enemies multiply when I shoot them with invisible bullets of love. This technically means I'm a digital cupid god.

Tacky, amirite?

Then I'll have you know it wasn't intentional. This was more an exercise to see how random tinting of assets and end states work. But first, the important things - bullets. I orginally did not make any bullet graphical assets. In fact, I reused the enemy ship image before changing it to the hero ship as it looked weird feeding the enemies the corpses of their own kind. However, having typed that - maybe I should have stuck with it.

Since the enemies.lua have most of the bits (out of all the other files) I need to create bullets, I duplicated the file and renamed it as bullets.lua; changing all enemies with bullets and enemy with bullet.

For bullet.setup:
it.vx=opt.vx or 0
it.vy=opt.vy or 0

I edited the (x,y) velocity of the bullet (single) to include options so that I may change it later to give it variety and interest. You don't have to do this if you want a constant stream of bullets, all alike but I prefer the irregular pattern of the bullets.

Now I'm back to ship.lua to add a key press to shoot. I have chosen the spacebar as it's a lovely big button that beckons you for such purposes.

Before doing anything else, I added the following to the M.bake function:
local bullets=oven.rebake(oven.modgame..".bullets")
local enemies=oven.rebake(oven.modgame..".enemies")

As I found out recently, programming is all about referencing and iteration. All the time. This is why we have to add these two lines as this file calls functions from those other files.

For msg:
if m.keyname == "space" then	
	if m.action == 1 then
		ship.fire = true
	elseif m.action == -1 then
		ship.fire = false

I add this below the other key presses. I think it's pretty obvious what it does. Of course, I need to include the new variables for this to work.

So for setup:

Since the spacebar is not pressed before the game loads, the default state is false. I have also added a cooldown time for the ship to limit how fast the user can shoot bullets. Keep on reading and this will make sense.

For ship.update:

if ship.fire then
	if ship.cool<=0 then

for i,v in ipairs(enemies.tab) do
	local dx=ship.px-v.px
	local dy=ship.py-v.py
	if dx*dx+dy*dy<=32*32 then

So there is the ship.cool where I ask the program to countdown (-1). Each time I press the spacebar and cooldown reaches zero, bullets should appear from the ship. These bullets appear from the middle and at the top of the ship in varying magnitudes of velocity towards the top of the screen at 8 pixels per frame (-8+math.random()). Here I have also defined the cooldown time to 4 frames which means there is a gap of 4 frames between each shot.

Next we do some rather simple collision tests for when the enemies hit the ship. As we go through the enemies table where i is the index of the table (1,2,3 etc) and v is the enemy (enemies.tab[1],enemies.tab[2],enemies.tab[3] etc) since I parsed enemies.tab, we define two variables that becomes the (x,y) distance between the ship and the enemies.

Now for math, a little bit of Pythagorean theorem didn't do anybody any harm - a^2 + b^2 = c^2 - so what we're doing here is to instruct the program to quit the current game and go to the menu when an enemy hits the ship; when the distance between the enemy and the ship is smaller or equals to 32. The smaller the number, the closer the enemies need to be near you before you die.

This creates circular collision; ie. the shape of the collision is a circular area which basically treats both the ship and the enemies as circles.

Let's return to bullets.lua for some interaction between our protagonist and the many oncoming enemy ships. Or is the protagonist really the antagonist? We will never know! Or do we?

	for i,v in ipairs(bullets.tab) do
		if v==it then

The first thing I did was put a remove function for the bullets. If I don't do this, the bullets will just wrap around the screen like Asteroids and this is Gthang, not Asteroids.

So here I instruct the program to go through the bullets table and when a bullet hits an enemy, that bullet is then removed. table.remove in an actual function in the lua library so what this does is remove one table (bullets.tab,i) and replace it with the next one (if nothing remains, it ceases to be a table); where i is the location in the bullets table.

Finally, I edit the bullet.update with:
it.py = it.py+it.vy
it.px = it.px+it.vx

if it.py>1000 then bullets.remove(it) return end
if it.py<-256 then bullets.remove(it) return end
if it.px>(512+128) then it.px=it.px-(512+256) end
if it.px<(0-128) then it.px=it.px+(512+256) end

for i,v in ipairs(enemies.tab) do
	local dx=it.px-v.px
	local dy=it.py-v.py
	if dx*dx+dy*dy<=40*40 then
		enemies.add({px=math.random(0,512),	py=-math.random(0,512)})
		enemies.add({px=math.random(0,512),	py=-math.random(0,512)})

Here I added velocity to the bullet so that it moves. I then add some simple limiters where the bullet gets removed if it goes off screen in either direction. Of course the bullet is moving in just the one direction (up) but the other instruction is more of a failsafe for future intentions of bullet patterns that may involve other directions.

Anyway, next we find Pythogoras again doing the deed with his deeds. This time the distance is bigger than the collision distance between the ship and the enemies. You can always adjust this to your liking to make the game more difficult or more relaxed. So when a bullet actually hits an enemy, a number of things happen.

Firstly, that bullet is removed. Secondly, that enemy is removed. Thirdly, I instructed the program to add two enemies at random locations. You can add more enemies by adding the enemies.add line beneath but I found that this made the game a little, shall we say, overwhelming.

Enemies: Biege Alert
Enemies: Orange Alert
Enemies: Red Alert

Fourthly, for each enemy removed, the game will add 23 to your current score. Obviously, the screenshot above has yet to reflect this fourth rule.

Now we head on over to enemies.lua to add instructions to remove enemies.

	for i,v in ipairs(enemies.tab) do
		if v==it then

Here, similar to bullets.lua, we tell the program to look through the enemies table to find out the index of the enemy that is passed into this funtion where this index is then passed into table.remove which removes it from the table.

And that's a wrap, folks! At least, it was until this next bit. This next bit is all sorts of wonderful, you'll see.

For enemy.setup:

Let's add some colours! Not any specific colours, mind you, let's randomise this sucker; sucker being the enemy, that is. Here I have made a new variable that contains a table that has 3 random values - (r,g,b).

For enemy.draw:

We add this line before image:draw. What this does in relation to the previous enemy.setup is to call an Opengl function, gl.Color and stick (r,g,b,alpha) into it; where it.rgb[1],it.rgb[2],it.rgb[3] refers to the index number of the it.rgb table accordingly. Behold, the technicolour rainbow!

However, we cannot leave this code without adding the next bit.

For enemies.draw:

We add this after any previous code to reset the this function otherwise the next asset that is drawn by the program will inherit the settings of the previous asset instead of its intended colours.

Instead of doing the same for the bullets in bullets.lua, I have instead just opted for a temporary state by not declaring the colours as a variable in the file. Thusly, adding the following to the bullet.draw function:

will instead provide me with a specific colour to tint the bullets with. You can always use math.random() instead to create the effect of flickering random colours. By now, I had made a simple (64x64) bullet with a blur effect, all filled with white (bullet01.png) so that it can be tinted easily and with full saturation. Don't forget to declare this new sprite in the main.lua file.

For bullets.draw:

And finally, I add the reset to the Opengl function. We call this function here instead of during bullet.draw (singular) because calling the function per each bullet is a tad superflous, especially when it's something you don't need to do.

And exhale.

I wanted the enemy ships to move like the old shmups; intricate flight patterns abound. After much fiddling about with sine waves and radiants, I soon realise it was far too complicated for me to implement this, especially at my current learning stage. I looked around on the web for shmup enemy flight patterns but it always ended up in bullet hell formations instead. Besides, I can't find the answer if I don't know the question. I suppose most just draw some sort of spline that is parsed in as a pattern or something. If there is anything on the web about this, I couldn't find it.

In any case, I abandoned the flight formation and instead went for a more random approach. Not as pretty but hopefully, just as challenging when the game plays.

For setup:

First, I added a countdown variable in the it table. Since there are 60 frames per second, I've set the countdown to 2 seconds. This will make sense in the next bit.

For update:
	it.vx = it.vx*0.95
	it.py = it.py+it.speed
	if it.py>1000 then it.py=it.py-1256 end
	if it.px>(512+128) then it.px=it.px-(512+256) end
	if it.px<(0-128) then it.px=it.px+(512+256) end
	if it.countdown<=0 then
		it.vx = ((math.random(0,100)/50)-1)*8

I brought back the friction that I used for my ship previously as I quite like the "skidding on ice" effect. It also made the ship look more natural and not stiff when it moved.

As you can see, all I did was make the enemies move in one direction - down towards me. I also made them wrap so they don't just fly off the screen when the cycle is done. I also added instructions where if the enemies moved too far to the right or to the left, they would then appear on the far left and far right of the screen respectively.

Now here comes the countdown bit. First I declare that when the enemies are drawn on the screen, we wait 2 seconds (it.countdown-1) before we carry out the next bit of the code. Then when 2 seconds has passed (it.countdown<=0), change the horizontal movement (position+velocity) of the enemy ships randomly every 1 to 4 seconds.

There isn't any video capturing capability for GameCake at the moment so you'll have to make do with my still image. Just use your imagination whilst I bug the other half with this feature request.
Today I made some enemy ships. Well, it's actually one ship drawn many times on the screen. For this to work, I introduced tables into the code.

Before doing anything else, I drew a simple 128x128 enemy ship (bad01.png) and made sure I had enemies.lua set up as per usual. I do a quick ../bake and ../start to make sure everything works.

Next I add a new variable local enemy={} to the bake function. This means the new enemy variable contains a table; as {} literally means table in lua.

I also add a whole new set of functions (setup, clean, update and draw)for this local variable underneath. There is no need to add a msg function as the enemies are not controlled by any key presses.

The first thing I did was to declare some arguements (it,opt) for the setup function. Because there are lots of enemies, using an arguement makes it easier to run the same code on multiple occasions. Arguements are variables that are parsed into a function.


	it.px=opt.px or 256
	it.py=opt.py or 128

So where previously the above resembled enemy.vx, enemy has now been replaced by it. There is also another arguement, opt which comes up later when I add a new add function.

Here I give coordinates of where the ships should be drawn; where if it was not explicit, the x,y should default to 256,128 respectively.

	local image=sheets.get("imgs/bad01")


At the moment, I'm just using just the one enemy ship so I will declare it under the draw function.

local sx=85
local sy=64

enemies.tab = {}
enemies.add({px=0*sx,	py=1*sy})
enemies.add({px=1*sx,	py=2*sy})
enemies.add({px=2*sx,	py=3*sy})
enemies.add({px=3*sx,	py=4*sy})
enemies.add({px=4*sx,	py=3*sy})
enemies.add({px=5*sx,	py=2*sy})
enemies.add({px=6*sx,	py=1*sy})

Which brings us to the *creative* bit of the entire process - manually setting up a formation for the enemy ships. Here I declared another variable, tab that will contain the table full of wonderful enemies.

	local it2={}


What this does is make a temporary table consisting of settings that make up the main table. This is more akin to a temporary state that tells the main table what to do. Here I declared a new local variable, it2 that contains a table which is then parsed into setup along with the opt values which we will get from the enemies.add function.

Referring to the previous enemies.tab, [] and . are table lookups where # is the length of the table (number of entries found in the table). What I've done here is to add one entry to the end of the table.

For draw:
for i,v in ipairs(enemies.tab) do

This 'for loop' tells the program to iterate through this section of code where i (index) is a number between 1 and the total number of enemies and v (value) will be the table that contains all of the enemy data (enemies.tab). In this case, since there are 7 enemies, it loops 7 times to draw each enemy.

I have also added the 'for loop' for both update and clean functions. At the moment, I'm not using either functions but I have set it up just in case.

There were many concepts of programming that I found hard to grasp during this exercise but hopefully, thorough practise should elucidate this issue.

Bonus random math moment alert!

Try adding this 'for loop' to the enemies.setup function:

for i=1,100 do
	enemies.add({px=math.random(0,512),	py=math.random(0,512)})

This iterates the code 100 times which means 100 enemies are placed randomly on the screen within a 512x512 area!
Today I made a ship that moved left and right with varying magnitudes of velocity that utilised friction. I also introduced collision so that the ship would not fly off the screen.

The first I did was to create a rather rudimentary looking 128x128 ship (ship01.png) and making sure I had all the basics set up; ie. duplicate stars.lua, rename it as ship.lua, declaring the new variables into the main functions and including the new sprite.

Since I will be using key presses for ship movements, this would mean calling the message function. Here I edit main_game.lua and added ship.msg(m) to game.msg=function(m) with m being the message variable. I will also edit ship.lua and add print (wstr.dump(m)) to the message function here. What this does is print out information on to the console screen when any key presses or mouse movements are made.

For setup:

I have defined the (x,y) coordinates of the ship in relation to where I want it on the screen. In this case, the ship will be placed on the middle and at the bottom of the screen; where y=(the height of the screen)-(the handle point of the sprite).

I have also defined rotation for future use, (x,y) velocity, left/right button states and the speed of acceleration of the ship.

For draw:
	local image=sheets.get("imgs/ship01")

Now I draw my ship, load it from console and see if my screen blows up. Next I press the left and right button, noting everything that comes up on the console screen. Things that should, more or less, look like this -


From here I deduce that each key press comes with a class, action and keyname amongst other things. Each time I press down and release a key, 2 actions are logged - 1 when a key is down and -1 when released.

This should give me all the information I need to write instructions for interactivity.

For msg:
-- print (wstr.dump(m))

	if m.class == "key" then		
		if m.keyname == "left" then			
			if m.action == 1 then
				ship.left = true
			elseif m.action == -1 then
				ship.left = false
		if m.keyname == "right" then			
			if m.action == 1 then
				ship.right = true
			elseif m.action == -1 then
				ship.right = false

First thing I did was to comment out the string dump since I have all the information I need from the console about the key presses. Of course I can delete the whole line out but I'm going to leave it in here, just in case.

Next I begin by calling the msg variables (which is m) and the previous variables that are contained within it (class, action and keyname).

Specifically, when the left key is pressed down, then the state of the left button is true and when the the left key is released, the state of the left button is false. The same goes for the right key.

For update:
	if ship.left then	
			if ship.vx>0 then ship.vx=0 end		
		ship.vx = ship.vx-ship.speed
	elseif ship.right then	
			if ship.vx<0 then ship.vx=0 end		
		ship.vx = ship.vx+ship.speed
	ship.vx = ship.vx*0.9
	ship.px = ship.px+ship.vx
	if ship.px>512 then
		ship.px = 512		
			if ship.vx>0 then ship.vx=-ship.vx end		
	if ship.px<0 then
		ship.px = 0		
			if ship.vx<0 then ship.vx=-ship.vx end		

Now comes the physics bit.

The first chunk of code concerns the direction of the ship. When the left key is pressed down and the ship is moving to the right (0 is top left, 512 is top right, 768 is bottom left), then the velocity of the ship gets set to zero. This stops the ship instantly. At the same time, the ship accelerates to the left (negative is left) at the speed declared in setup which, in this case, is 1.75. The opposite goes for when the right key is pressed down.

The next chunk is friction. Here I define the velocity of the ship to be multiplied by 0.9. You may of course experiment and change the values to suit your needs. I find this suits me as it doesn't give that horrible slippery effect of being on ice.

Anyway, the next line is updating the movement of the ship to include that velocity. If this is not done, nothing happens!

Finally, we add collision where if the ship moves beyond the screen, the ship is moved back and it's velocity is reversed; ie. it bounces back into the screen. However, these subtle instructions are only visible with proper combinations of pressing and releasing of keys and by this simple programming exercise, I can now appreciate it fully!

As an incentive, if you comment out if ship.vx>0 then ship.vx=0 end and if ship.vx<0 then ship.vx=0 end, you get an entirely different ship behaviour. Amazeballs.

Today I made a scrolling parallax background that wrapped around the screen.

For this to happen, I had to make a graphical asset which I said I wouldn't but I did anyways. It's just 2 images where one is a simple 1024x1024 black background with a few blobs of blurred white stars (back01.png) and the other has a 1024x1024 transparent background with smaller, brighter and less blurred stars (back02.png); nothing complicated. I shove these into new folders art>imgs.

From here, I load main.lua and edit main.loads=function() to include the new star sprite sheets by replacing oven.cake.images.loads({}) with the following:


The first two numbers define how many columns (x) and rows (y) your sprite will be chopped into; eg. 1/4,1 means 4x1 and 1/32,1/2 means 32x2. The second two numbers are the coordinates of the handle. A handle is the point where your image is drawn from so 1/2,1/2 means my handle is located in the middle of my image.

Next is the exciting bit where I do some parallaxing. First, I made a new file by duplicating main_game.lua and renaming it stars.lua to preserve the 4 functions - setup, clean, update and draw.

setup - gets called once to run actual game update - gets called a constant 60 times every second (frame rate) draw - gets called up to 60 times per second (may run slower) clean - gets called only when state is changed (after game)

I then replaced all game text in the file with stars, taking care not to replace gamecake of course.

Now I go back to main_game.lua and add local stars=oven.rebake(oven.modgame..".stars") to the main bake function so that the game loads the new file.

Next I include stars.setup(), stars.clean(), stars.update() and stars.draw() to each of the 4 main functions. This needs to be done for each new file created that requires loading in the game. I also did a bit of housekeeping here and extracted any uneccessary if statements from the other function calls.

Back to stars.lua, I added the following to each of the main function.

For setup:

Here I have included the two sprites to load at setup where they are both variables (p1y and p2y) and set to zero since updating adds to that value. You may or course, call the variables anything you wish.

For update:
	if	stars.p1y>1024 then
	if	stars.p2y>1024 then

Here we define movement where p1y is moving at (60*0.25fps) and p2y is moving at (60*0.4fps). Since one image is moving faster than the other, we now have parallax. I also added some if statements to make sure the images wrap.

For draw:
	local image=sheets.get("imgs/back01")
	local image=sheets.get("imgs/back02")

Here is where we call the function to display things on the screen. I've declared two variables for the two sprites but named them the same. Like css, the same variable always updates to the latest. In this case, to achieve the impression of endless scrolling, the images are drawn 3 times - the reset state, before reset state and after reset state. Here is also where I explicitly declare the dimensions of the sprite sheet (1024x1024).

The first number is which of the sprite to draw, the next two numbers are coordinates (x,y), the next number is the rotation angle and the last two numbers defines the dimension of the drawn sprite.

Finally after a ../bake and a ../start in the console, you should hopefully get the following screen; unless I've missed something.

You can take screenshots of in-game activity with F12 at any time. The screenshots are found in files>snaps.
Naming your game is probably the first thing you do before anything else. Naturally, it took me some time before I settled on the aptly chosen, gthang (galaga thing). After that rather crucial step, I then proceeded to defining the dimensions of the project - a portrait mode of 512x768. This felt right to me as most shmups are tall rectangles. We do this by first installing the base code into the new directory via the console and then editing the lua>init.lua to reflect those dimensions. By the way, I'll be using the GameCake Engine the whole time.

Next bit is to fix the layout of the menu buttons to fit the new dimension. We do this by editing the lua>gthang>gui.lua at the appropriate places and making sure it all adds up. Always bake and check often! Since I haven't decided on what I'm going to include in the game right this moment, I've simply duplicated the main_menu.lua and saved it as main_game.lua, replacing all menu text with game within the file itself.
Having attempted learning lua unsuccessfully in my previous life, I have decided to try it once again. This time, I have chosen Galaga as the output and being a game I would actually want to play, this should hopefully encourage me to finish what I started.
So some decisions - screen or world scrolling? With screen scrolling, the main action takes place on screen where things materialize and nothing happens off screen; this way, I only need to focus on what's happening within a limited viewspace. With world scrolling, the viewspace moves over everything that may or may not be there where things are happening all the time beyond the actual viewspace. There is no right or wrong approach to this as either will pose different sets of problems but I'm going for the former - screen scrolling.

I'm not going to be doing any graphical assets for this so I will be utilising the dreaded 'programmer art' method. This is an exercise in 'proper' programming after all. Right, so the few things I will be drawing includes the backdrop, enemy ships, player ship, enemy bullets, player bullets and explosions.