Jump to content
Atarius Maximus

My 2k Game Experiment - Gate Racer

Recommended Posts

Here's my experiment in making a 2k game, it's the first time I've tried to. I thought I'd try my luck just to see if I could make something fun to play with some replay value as well. My goal of course was to have at least 2048 Bytes free in a 4K build and I ended up with 2053 bytes free. I've always thought it would be impossible so I thought I'd try and prove myself wrong. I know "fun" is relative so I just made something I thought I might like to play more than once. :)

 

The game is called 'Gate Racer'. The object is to drive through the scrolling gates while avoiding hitting the barriers, sides of the road, or oil slicks. There's a clock timer (that shows minutes/seconds/tenths of seconds) at the bottom and the object is simply to survive on the road as long as you can. Your final time is displayed when you crash, hitting fire then restarts the game. I implemented left and right velocity to make it more interesting (and require a bit more skill), and the gate size and location is randomly generated. The gates will get smaller as you progress and do so very quickly. There is also a powerup you can collect (a white block on the screen) that will make you invincible for two gate passes.

 

I started thinking about what style of game would lend itself to such a small size. One of my all time favorite 2K games is Activision's Dragster and a good game lasts less than 7 seconds. With that in mind, I wanted to come up with a short game that requires some skill (and practice to get better) but also includes some randomization to increase the replay value. I had all sorts of ideas for this game that wouldn't fit, in addition to some core items that I really wanted in there that also wouldn't fit.

 

Here's a list of small features I wanted but removed due to lack of ROM space in 2K. These features would require an additional 75 bytes and would make the game feel a bit more 'complete' IMO.

 

-> You can't use the reset switch in-game, it needs 10 bytes. It's a short game anyway and pressing fire restarts after death.

-> No sounds. I removed the engine Rumble sound, it needs 16 bytes. I didn't put in a crash sound either, that needs another 16 bytes.

-> I eliminated my line of code that randomly increases size of the gate, it needs 13 bytes. It would allow for slightly longer games.

-> I eliminated the car moving slightly up the screen during the game, it needs 13 bytes. It would progressively make the game harder.

-> I eliminated the 'press fire to start' option at beginning of game, it needs at least 7 bytes. The game starts up as soon as you power it on.

-> The oil slick doesn't reset to the top when you die. Not sure how many bytes it would take to fix it, prob 13 or less

 

There were other concessions as well. I didn't even try to implement my ideas with the ball or missiles due to lack of space. There could be oncoming cars, variable speeds on the road, the ability to shoot oncoming items, sprite animations, levels of difficulty, color changes, a title screen, moving gates, and lots of other things I'm not thinking of right now.

 

If you want to compile this yourself you'll need the custom score graphics file and the timer.inc file included in the zip. The code is well commented, feel free to make suggestions. It's possible some of my code could be optimized to save a few bytes here and there.

 

So, did I succeed? Beats me. It was definitely challenging and I've never been so focused on saving a single byte of space. The end result isn't horrible but I think it could be a whole lot better in 4K.

 

Steve

 

UPDATE:

 

Final version attached. It includes most of the things I couldn't fit in initially plus more, thanks to all the people who assisted with their comments and suggestions. The allfiles zip contains the source and all the modified include files that you'll need to compile it. The oldversions zip contains binaries of all the development versions.

GateRacer_Final.bin

GateRacer_AllFiles.zip

post-2143-0-19685600-1362082786_thumb.jpg

post-2143-0-75557300-1362082786_thumb.jpg

OldVersions.zip

  • Like 1

Share this post


Link to post
Share on other sites

That's pretty awesome! If your game is under 2k, though, why not put it in a 2k cartridge?

set romsize 2k

 

Also, if you used a custom .inc inlcludes file, i'll bet you could get an extra 100-200 bytes by cutting out all the stuff you don't need.

Share this post


Link to post
Share on other sites

I mentioned why it's not a 2k bin in the remarks in the source code but forgot to mention it in my original post. It won't compile with the 'set romsize 2k' option because of the custom score graphics file, it's been expanded.

 

When compiling, I get this error:

 

Error: segment: f7fc vs current org: f80c

GateRacer.txt.asm (2820): error: Origin Reverse-indexed.

 

I need to remove 16 bytes from the ORGs at the beginning of the file as explained by SeaGtGruff here: http://www.atariage....e-graphics-asm/. I tried it and couldn't get it to work. Honestly it didn't bother me that much as despite the 4K binary there's only 2k of data in it. It's still a 2k game. :)

 

Steve

 

EDIT: Oh yeah, about the timer.inc file. I didn't look at it at all, SeaGtGruff wrote it and I just used it as-is. I suppose it's possible something could be trimmed in it but I kind of doubt it.

Share this post


Link to post
Share on other sites

After reading this post and fiddling around, I figured out what was wrong. The fixed, working score_graphics_timer.asm file that will allow the set romsize 2k option is attached below.

 

