Tuesday, May 31, 2016

Back to the game code

After over a week of learning about random spawning, collisions and those confusing Lua tables, I finally came back to working on the game proper. Today, I added game states (so I can have a splash screen), and implemented the improved random spawner with a pretty solid collision between the ball and the bricks/enemies. This marks the basic play mechanics as complete, but there is still a lot to do for this game. The next step is coming up with a selection of enemies that will create interesting gameplay, then implementing a good algorithm for spawning them in such way to make the game challenging and fun. It will be interesting to actually try my hand at some video game design after learning  about gamedev and programming for over two weeks... oh and trying to make some passable pixel art.


In the meantime, I'll break down the code for the spawner used in the game:

function create_bug()
--responsible for assigning
--random values to enemies
 local sprites={17,19,21,23}
 local sn = flr(rnd(4)+1) 
 local o={}
 o.sprite=sprites[sn]
 o.x=flr(rnd(110))+1
 o.y=flr(rnd(60))+10
 o.w=2
 o.h=o.w
 o.x2=o.x+o.w*8
 o.y2=o.y+o.h*8
 o.xdir=flr(rnd(2)+1)
 o.ydir=flr(rnd(2)+1)

 overlapped = true
  while overlapped do
   overlapped = false
   foreach(bugs, function(bugs)
    if bugs.x<=o.x+o.w*8+1 and bugs.x+bugs.w*8>=o.x-1 and bugs.y<=o.y+o.h*8+1 and bugs.y+bugs.h*8>=o.y-1
    then
     test+=1
     overlapped = true
     o.x=flr(rnd(110))+1
     o.y=flr(rnd(60))+10
    end
   end)
  end
   add(bugs, o)
end

function col_bugball()
 for a=1,#bugs do
  if bugs[a]!=nil then
   if bugs[a].x<ballx+ballsize
   and bugs[a].x+bugs[a].w*8>ballx 
   and bugs[a].y<bally+ballsize
   and bugs[a].y+bugs[a].h*8>bally then 
    test+=1
    --bounce horizontal
    if ballcenterx<bugs[a].x
    or ballcenterx>bugs[a].x+bugs[a].w*8 then
     ballxdir= -ballxdir
     sfx(01)
    --bounce vertical  
    elseif ballcentery<bugs[a].y
    or ballcentery>bugs[a].y+bugs[a].h*8 then
     ballydir= -ballydir
     sfx(01)
    end 
    del (bugs, bugs[a])
   end
  end
 end  
end

The first part of the code is pretty similar to the one in the post before, but it has few important changes - mainly optimization and changing the enemies from simple rectangles to actual sprites (who are simple rectangles for time being, but that will change). The most important change is in the approach to spawning objects. Instead of running the whole function as in the previous version, I only change the X and Y of the spawned object if the collision is detected. This approach is less memory intensive, although can still manage to crash Pico8, if pushed too hard. Once I implement some enemy types, I will limit the amount of times the program will try to spawn something. Right now, it is a good tool for testing. The other change, swapping IF to WHILE when checking for collisions, solves the issue I had when a the function would check for object N, then spawn object N+1, but it didn't take into account any objects spawned before N so the new object would sometimes overlap the older objects.

The second part function col_bugball() takes care of the collision between the enemies and the ball. It cycles through every enemy in the table bugs and checks for their collision. I am using the formula for collision between squares, as the ball sprite is effectively a 5x5 pixels square and my enemies will stay in roughly rectangular shape. Once it checks for collision, the function checks if the ball hit the block from the side, or top/bottom. This then reverses the ball direction accordingly. I have some small issues with the ball behaving odd here (changing X and Y direction on the same block), which I am still to fix. I will look into it after I have made couple enemy types and see if the issue prevails. Finally, the object that was hit by the ball gets destroyed. This part will get changed to a hitpoint system, once the enemy types will start rolling in. Having some enemies take more than one hit is a staple of breakout games after all.

