Posted September 10, 2023 by Lucas Castro
Just released KATA, my entry for the Pico 1K Jam 2023, which the games whould be created within 1024 bytes, and now I'm going to share a bit about this experience.
For the first sight I thought the size limitation would be OK for the idea of creating a "Genius" inspired game as the logic at all is pretty simple.
Actually, I did something like this on my first semester of programming classes, as an exercise to study Pascal programming language. On that season it had the 4 colours (green, blue, red and yellow) really like the original Genius. Also it had sounds for each color and on game over. Unfortunently I lost it after format my computer.
Anyway...
This time I wanted to bring a bit of martial arts to the game because, a couple of years ago, I practiced Capoeira, a Brazilian martial art, and on the classes it's common to have a sequence of moves to repeat. I learned this is an influence of oriental martial arts, like Karate, and the term for this kind of exercise is Kata. You can learn a bit more on Wikipedia.
As a jam requirement, we can not use pre-created sprites, sounds, etc, what means that all the content of the game needs to be generated by code.
Therefore, if someone pastes the game code into Pico-8, the game should run perfectly.
However, it makes harder to generate sprites by code having a code size limitation.
So, after create a prototype using numbers and created sprites to see the game with the images.
There were 7 sprites, one for the idle player and the others for each moves:
With that I thought: "Okay, now I can figure out a way to make them by code."
The first attempt was to use simple built-in functions to draw the figther, like RECTFILL, CIRCLE, and PSET.
Even still being worried with the number of code I managed to create one draw with this strategy.
However I felt that would be hard if I wanted resize the sprites and I figured out that we can do it with SSPR function that expects a sprite index.
The second attempt was to handle the memory and create sprites as I had drawed them.
For that I had to understand how the memory is organized in Pico-8 and how manipulate it.
It took a couple of hours to understand. No problem, I was curious to understand this topic of Pico-8!
After that I had to write a function because functions like RECTFILL doesn't exist to set memory.
Keep in mind we need to to set a memory slot for each two pixels of the draw.
So the idea is send a table as argument with all the pixels should be set in a sprite.
For example:
draw(1,{11,12,19,20,25,26,27,28,29,33,37,41,42,43,44,45,50,52,58,60},0,7)
And the belt? That has another color!
For the belt I called draw again after the previous one, but without the background argument.
draw(1,{34,35,36},9)
Now I can referer the sprits using the SPR function and stretch them using the SSPR.
spr(1,75,73,1,1,true) sspr(16,0,8,8,20,50,32,32)
Having all the sprites created and the game running like I wanted, it's time to see how many bytes I should cut off to fit in 1024 bytes.
I had 224 bytes to delete!
Wasn't easy to figure out ways to reduce such bytes. It last some hours.
Following goes the actions I took.
if (s==0 or s==3) and btnp(❎)
... leave the OR operator after the AND evaluation:
if btnp(❎) and (s==0 or s==3)
if btnp(5) then b=5 end
... use the one line if:
if (btnp(5)) b=5
if s==1 then ... elsif s==2 then ... end
... avoid ELSEIF when is possible:
if s==1 then ... end if s==2 then ... end
function draw(s,l,f,b) local z=0 ... end
... use global variables.
function draw(s,l,f,b) z=0 ... end
Ok, that's danger and we need to have attention as different locations can have local variables with same name.
pc(20,"orange belt")
.. only remove them:
pc(20)
ctr={[0]="⬅️","➡️","⬆️","⬇️","🅾️","❎"} ... print(ctr[sp],32,90)
... prefer remove the zero and deal with it:
ctr={"⬅️","➡️","⬆️","⬇️","🅾️","❎"} ... print(ctr[sp+1],32,90)
function _init() init_game() end function _update() ... end function _draw() ... end
Use only the _update function:
init_game() function _update() ... -- draw code goes here ... end
Honestly, I still don't know the side effects of this, but just worked!
Even after all the previous changes (and the more obvious ones like reduce naming, spaces, etc) I still had 97 bytes to reduce 😭
Confess I tought of reducing the features, like the "start game" message and the number of sprites. But I was pretty satisfied with the scope I didn't want to do that.
The solutions cames when I minify the source code using the fantastic Shrinko8 tool.
Yeah, 1024 bytes!!!
Probably, it's possible reduce even more the size, like improving the drawing algorithm, but already is good enough to submit the game.
This experience was fun and for me!
Hope you have liked!
Let me know how was your experience with those challenges I mentioned?