The problem is this, from the top of the file:

 

ifconst ROM2k
 ORG $F7AC

 

As Gruff explains, since you're using a version of score_graphics.asm that's just had two extra sprites added (for the . and the : ), you need to decrease that ORG by the equivalent of 16 bytes, since each sprite is 8 bytes (1 byte per row, 8 rows per sprite), which leaves you with this:

 

ifconst ROM2k
 ORG $F79C

 

Also, if you change every "if something > 0 ..." to "if something ..." and every "if something = 0 ..." to "if !something ...", you save JUST enough bytes for sound effects. See attached. :D

GateRacer.zip

score_graphics_timer.asm

Share this post


Link to post
Share on other sites

After reading this post and fiddling around, I figured out what was wrong. The fixed, working score_graphics_timer.asm file that will allow the set romsize 2k option is attached below.

 

The problem is this, from the top of the file:

 

ifconst ROM2k
ORG $F7AC

 

As Gruff explains, since you're using a version of score_graphics.asm that's just had two extra sprites added (for the . and the : ), you need to decrease that ORG by the equivalent of 16 bytes, since each sprite is 8 bytes (1 byte per row, 8 rows per sprite), which leaves you with this:

 

ifconst ROM2k
ORG $F79C

 

Also, if you change every "if something > 0 ..." to "if something ..." and every "if something = 0 ..." to "if !something ...", you save JUST enough bytes for sound effects. See attached. :D

Fantastic! Thank you so much for your help. I'm out of time to make any changes for today, but hopefully I'll be able to take a look again this weekend. Adding audio to this game would definitely make it better :)

Share this post


Link to post
Share on other sites

I feel this should be renamed Drunk Racer. Controls shouldn't be part of the challenge :) That being said, it's awesome for what it is! Complete gameplay in 2k.

 

I never knew about the timer score mini kernels. We REALLY, really need a pinned topic with all the mini kernels that have been 'brewed over the years..

Share this post


Link to post
Share on other sites

Do it, loon.

 

I kind of agree with loon. The amount of weave may be a bit excessive, especially since it largely comes down to chance: whether an oil stick happens to have spawned in front of where you were trying to go or not and whether or not the opening spawned close enough for you to reach it without careening out of control. Maybe making it 1/2 or 1/4 the current amount would allow it to come down to a bit of skill rather than pure luck.

Share this post


Link to post
Share on other sites

Do it, loon.

 

I kind of agree with loon. The amount of weave may be a bit excessive, especially since it largely comes down to chance: whether an oil stick happens to have spawned in front of where you were trying to go or not and whether or not the opening spawned close enough for you to reach it without careening out of control. Maybe making it 1/2 or 1/4 the current amount would allow it to come down to a bit of skill rather than pure luck.

 

Thanks for the feedback, Cybearg and theloon. I agree with you guys about the controls, it's difficult. I also know that the randomization does introduce the element of luck to get a high score. I had considered naming it "Ice Racer" with a blue background because of the controls. :) I'll revisit the controls and see what I can do. I could completely remove the code that makes you slide back and forth as that would free up a ton of space for other things.

Share this post


Link to post
Share on other sites

In a way you've got the same challenge as the developers did in Marble Madness: make the controls feel lose and analogue whilst not being frustratingly out of control.

Share this post


Link to post
Share on other sites

Thanks to Cybearg's help, I was able to make a few enhancements and compile it in an actual 2K bin. This new version adds some sounds, there's now an engine rumble sound when you're playing and a crash sound when you crash. The crash sound will stay on until you reset, there was not enough space to set a timer to turn it off. I changed the oil slick sprite to the ball to save a few more bytes, and (most importantly) I changed the left/right velocity to make it a bit easier to control your car. It's much less frustrating now and you'll crash a lot less. There's now 4 bytes left in the 2K ROM, not really any space left to make enhancements in this version. I'll update the first post with the new version shortly. I haven't spent much time playing the new version yet, I'll post my new high score a bit later. :)

  • Like 1

Share this post


Link to post
Share on other sites

I forgot to mention one additonal improvement in my last post. I was able to re-add the "press fire button to start" option. The game now doesn't start as soon as you launch it, you need to press the joystick button to begin. A minor thing, but a big improvement. :)

Share this post


Link to post
Share on other sites

@theloon - not a bad idea. That would save some more space. If I did that, any thoughts on what to use the extra space for? It of course wouldn't be very much. :)

Share this post


Link to post
Share on other sites

If I had my druthers the slide would be even less. The oil slick should use missile1 so you can color it black. Also, the oil slick moves at a different rate from the road. Not sure if you already do this but you could add a speedup over time.

Share this post


Link to post
Share on other sites

Maybe you'd have enough space left to allow the explosion sound to stop after a while if, instead of plotting out the entire playfield, you drew it with two pfvlines, instead:

 

pfvline 0 0 11 on
pfvline 31 0 11 on

Share this post