Sunday, May 29, 2016

I broke Pico 8 and I am not even mad.

Yesterday I made Pico 8 run out of memory. I was trying to figure out how to spawn "enemies" in such way so they wouldn't overlap (which is important for the game). So far it works, but it is not a great solution if you need more than a handful things spawned (which I don't). It can quickly start hogging the memory, because the program gets lost in an ever expanding loop of spawning and deleting those squares. The top left variable tracks how many times the program goes through that loop before it can find a square that does not overlap any of the existing ones, and I have seen it add 500 on few occasions. To be honest, 500 is still a very impressive number. As someone new to programming, I am amazed how much even the limited Pico8 can compute. Anyway, here's the code for this function...


function create_bug()
--responsible for assigning
--random values to enemies
 local o={}
 o.x=flr(rnd(110))+10
 o.y=flr(rnd(60))+10
 o.w=flr(rnd(12))+4
 o.h=o.w
 o.x2=o.x+o.w
 o.y2=o.y+o.h
 o.col=flr(rnd(14))
 o.xdir=flr(rnd(2)+1)
 o.ydir=flr(rnd(2)+1)
 add(bugs,o)
 
--check if the new bug is not overlapping
--with any existing bug.
 for a=1,#bugs -1 do
--by using the collision formula
   if bugs[a].x<=o.x+o.w 
    and bugs[a].x+bugs[a].w>=o.x
    and bugs[a].y<=o.y+o.h
    and bugs[a].y+bugs[a].h>=o.y
    then test+=1
    del (bugs,bugs[#bugs]) --delete overlapping bug.
    create_bug() --try again
   end
 end
 
end

I won't use that method as there is a possibility it will simply break the game. But, I will leave it here, as a pretty good example of the programming process (at least for newbies): code, find out it doesn't work exactly how you wanted, find the reason why, code more. I am quite proud that I was able to break PICO8 and that I could identify why it happened. So there's that. It seems that, instead of deleting and trying again, a better way is to move the new object so it is no longer on top of any of the existing ones. At least it seems better on the surface...

Friday, May 27, 2016

Collisions for randomized enemies also [mostly] work!

It feels like right now I am getting a bit too close to the deep end of the pool. While in the last few days I have managed to make the randomly spawned balls move (pretty easy) and even collide with each other (really hard), I couldn't have done the later without the help from the Pico8 communities on Slack and IRC. Those guys helped me understand Lua syntax much more, and on more than one occasion simply gave me the answer. My next step, after fixing few bugs in this code, is to go back to my pong game and start implementing those enemies in. I feel like I need to take a step back from trying to understand more advanced topics and actually work on the game, mostly because programming the game and seeing how it all comes together is much more rewarding than trying to perfect a single side mechanic.


Anyway, let's see how this code works...

MOVEMENT:

function update_bug(o)
--move the bug
  o.x+=o.xdir
  o.y+=o.ydir
--keep within world  
 if o.x+o.size>126
 or o.x-o.size<1 then
  o.xdir= (-o.xdir)
 end
 if o.y+o.size>126 
 or o.y-o.size<1 then
  o.ydir= (-o.ydir)
 end 
--avoid collision with wall
 if o.x-o.size<=0 then o.x=1+o.size end
 if o.x+o.size>=127 then o.x=126-o.size end
 if o.y-o.size<=0 then o.y=1+o.size end
 if o.y+o.size>=127 then o.y=126-o.size end
end

function _update()
 debug()
 foreach (bugs, update_bug)
end

This was the easier of the two tasks. Moving something (a shape, sprite, whatever) was covered pretty well in the Squashy tutorial. All we need is to change the X and Y values the object and then call this in the _update() function. The only difference here was instead of a single object, I had bunch of objects stored inside a table, each under its own number. This is where my lack of knowledge of Lua syntax, and of programming in general, slowed me down. On paper I knew exactly how to do it. Get a loop going that updates the X and Y values of each element inside the table. Now All I needed to get it going was to find a way to access stuff in that table. So I had spent some time looking for Pico8 carts that have random enemies and try to dissect their code. I have noticed few of them using the FOREACH statement in conjunction with a table and a function that had one parameter - o. This "got the ball rolling," so to speak.

At this point I thought that the naming of the parameter (o) had to be the same to the one used in creation of my table (which also was o). That's not the case. To my understanding FOREACH looks up the values from the table (in the case of bugs, it returns the table for each enemy), and plants it into the function. The function can now process each enemy one by one. Thanks to that it changes X and Y for enemy 1, then 2, than 3 and so on. The "o" parameter is simply a "placeholder" a local variable (as I said, I mostly understand tables )

After finding a way to update X and Y of every enemy I just added some IF statements to keep the balls on screen (bounce of the wall just like in Squashy) and another one to eliminate a bug where a ball would get stuck on one of the walls after collision. I guess I could have combined them into one function, but having them separated makes it more clear what each section does.

After I had the balls moving and bouncing of the walls I wanted them to bounce of each other. For that I needed...

COLLISIONS:

--check for collision between bugs  
function collision_bugbug()
--cycle thru the table get one enemy
 for a = 1, #bugs do
--cycle thru again get second enemy 
  for b = a+1, #bugs do
--formula for distance between circles  
  local distance=sqrt((bugs[a].x-bugs[b].x)^2+(bugs[a].y-bugs[b].y)^2)
--if distance is smaller than combined sizes
--of both enemies, it means they collide
    if distance <= bugs[a].size + bugs[b].size +1 then
--bounce the balls back on collision
      bugs[b].xdir= -bugs[b].xdir
      bugs[b].ydir= -bugs[b].ydir
      bugs[a].xdir= -bugs[a].xdir
      bugs[a].ydir= -bugs[a].ydir
--just for testing how many collision there are      
      test+=1
   end
  end
 end  
end
     
  
--system functions
function _update()
 debug()
 collision_bugbug()
 foreach (bugs, update_bug)
end

This was the tricky syntax part that I couldn't figure out on my own. It felt like it was within my grasp after figuring all the math and learning about FOREACH, but it felt like a strange blind spot in my brain whenever I was trying to create syntax to compare two different enemies from inside the table. I spent a day or so trying to find a solution, but again, documentation simply wasn't there (I really hope that Pico-8 manual will eventually become a little noob friendly). This is where the awesome community of this fantasy console stepped in.

This is the second version of the collision code. The original way was working fine, but used over twice as much CPU clock. It was based around FOR x in ALL(table) instead of FOR x=1,#table (length of the table) which meant that the code would check enemy 1 vs enemy 2, but also check enemy 2 vs enemy 1, which was not necessary, as we already checked if they collided. I am not really on the level of proficiency to optimize my code, but when there was an opportunity to do so, I jumped on it. Here's a comparison how the old (left) vs current (right) works:


Easiest way (at least for me) to understand it is to treat every unique number as an unique enemy. Each number holds a table for one enemy. So Bugs[1] holds X,Y and other attributes of the first enemy, Bugs[2] the second and so on. As you can see, the current version does "less work" as shown by the white spaces. Later on I added to the formula, so B starts at A+1 instead just A, so the function won't check collisions against against the same enemy. This saved a little more CPU time and a token, as I didn't have to add A != B (A does not equal to B) to the IF statement. Anyway, let's break down the current code...

function collision_bugbug() initiates the function, so we can call it later in _update(). Next two lines (for x in...) cycle through the enemies' table twice and generate pairs of numbers (A and B) which we can compare.
Next we need to find out the distance between the circles to see if they are overlapping. This is where Pythagorean Theorem comes in handy yet again (honestly I never thought I will get that much millage out of something I have learnt in primary school). We basically find the distance between two points (centers of the two enemies) and put it in a variable ( local distance=sqrt((bugs[a].x-bugs[b].x)^2+(bugs[a].y-bugs[b].y)^2) ) for clarity. Then we check if this distance is equal or smaller then the sum of the sizes (radiuses) of the circles. If it is, it means that the circles are touching / colliding. 
THEN we put whatever we need upon collision, in this test I just reverse the directions at which the circles travel (also add one to test variable, just for troubleshooting). 


That's it. When it is broken down like that it doesn't seem that difficult, but it took me a long time to get there, and would probably take me much, much longer without the community's help. 
If you want to check out the whole code for the spawner, feel free to download the cartridge to the left and mess with it. Right now there are still some bugs (circles can spawn on top of one another or can get stuck if multiple circles collide at the same time) that I will try to fix in the near future (well, basically as soon as I can figure out the syntax for it). My next step is to transplant this into the game code proper and do some tests with squares, sprites and maybe even pixel perfect collision (which maybe way beyond my skill level, but there is a Pixel Perfect Collision Demo cart that I plan on digging in). 

Monday, May 23, 2016

The randomized enemy spawner is working!

This bunch of circles might not look like much, but they took me over two days to figure out. The issue was not making them have random values, but wrapping my head around the concept of Lua tables. Lua is great at simplifying things to make the programming flow better. Unfortunately, a byproduct of this is making some concepts more difficult to understand by someone who has very little programming experience. This is the case with tables. They combine arrays and matrices (and probably some other things!) into a single object. This is a great thing for someone who understands how those base concepts work...for someone like me, it is a big hurdle. It didn't help that the Lua documentation focuses solely on the differences between tables and the things they replace...


It took a lot of reading, testing, looking up others' source code and a dash of frustration, but, with help from Pico8 community, I managed to (at least partially) wrap my head around it. The moment it finally clicked felt awesome!

To make it easier on myself, I wrote this randomized enemy spawner as a new program, away from my game code.  I used simple placeholders for most of the elements. That way, nothing else would come in the way of grasping this concept. I think it paid off, because I got it to work and even made some pretty clean looking code:

Edit: I was advised to change the table o from the create_bug function to local table to avoid other functions grabbing this data when they don't need to. I changed that in the code below.

--table for enemies
--enemies are bugs
--hence the name
bugs ={} 

function create_bug()
--responsible for assigning
--random values to enemies
 local o={} --make empty table
 --and fill it with below values
 o.x=flr(rnd(110))+10
 o.y=flr(rnd(50))+10
 o.size=flr(rnd(18))+2
 o.col=flr(rnd(14))

 --add this table to bugs table
 --this way, we have all the enemies
 --stored in one place so they can
 --be accessed all at once.
 add(bugs,o)
 return o
end

function draw_bug (o)
--draw an enemy with values
--established in create_bug
  circfill(o.x,o.y,o.size,o.col)
end 

--spawn enemy on button press
--used for testing the code
--yes, I know the name is 
--somewhat misleading
function debug()
 if btnp(4) then
  create_bug()
 end 
end 

--system functions
function _update()
 debug()
end

function _draw()
 rectfill(0,0,127,127,15) --draw background
 foreach (bugs, draw_bug) --draw all the enemies!
--this function goes through all the enemies
--stored inside bugs table and draws
--them one buy one.

 --show current amount of enemies
 print (#bugs,4,4,1)
end

There are still some small things I do not know exactly why they work, but I know how to make them work, so that's good enough for now. I will continue expanding this code to make those enemies move and possibly not overlay each other, then I can transplant it into the game proper. I hope that by doing so I will figure out the bits I don't fully comprehend.

Saturday, May 21, 2016

Quest for random numbers...

Now that I am happy with the general ball physics of the game I want to implement the next aspect - enemies. For this game I have this idea to mash-up breakout and a shoot'em'up / space invaders type game together. Player's goal is to destroy the enemies with the ball. The enemies alone don't attack the player's paddle, but instead make the game more difficult by producing glitch effects... but this post is not about that.

This post is about me basically wasting a whole day, because I was afraid to code. I spent the whole day today and a lot of yesterday NOT doing code, because I had no idea where to start. Like I know what I want for the enemies to work. I want them to spawn at random(ish) time at random(ish) place on the "board" and move about. Then I want to add collision between enemies and the ball and a way to destroy them. That's all.

But because I am a noob at programming I didn't even know how to generate random number in Lua! This small thing stopped me from doing any real work on the game for more than 24h. This is stupid!


I spent wasted some time looking for tutorials for "spawning enemies at random +lua" and similar shit, but generally I just avoided coding or anything related to it because this task of adding randomly spawning enemies seemed too complex for my meager skills. Then it suddenly occurred to me that I am not supposed to code it all at once. I have already broken down the task into smaller chunks, so what I need to do is to tackle one chunk at a time. This was an eye opener and something that I will need to remember if I ever get scared of coding again.

LEARNING TO LOOK FOR ANSWERS.

So now I had a manageable task in front of me: learn how to call random numbers, especially between two numbers (handy for coordinates between 0 and 127). I can do this.

Sadly the Pico-8 manual is not very newbie friendly right now, so it wasn't much help. It did give me the RND function, so I had a starting point. Next I just played different games on Pico-8 to see which one of them had randomized enemies and lookup the source code. This didn't help as much, because a lot of those games didn't have any comments explaining what is happening. It did give me some ideas though. Lastly I did something that I should have done much earlier, googled "+lua +rnd" - and this really broke me out of my code scare. I found couple websites that explained exactly how RND works. However, PICO-8 uses a custom version of Lua so I had to test it inside my game to see what does and doesn't work. This last part helped immensely, because it broke my temporary fear of coding. After all I only was testing one small thing. Nothing scary.

So, if you are a newbie like me, and you are stuck because you don't know how to proceed, do this:
  1. Break down the issue into small chunks. As small as you can. Think of everything that your program needs to do to make this thing happen. Write them down if it helps. Then try to implement them one by one.
  2. Lookup manuals and other documentation for the engine/framework you are working with to find out how to do each step. For me it was Pico-8 manual, that is still in very early stages and not overly helpful. But it doesn't matter. It can put you on the right track.
  3. Google what you need to know. Not the whole task, just the thing you are currently working on from your list of small chunks. Learn about that thing.
    1. If you are a Pico-8 user, lookup how others solved that problem. Get into that source code and try to understand it.
  4. Test. Implement something small to check how it works. Either as a new or inside your current program. If you are worried that you will mess up your code - don't. Just save a backup.
  5. Test it in a different way. Maybe expand your test to get you closer to your big goal or test some other aspect of what you learned from the steps 2 and 3.
  6. Test more, until you feel that you know what you are doing with this thing.
Now you can implement (at least a bit of) your code to solve the issue and you have, and you have learned something new in the process. Best of all, you managed to code something when it felt impossible. You got this.

EDIT:

Just my luck. Someone had a random number related question in the Pico-8 BBS as I was writing this post. Those answers would have helped me a lot. I guess I should be more open to asking for people's help even with my noob questions. But in the long run, maybe I am learning more by finding the answers on my own. Hmmm? Anyway, here's a small skeleton I made while I was NOT coding.

Thursday, May 19, 2016

://BEGIN: Pixelart

Outside of the header of this blog (which I made few days ago) I never tried my hand at pixel art. I was always fascinated by it, but in the midst of learning Photoshop, Illustrator and other things used in graphic design, I never found time to give it a try. So today, I gave a 8x8 sprite a try...

I just went to pixeljoint looking for inspiration, as their search engine has options for looking up art by pixel dimensions. After I found an 8x8 sprite I liked, I have redrawn it in the Pico-8 palette using the free version of Aseprite (I will eventually buy the proper full version as soon as I have $15 to spare). Next I tried some walking animation and found it really tricky on such small resolution. In the end I cheated a bit and looked up the frame-by-frame animation of the sprite I was basing this guy on. I just cut the amount of frames in half (again, thinking of limited sprite space on Pico-8) and came up with this guy...

He is far from perfect, but it was a good exercise. If I have learnt anything from it, is that making 8x8 sprites is hard. If I ever need a protagonist for a game, he will be at least 16x16.

Wednesday, May 18, 2016

Ball and paddle physics!

One thing that really disappointed me with the write-in game from Pico-8 Zine was the constant angle at which the ball travels. It was good as an introduction to programming goes, because it was so simple, but it was really boring from a gameplay standpoint. If I wanted this game to be something more than just a proof of concept, I had to find a way to improve this mechanic.

This was not an easy task. Finding and implementing the solution took, on and off, couple of days of brainstorming followed by trial and error in Lua. But, with some old school pen&paper math, and a little help of google I managed to get the ball to bounce at different angles, depending which part of the paddle it hits. Now the game requires some strategy on top of reflexes.


***

THE PROCESS

The problem here was to figure out how to change the angle at which the ball travels after hitting the paddle. It was an issue mainly because everything in this game was created using X and Y coordinates, and even if it didn't, as far as I know (and I might be very wrong), Pico-8 doesn't offer a function to move a graphic at an angle. Also, I didn't want to jump into messing with angles just yet. So, I had to find a way to translate angles to coordinates.

Fortunately I remembered that vectors are a thing, so that was my starting point. The game as I had it at that point used value of 3 for both ballxdir and ballydir, which made the ball travel at a 45 degree angle. If I changed one of the values (in my case, X), the angle would change. Sadly this meant that the overall speed would change too, because Y stayed constant. So depending on X, the ball would go either very fast or very slow. Not good.


KEEPING THE SPEED CONSTANT

I managed to solve this by just drawing out the problem on graph paper and looking for some patterns. Right now it is so obvious to me that the speed I was looking for was the hypotenuse of a right triangle with sides equal to  ballxdir and ballydir values. But, at the time, it felt like a great discovery worthy of celebration. From that it was pretty easy to calculate speed and then make the ballydir change to keep that speed, thanks to this Greek guy named Pythagoras, his fancy a2+b2=c2 theorem and the PICO-8 manual which gave me the SQRT function.

ballspeed=sqrt(ballxdir*ballxdir+ballydir*ballydir)
--this is where the
--code to make the ball
--change horizontal direction
--depending on where it hit 
--the paddle would go
ballydir=sqrt(ballspeed*ballspeed-ballxdir*ballxdir)*(-1)
 --multiply by -1 to make 
 --the ball travel up

Now I was able to change the the value of horizontal travel for the ball and keep the speed from going haywire. Now I just needed a good way to generate the horizontal travel value (ballxdir) depending on where the ball hit the paddle. If it hits it dead center, the ball should travel almost straight upwards (exact straight is boring) and the further from the center the ball hits, it should bounce of at a smaller angle (larger ballxdir).

MAKING ANGLED BOUNCES

This is where I once again took out my pen and paper and started drawing. I have split the paddle down the center (so between 12th and 13th pixel, as the paddle is 24 pixels wide). I wanted everything to the left of that dividing line to bounce the ball left (so negative X) and everything on right, right (positive X) The first idea was make the ballxdir equal to how many pixels away from the center of the paddle the ball hit. So 1 at 1 pixel, 2 at 2 and so on. That made the ball go like crazy very quick. I tried to fix it by limiting that value with formula: ballxdir=padw/6-6. That gave me values between -6 and 6, but it was still too much (also generated some bugs with the Pythagorean theorem). Narrowing it down to even 4 with IF functions made big chunks of the sides of the paddle always bounce back at -4 or 4, which was functional, but not much fun. I was getting somewhere, but it wasn't it. So I followed the programming advice I have read multiple times - go and find your answers.

I googled "breakout physics pythagorean theorem" and stumbled upon this gamedev stackexchange topic. It is originally for Java, but the code is explained very well, so I was able to transplant it into my game. Instead of using pixels (a mindset I pushed myself into by thinking of low rez games), the advice there tells you to "calculate the position of the ball relative to the center of the paddle, and express this as a number between -1 and +1". Then, multiply that by current speed so it will give out an horizontal movement that is lesser than the overall speed (so it won't mess up the  pythagorean theorem), but makes the value varied enough to give a crazy huge amount of angles! This worked perfectly for me! I ended up with this code:

 function hitball()
 --check if ball is within paddle
  if ballx>padx-2 and
  ballx<=padx+padw+1 and
  bally>pady-6 and
  ballydir>0 and
  bally>padx+1 then 
  --pitagoran therum keeps
  --overall speed constant
   ballspeed=sqrt(ballxdir*ballxdir+ballydir*ballydir)
   --change ball angle
   --based on where the ball
   --hit the paddle
   padcenterx=padx+padw/2 
   hitx=(ballcenterx-padcenterx)/(padw/2) 
   ballxdir=ballspeed*hitx 
  --speed up the ball  
   ballspeed+=0.05
  --compute ball y direction 
  --to keep speed constant 
   ballydir=sqrt(ballspeed*ballspeed-ballxdir*ballxdir)*(-1)
    sfx(1)
    score+=10
  end 

Now that I am finally happy with the core gameplay mechanic, I can move to introducing some other things into the game...like graphics or enemies. While the former won't be too much of an issue (I already experimented with the ball sprite), the latter will be something completely new to me. I guess I will check out more tutorials and get into source code of some of the Pico-8 games.

Oh, and while we are on the topic of Pico-8 games, I want to give a shout out to Josh Millard from Pico-8 BBS, whose game Arkanoi-8 pushed me to implement better ball physics on my own (in a big part because I don't really understand his advanced code, so I couldn't copy it ). Thanks Josh!

Monday, May 16, 2016

://BEGIN: Pong-esque

For my first game I have decided to create a simple paddle game. Mainly because the first issue of the amazing Pico-8 Zine gives you the code of a single player variant of pong to type-in. It was a great read for someone like me, because it explains what every snippet of code does. I was not just blindly typing some arcane formulas (as it was the case with 80s magazine type-in programs), but actually learning what each part of the code does.

Around an hour later I had a functional game! Sure, it was a super simple and nobody would look at it twice, but it was mine. I made that thing. For someone whose only previous programming achievements were a calculator and a hangman type game, both text mode only, this was a great feeling.

The code from the magazine covered just the basic gameplay. Press button to start, bounce the ball to get score. If you lose a ball, it just reappears and you play until you run out of lives. Once this happens, the game just stops. Done. If you are just starting your programming journey, I think things like this zine's tutorial are a great way to do it. Not only it slowly teaches you the basics, but it gives you something that you can actually play in short amount of time. Sure it gives you a really barebone product, but I think it was a brilliant tactic, because you will want to expand it on your own. After playing for a while I wanted to implement things like "Game Over screen" or ability to serve the ball from the paddle. I have willingly stepped into an uncharted territory, trying to code things on my own. To my surprise, I was able to implement few extra features the same afternoon.

SERVING

First thing that bothered me was that the ball would just start flying on its own after you lost a life. Instead, I wanted to be able to hit a button to serve a ball after losing a life. That was pretty easy on its own: just add a variable (newball) that stops the ball from moving  after you lose a life. But having a ball just hanging in the middle of the screen wasn't fun either. Instead when you lose a life, I have put the ball in the middle of the paddle (ballx = padx+padw/2) and made it move with it (using the same formula for ballx that I use for padx when left or right cursor is held) until you hit a button to let it go. This would be very handy if I wanted to turn this game into a Breakout/Arkanoid clone (spoiler alert - I do).

BALL SPEED

The constant speed of the ball turned out to be very boring. Like "I would quit the game before I even lost a life" level of boring. So I decided to spice it up a bit. The speed of the ball in this game is basically how many pixels the ball travels each frame (4 vertical and 3 horizontal in the Pico-8 Zine version, kept in the ballydir and ballxdir variables). Knowing that, I just added 0.1 to both those variables each time the ball bounces off the paddle. Simple solution that made the gameplay a little bit better.

GAME OVER STATE

Another anointing thing was not being able to restart the game after you lose all your lives. I added a simple IF function that prints a game over message after the player loses all lives (lives<0). When the player hits Z (as directed by game over message) everything restarts: score goes down to 0, lives go up to 3, speed goes down to original values (that's something that I changed later to restart after losing a life instead, it made for a better game). The program changes the newball state back to the value that allows serving.  There was a bit of trial and error here (that still left a bit of iffy code behind that needs fixing), but I am glad I solved it.

BUGS and DEBUGGING

To my surprise, bug fixing was actually really fun. It is probably because the code for this game is pretty short and simple, and, let's face it, this project is not really that important. I can see if I would have thousands lines of code for something else than a side project, bugs could be a real pain in the ass. Fortunately I have only run into few bugs so far. One when the ball would bounce multiple times while overlapping the paddle, the other would make the ball stuck on either left or right wall if you hit the ball "just right." Solving them was a bit of a process. I had to ask myself questions "why" this particular thing is happening and once I had the answer, I had to come up with some code to solve it. So far I think that debugging was the most rewarding thing when it comes to learning how to program. Knowing the syntax, even figuring out how to introduce new gameplay elements is great, but getting down to a root of a problem, and tweaking the code to prevent the program from doing it again will really put you in a programming mindset.

HELLO WORLD!

Welcome to Level 0 Game Developer, a blog about trying to learn how to make video games from scratch.

This is a somewhat / not really a companion site to Level27Geek, my main blog where I (infrequently) write about things related to tabletop gaming. Thanks to my fascination with all kinds of games, I have some knowledge about game design and the underlying mechanics. I am, however, almost completely in the dark when it comes to video game development. The only programming I ever did was BASIC around 15 years ago. Any art I ever created was not made with games in mind, and I never tried my hand at sfx or music. Hence, the "level 0" in the title. Yet, I have this vision of grandeur that I can prove that learning how to make video games is not that hard.
Well, let's see how that goes...

***

For my first attempts at gamedev I will be using PICO-8. It is a platform that bundles a programming environment with art and sound editors in an 80s inspired, "fantasy console" package. I have chosen it for few reasons:

  • PICO-8 forces you to code. Sure, it is "only" in LUA, but it will still help you develop a proper programming mind-set and make you used to typing every bit of code on your own. And while it is great that nowadays you can make a game without knowing how to program, having that skill and understanding the underlying code will benefit anyone in the long run. 
  • PICO-8 limits your scope. This platform is similar in power to the early 80s personal computers like the BBC Mico, or ZX Spectrum. It has limited resolution, color palette, sound, controls, memory... basically everything. Constraints boost creativity, but more than that, they stop you from overwhelming yourself. When learning to make games you should start small - and I think that PICO-8 is great for that.
  • PICO-8 is about sharing. All of the games on the platform are free, but that's not the best part. When you load a cart into PICO-8 you have access to its source code, art and sound! This is a great resource for learning, as you can see how others have solved problems you might be encountering and just analyze how different games work. You can tweak that code or even build upon it to make your version of the game, as most carts bear a Creative Commons license.
  • PICO-8 is nostalgic. I can't say that the retro aesthetic didn't appeal to me...and it is not really about the lowres pixel artstyle and chip bleerps. I have grown up with a Commodore64 followed by Atari ST and various Amigas. I've been there when the demoscene reigned supreme and people made awesome games from their bedrooms. I have tried be a part of this movement, but it was simply beyond my skill at that age. On some levels, PICO-8 let's me relive those days.