Link to post
Share on other sites

This is rather fun. Only got to 32.5 seconds so far. I think you've got a good game. I suggest going all out for a 4k update of this game with the things you would have added. I like battling the momentum of the sharp left and right turns.

Share this post


Link to post
Share on other sites

I think you could shave a few bytes here

(untested)

 

rem player movement code
rem
if joy0right then direction = 1
if joy0left then direction = 0
if !joy0left && !joy0right && direction && velocityx then velocityx=velocityx-0.0030
if !joy0left && !joy0right && !direction && velocityx then velocityx=velocityx+0.0030

 

rem player movement code
rem
if joy0right || joy0left then direction = direction ^ 1 : goto skip
if !velocityx then goto skip
if direction then velocityx=velocityx-0.0030 else velocityx=velocityx+0.0030
skip

Share this post


Link to post
Share on other sites

That car wreck sprite feels like it could be cut out. Could you play with NUSIZ and/or color cycle the car sprite instead?

Excellent Idea. I removed the crash sprite and it freed up a bunch of space.

 

If I had my druthers the slide would be even less. The oil slick should use missile1 so you can color it black. Also, the oil slick moves at a different rate from the road. Not sure if you already do this but you could add a speedup over time.

I've got the slide pretty much how I want it in this version, and added a no-slide option on the right difficulty switch. I changed the oil slick to missile1 as you suggested, it does look better. The oil slick does not speed up over time.

 

Maybe you'd have enough space left to allow the explosion sound to stop after a while if, instead of plotting out the entire playfield, you drew it with two pfvlines, instead:

pfvline 0 0 11 on
pfvline 31 0 11 on

Great Idea Cybearg, that worked perfectly and saved some space.

 

He wouldn't need the borders of the road drawn with playfields statement if he used PF0 = %10000000 or something similar

Great Idea. I used that along with the pfvline and I really like how the road looks now.

 

This is rather fun. Only got to 32.5 seconds so far. I think you've got a good game. I suggest going all out for a 4k update of this game with the things you would have added. I like battling the momentum of the sharp left and right turns.

I most likely will expand the game in the future, I just want to be happy with the 2K version first. I find it hard to know when to stop working on a project. :)

 

I think you could shave a few bytes here

(untested)

Thanks bogax. I used your idea and shaved off a few bytes in the player movement code.

 

Thanks to everyone for all the suggestions! I was able to use everyone's ideas in this latest build. The new version is in the first post again.

 

Here are the latest Changes:

 

1. Added Left Difficulty Switch option: A=Oil Slick Off, B=Oil Slick On.

2. Added Right Difficulty Switch option: A=X/Y Velocity Off, B=X/Y Velocity On.

3. The Crash sound will now turn off after a few seconds.

4. Timer font changed and it now turns red when you crash.

5. Eliminiated Car Crash sprite, your car now flashes colors after a crash instead.

6. Road graphics changed.

Share this post


Link to post
Share on other sites

One other idea besides pf-whatever line is to remember that the playfield is just a bunch of variables. When the horizontal blockade lines reach the bottom of the screen you could add new exists just by zero-ing var44, var45, var46 or var47. Likewise you could add another horizontal blockade by making var44, var45, var46 or var47 = %11111111

Share this post


Link to post
Share on other sites

You're using the standard kernel

with no funny stuff right?

And your playfield is very simple

I think you could shave a few more

bytes if you replace your playfield

statement with this.

There's only one value in your

playfield (here called pfedge) other

than zero this just pokes it

directly in a loop with out having

to duplicate it in the code to fill

the playfield.

Hope I got those locations right

(untested)

 

const pfedge = $80
const pfleft = $A4
const pfright = $A7

pfclear
for i = 0 to 48 step 4
pfleft[i] = pfedge : pfright[i] = pfedge
next

anyway, you could try it

 

edit: oops one line short, fixed now I think

 

edit again after reading theloon's post

I forgot the pfvariables have names

so using them it would be

const pfedge = $80

pfclear
for i = 0 to 48 step 4
var0[i] = pfedge : var3[i] = pfedge
next

Edited by bogax
  • Like 1

Share this post


Link to post
Share on other sites

I was just messing around with modifying the std_kernel.asm file, looking for things that I may be able to remove. I took out the sections below, which seem to relate to reading paddles and the "shakescreen" function, neither of which I'm going to be using. I now have 72 bytes free when compiling. :) I may still be able to trim a few more things out. Now I can at least add in a basic titlescreen and the crash sprite.

 

;--------------------
ifconst shakescreen
  jsr doshakescreen
else
  ldx missile0height
  inx
endif
;--------------------
ifconst readpaddle
  stx paddle
else
  sleep 3
endif
;--------------------
ifconst shakescreen
doshakescreen
  bit shakescreen
  bmi noshakescreen
  sta WSYNC
noshakescreen
  ldx missile0height
  inx
  rts
endif
;--------------------

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...