Jump to content
IGNORED

Dragon Racer: Trials of the Wyrm


Revontuli

Recommended Posts

I am currently finishing up two very large (non-Atari) coding projects, and I decided to relax by making a nice, small-scale Atari 2600 game. I've done some experiments with Batari Basic before, but nothing I'd have been up for sharing. A "What Atari Game Are You?" quiz gave me the result "Dragon Racer," so I decided to take that idea and run with it.
Dragon Racer: Trials of the Wyrm
Dragons compete to collect gems for their hoard across a variety of locations. Each new gem only appears after the last has been taken, revealing a path through each treacherous track.
Download the latest (and semi-final) build here:

Dragon Racer Screenshot 1

Dragon Racer Screenshot 2

 

The first to collect 32 gems wins! Alternatively, a player might decide to run a time trial - in which case they must try to run through three laps of a track in the fastest time possible. The scoreboard will show how many gems each player has collected, or the time/laps the player has during the time trial.

Select: Choose track - As you look at each layout, you can see the gems revealing the path you will need to take.

Difficulty (Left/Right):
AA: Two Human Players
AB: Human Player Solo Time Trial
BA: Human Player vs Fast AI
BB: Human Player vs Slow AI

 

Use your joystick to change the speed and direction of your dragon.

Pressing the joystick button will have a dragon breathe fire, which is somewhat steerable. If a dragon hits a wall or their opponent's fire, they will disintegrate and reform slightly behind the next gem on the track, stunned for a few seconds.

 

The file is based on an 8kSC ROM - It seems to work fine on a good ol' sixer, but I haven't tried the game on any other hardware. While I'm a little cramped for new features at the moment (8k and 2000 cycles go quickly when you're having fun!) I'd be curious as to what people think of the speed, stun time, scoring, and other values in the game.

 

DragonRacer_6_4_2018.bin

 

(Newer version with momentum/fire fixes at boundaries - thanks for everyone's feedback and help!)

DragonRacer_7_25_2018.bin

 

Now a version designed for the Atari Flashback Portable, fixing its scoring bug (thanks, Karl G!):

DragonRacer_9_25_2018_AFB.bin

 

Latest version at top of the post!

 

Many thanks to the people whose posts and helpful reference material I've found through this site!

 

[Edit: June 4 version tones down color flashing effects]

[Edit: July 25 version fixes some momentum/fire issues at boundaries]

[Edit: September 25 version has Atari Flashback Portable score fix]

[Edit: March 6 update - semi-final, with font change and AFP fixes wrapped into one binary]

Edited by Revontuli
  • Like 8
Link to comment
Share on other sites

Thank you all for playing!

The fast AI moves at the player's maximum speed all the time - breathing fire gives you an advantage, although I've found that getting a perfect score (i.e. collecting 32 gems while the AI collects none) can be a challenge even on the slow AI mode. And the arena can be pretty brutal. I might try making the fast AI a -little- faster, but that figures in to some of the issues I have below regarding fixed-point numbers.

I'm on the fence with the color cycling backgrounds, they can be a bit much - in my defense I think it looks better on a CRT than on a digital display.

I do have a few questions, or at least a request for advice. Part of this project was to see if I could get a fixed-point number based control scheme with acceleration/velocity working. Being able to add a decimal delta to a sprite position each frame is handy, to say the least. I found that using negative values -almost- works, but comparisons with them don't really seem to, so I need an extra boolean to basically handle whether I add or subtract a delta each frame. Some searches online found I was not alone in having these kinds of issues, but I was curious if there were other approaches.

For instance, handling the horizontal movement of the player currently goes something like this:


 _SwitchDirTest_b3{3} = 0

rem we are moving horizontally, we should check to see if we change directions

 if _P0_VEL_X > 0 then _SwitchDirTest_b3{3} = 1

rem Here we increment the player input, accelerating if the joystick is used

 if joy0right && _DRAGON_P0_MOVING_RIGHT_b1{1} then _P0_VEL_X = _P0_VEL_X + _DRAGON_ACCL
 if joy0right && !_DRAGON_P0_MOVING_RIGHT_b1{1} then _P0_VEL_X = _P0_VEL_X - _DRAGON_ACCL

 if joy0left && !_DRAGON_P0_MOVING_RIGHT_b1{1} then _P0_VEL_X = _P0_VEL_X + _DRAGON_ACCL
 if joy0left && _DRAGON_P0_MOVING_RIGHT_b1{1} then _P0_VEL_X = _P0_VEL_X - _DRAGON_ACCL

rem If we hit 0, then we have changed directions

 if _P0_VEL_X < 0 then _P0_VEL_X = 0
 
 if _P0_VEL_X = 0 && _SwitchDirTest_b3{3} then goto __skip_direction_change_horiz
 
 if _P0_VEL_X = 0 && !joy0right && !_DRAGON_P0_MOVING_RIGHT_b1{1} then _DRAGON_P0_MOVING_RIGHT_b1{1} = 1
 if _P0_VEL_X = 0 && joy0right && _DRAGON_P0_MOVING_RIGHT_b1{1}  then _DRAGON_P0_MOVING_RIGHT_b1{1} = 0

__skip_direction_change_horiz

 if !_DRAGON_P0_MOVING_RIGHT_b1{1} then REFP0 = 8

rem Then I cap the speed.  The comparison was not working when I tried to use negative values.  

 if _P0_VEL_X > _DRAGON_SPEED then _P0_VEL_X = _DRAGON_SPEED

rem We then add the delta to the sprite position later on, according to the bit values in variables like _DRAGON_P0_MOVING_RIGHT_b1.

 if _DRAGON_P0_MOVING_RIGHT_b1{1} then _P0_L_R = _P0_L_R + _P0_VEL_X
 if !_DRAGON_P0_MOVING_RIGHT_b1{1} then _P0_L_R = _P0_L_R - _P0_VEL_X

The vertical component (and system for player1/AI) are pretty much the same idea.

It's a mess of if/thens, and a little convoluted (I may have a direction flipped around somewhere in there), but it works. Reading about the fixed point number system, I think I could see how I could incorporate negative values (and felt like I was close), which could reduce quite a bit of branching, but at the moment a wacky system that totally works beats an efficient system that almost works. I am curious, as while what I have right now works fine for this game, I would like to optimize this system for future games.

Link to comment
Share on other sites

I'm on the fence with the color cycling backgrounds, they can be a bit much - in my defense I think it looks better on a CRT than on a digital display.

Modern consoles have warnings which say that exposure to certain patterns or backgrounds on a television screen may trigger epileptic seizures or blackouts in some people and these conditions may trigger previously undetected epileptic symptoms or seizures in persons who have no history of prior seizures or epilepsy. When in doubt, don't quickly change the color of large sections of the screen.

 

Besides that, it can be irritating for people who just have sensitive eyes:

 

randomterrain.com/atari-2600-memories-game-design-guidelines.html#no_flashing

 

randomterrain.com/atari-2600-memories-batari-basic-commands.html#ex_pulsation_examples

Link to comment
Share on other sites

Modern consoles have warnings which say that exposure to certain patterns or backgrounds on a television screen may trigger epileptic seizures or blackouts in some people and these conditions may trigger previously undetected epileptic symptoms or seizures in persons who have no history of prior seizures or epilepsy. When in doubt, don't quickly change the color of large sections of the screen.

 

Besides that, it can be irritating for people who just have sensitive eyes:

 

randomterrain.com/atari-2600-memories-game-design-guidelines.html#no_flashing

 

randomterrain.com/atari-2600-memories-batari-basic-commands.html#ex_pulsation_examples

 

More than fair - I turned off the background color cycling, and toned down the playfield color cycling, and updated the initial post with the new build.

  • Like 1
Link to comment
Share on other sites

I love physics based code, so I've played in this problem space before. Negative velocity can sometimes get a bit sticky, but you can do what you want without so many conditional subtractions/additions.

 

Something like this works for the core...

 

if joy0right then _P0_VEL_X = _P0_VEL_X + _DRAGON_ACCL
if joy0left then _P0_VEL_X = _P0_VEL_X - _DRAGON_ACCL
if joy0down then _P0_VEL_Y = _P0_VEL_Y + _DRAGON_ACCL
if joy0up then _P0_VEL_Y = _P0_VEL_Y - _DRAGON_ACCL
_P0_L_R = _P0_L_R + _P0_VEL_X
_P0_U_D = _P0_U_D + _P0_VEL_Y

When you want to check the sign of the velocity (for example, to point your dragon sprite) you can check if the "hi" byte of the velociy is >127 (negative) or <128 (positive).

 

With a comparison, bB automatically references the hi byte, so "if _P0_VEL_Y>127" will work, but I prefer to dim each part of the fixed point variable, to keep which part I'm accessing obvious...

 

dim _P0_VEL_Y_HI=w
dim _P0_VEL_Y_LO=x
dim _P0_VEL_Y=_P0_VEL_Y_HI._P0_VEL_Y_LO

...this also generates more sensible looking assembly source, as fixed point arithmatec refers to _P0_VEL_Y and _P0_VEL_Y_LO, instead of _P0_VEL_Y and "x".

 

To implement top speed, you need a wee bit of conditional code.

 

if P0_VEL_Y_HI>127 && P0_VEL_Y_HI<254 then P0_VEL_Y_HI=254:P0_VEL_Y_LO=0: rem sets a negative top speed of 2. (-1=255, -2=254, -3=253, ...)
if P0_VEL_Y_HI<128 && P0_VEL_Y_HI>2 then P0_VEL_Y_HI=2:P0_VEL_Y_LO=0: rem sets a positive top speed of 2. (1=1, 2=2, ...)

I think that's probably enough to get you there, but let me know if you have any questions.

 

[edit - technically the speed limit code above allows the speed to creep up past 2, before it gets tamped down to 2.0. You can swap out the speed limit code above for something like "if P0_VEL_Y_HI=2 || P0_VEL_Y_HI=254 then P0_VEL_Y_LO=0" if you want exactly 2.0 as the limit. You'd need a combo of the two techniques if the acceleration is ever >=1.0]

Link to comment
Share on other sites

 

When you want to check the sign of the velocity (for example, to point your dragon sprite) you can check if the "hi" byte of the velociy is >127 (negative) or <128 (positive).

 

With a comparison, bB automatically references the hi byte, so "if _P0_VEL_Y>127" will work, but I prefer to dim each part of the fixed point variable, to keep which part I'm accessing obvious...

 

dim _P0_VEL_Y_HI=w
dim _P0_VEL_Y_LO=x
dim _P0_VEL_Y=_P0_VEL_Y_HI._P0_VEL_Y_LO
...this also generates more sensible looking assembly source, as fixed point arithmatec refers to _P0_VEL_Y and _P0_VEL_Y_LO, instead of _P0_VEL_Y and "x".

 

To implement top speed, you need a wee bit of conditional code.

 

if P0_VEL_Y_HI>127 && P0_VEL_Y_HI<254 then P0_VEL_Y_HI=254:P0_VEL_Y_LO=0: rem sets a negative top speed of 2. (-1=255, -2=254, -3=253, ...)
if P0_VEL_Y_HI<128 && P0_VEL_Y_HI>2 then P0_VEL_Y_HI=2:P0_VEL_Y_LO=0: rem sets a positive top speed of 2. (1=1, 2=2, ...)
I think that's probably enough to get you there, but let me know if you have any questions.

 

[edit - technically the speed limit code above allows the speed to creep up past 2, before it gets tamped down to 2.0. You can swap out the speed limit code above for code that checks if the hi byte is 2, and clears out the lo byte, if you want exactly 2.0 as the limit. You'd need a combo of the two techniques if the acceleration is ever >=1.0]

 

 

Very helpful! I'll be incorporating this into future code.

 

Part of the issue is merging 8.8 (2 byte) and 4.4 (1 byte) types - I find things like velocity generally only need one byte (as far as resolution and scale), while things like position need two. Re-reading RandomTerrain's handy reference site, I think I found a way to reconcile things and getting a better grasp of the systems. Multiplying 4.4's by 16 should make them "compatible" with other variable types in certain circumstances, correct?

 

On the other hand, I'm realizing that the SuperChip option opens up quite a bit more RAM to play with, so it might be worth using the extra memory to avoid the 8.8/4.4 mixture headaches, I'll see.

 

Thanks again!

Link to comment
Share on other sites

Glad to help. :)

 

Part of the issue is merging 8.8 (2 byte) and 4.4 (1 byte) types - I find things like velocity generally only need one byte (as far as resolution and scale), while things like position need two. Re-reading RandomTerrain's handy reference site, I think I found a way to reconcile things and getting a better grasp of the systems. Multiplying 4.4's by 16 should make them "compatible" with other variable types in certain circumstances, correct?

Well, not quite. Since 4.4 uses the full byte to represent -8 to 7.9375, in a sense it's already scaled up. If you want to compare the whole number part with a regular variable, you'd want to divide the 4.4 by 16. But that only works if it's a positive number. You need to treat it differently if it's negative, and the whole thing becomes a bit patchwork.

 

To be honest, I try to stay away from mixing 4.4 and 8.8 types. A simple 4.4=4.4+4.4 takes 11 cycles. A simple 8.8=8.8+8.8 takes 20 cycles. But 8.8=8.8+4.4 takes 105 cycles (sometimes more) and uses an extra chunk of rom for some handling routines.

Link to comment
Share on other sites

To be honest, I try to stay away from mixing 4.4 and 8.8 types. A simple 4.4=4.4+4.4 takes 11 cycles. A simple 8.8=8.8+8.8 takes 20 cycles. But 8.8=8.8+4.4 takes 105 cycles (sometimes more) and uses an extra chunk of rom for some handling routines.

 

Ouch! With that in mind, I think I could scrounge up a few more bytes of RAM to turn the velocities into 8.8 types. A pity, really, since I doubt I'd need velocity to be more than 7.9 pixels/frame, and each component adds up in RAM when you're handling multiple sprites.

 

This is all great to know moving forward. If I go ahead with using more banks in future projects, I'll need to restructure what I did anyway, and it's good to know I can make this process a bit more efficient.

  • Like 1
Link to comment
Share on other sites

 

It seems to work fine on a good ol' sixer, but I haven't tried the game on any other hardware.

 

for the record, it's playing fine on my Flashback Portable (v.1.0)...

i'm struggling with the inertia, but that's a problem with my skills rather than with the game... :)

  • Like 1
Link to comment
Share on other sites

  • 1 month later...

Watch gameplay of this game on Twitch replay, or on YouTube soon

 

I finally caught the stream - thank you for playing, I'm glad you enjoyed it! My only regret is that you didn't try any of the other 3 race tracks (the Game Select switch will cycle through them). Your play session gave me some very good feedback on the game as well.

 

The "not firing at the top of the screen" bug comes from the momentum-based targeting. I'm not actually stopping momentum if you hit the screen boundaries, the dragon just gets shunted back onto the screen. The dragon fire comes directly from the mouth, and, if you hit the top of the screen, that momentum will carry the fire off the top of the screen immediately. You have to counter-intuitively press down on the joystick to "straighten out" the dragons so they shoot straight - of course that means you risk slamming into a wall.

 

Stopping momentum at boundaries would be the most obvious way to fix things, but it'd take a few more bytes of ROM than I currently have. A code revision should free up some space, though. I was also a little wary of having the boundaries halt the dragon, because it seems a little "safer" than I wanted the track to be, and controlling the dragon's momentum is basically the challenge of the game. It'd be worth it to make the dragon firing more intuitive, though.

 

All my rambling aside, it was great to watch folks playing and enjoying these homebrews - thank you again!

Edited by Revontuli
  • Like 2
Link to comment
Share on other sites

You're welcome! We love playing up and coming games in development! Sorry we didn't get to play the other tracks, I must have glossed over those options when reading out the instructions as we try to play every part of the game as possible.

 

Thanks for the explanation of the top of the screen firing situation, that makes a lot more sense now.

 

Very fun game and I'm looking forward to further developments on it!!

 

Here's the archive YouTube video of the episode:

 

 

I finally caught the stream - thank you for playing, I'm glad you enjoyed it! My only regret is that you didn't try any of the other 3 race tracks (the Game Select switch will cycle through them). Your play session gave me some very good feedback on the game as well.

 

The "not firing at the top of the screen" bug comes from the momentum-based targeting. I'm not actually stopping momentum if you hit the screen boundaries, the dragon just gets shunted back onto the screen. The dragon fire comes directly from the mouth, and, if you hit the top of the screen, that momentum will carry the fire off the top of the screen immediately. You have to counter-intuitively press down on the joystick to "straighten out" the dragons so they shoot straight - of course that means you risk slamming into a wall.

 

Stopping momentum at boundaries would be the most obvious way to fix things, but it'd take a few more bytes of ROM than I currently have. A code revision should free up some space, though. I was also a little wary of having the boundaries halt the dragon, because it seems a little "safer" than I wanted the track to be, and controlling the dragon's momentum is basically the challenge of the game. It'd be worth it to make the dragon firing more intuitive, though.

 

All my rambling aside, it was great to watch folks playing and enjoying these homebrews - thank you again!

 

Link to comment
Share on other sites

I just uploaded a little update in the original post - thanks to everyone for their feedback and help. The main thing is that the dragons will stop the relevant momentum if they hit a wall, and will breathe fire accordingly-they'll breath fire even if they're sliding along the top of the screen, for instance. I freed up a bit of space pretty easily (hopefully without introducing any bugs - if anyone finds any odd behavior with this new version, let me know!)

 

Game looks fun! Any carts coming out soon?

 

Thanks! I'll have to see about physical cartridges - I have a few ideas on where I'd like to take this game and what I've learned, but at the very least I want a little more testing before committing.

 

On another note - I was able to try the game on the Flashback Portable. It plays great, but the score has problems : The first and third digit seem to be linked together and output incorrectly. This seems to be a problem with multiple projects, but I've only been able to find implicit ways to fix it, nothing specific. Does anyone know of a method to fix the score on the Portable?

  • Like 2
Link to comment
Share on other sites

I just uploaded a little update in the original post - thanks to everyone for their feedback and help. The main thing is that the dragons will stop the relevant momentum if they hit a wall, and will breathe fire accordingly-they'll breath fire even if they're sliding along the top of the screen, for instance. I freed up a bit of space pretty easily (hopefully without introducing any bugs - if anyone finds any odd behavior with this new version, let me know!)

 

 

Thanks! I'll have to see about physical cartridges - I have a few ideas on where I'd like to take this game and what I've learned, but at the very least I want a little more testing before committing.

 

On another note - I was able to try the game on the Flashback Portable. It plays great, but the score has problems : The first and third digit seem to be linked together and output incorrectly. This seems to be a problem with multiple projects, but I've only been able to find implicit ways to fix it, nothing specific. Does anyone know of a method to fix the score on the Portable?

Same issue that Jared Gray West had with Quantum Tunnel - see this thread for info: http://atariage.com/forums/topic/169819-the-titlescreen-kernel/page-11?do=findComment&comment=4070420

Link to comment
Share on other sites

Different issue. The post you linked is a fix for the titlescreen kernel score on some later TIA revisions. (making it closer to the bB standard kernel score code.) Dragon Racer doesn't use the titlescreen kernel.

 

FBP is known to have emulation issues, among other things. Nukey's post in that thread is the most illuminating, and I'd consider him the FBP-kludge expert.

 

I don't have a FBP, so I don't know what the fix would be for the scores here.

  • Like 1
Link to comment
Share on other sites

Different issue. The post you linked is a fix for the titlescreen kernel score on some later TIA revisions. (making it closer to the bB standard kernel score code.) Dragon Racer doesn't use the titlescreen kernel.

 

FBP is known to have emulation issues, among other things. Nukey's post in that thread is the most illuminating, and I'd consider him the FBP-kludge expert.

 

I don't have a FBP, so I don't know what the fix would be for the scores here.

My fault - that's what happens when someone (like me) doesn't know a thing about programming.

Link to comment
Share on other sites

Same issue that Jared Gray West had with Quantum Tunnel - see this thread for info: http://atariage.com/forums/topic/169819-the-titlescreen-kernel/page-11?do=findComment&comment=4070420

 

 

FBP is known to have emulation issues, among other things. Nukey's post in that thread is the most illuminating, and I'd consider him the FBP-kludge expert.

 

I don't have a FBP, so I don't know what the fix would be for the scores here.

 

These are informative threads, thank you. It looks like I'll have to hold off on fixing the score for the Flashback Portable for the time being. My assembly coding/Atari hacking skills are not up really to the task on their own, and I'm glad the game runs as well as it does on that machine.

 

Playing with the Atari via batari Basic has been fun! My schedule this summer has been and will be a little erratic, but I do have a few other ideas I might try if and when I can get back to coding. Having only a few bytes of RAM, a few kilobytes of ROM, and a few thousand cycles a frame seems to enforce some discipline on me- it's all a balancing act, and I really have to decide if a specific feature is worth a mix from those three budgets.

Edited by Revontuli
  • Like 1
Link to comment
Share on other sites

FWIW, I think I finally understand Nukey's score fix well enough that I can recreate it myself in the form of a custom std_kernel.asm that one can drop into a project directory to get a AFP-compatible six-digit score. I'll start a new thread for this when I have something working on mine.

  • Like 1
Link to comment
Share on other sites

  • 1 month later...

I finally got around to incorporating the kernel fix for the scoring on the Atari Flashback Portable - This version is basically the same as the July version, but it does have a tiny bit of artifacting (the little black line) that comes with the score fix, and some color changes to save a byte or two to fit the new kernel, so it's really only needed for those who'd want to play on the Flashback. If you -do- have the Flashback Portable, though, this version is recommended if you want accurate and valid scoring!

 

Thanks to Karl G for the fix!

Link to comment
Share on other sites

  • 5 months later...

I finally got around to combining the Flashback Portable fixes with the original build, as well as making a semi-custom font. The binary is at the top of the original post, and that same binary should work on an original Atari as well as the Flashback Portable.

 

I'm submitting this binary as a semi-final build. I've no more planned features to add, but I'll keep an eye out for bugs or other oddities. The best way to find bugs in a project is to declare it "finished," after all!

  • Like 3
Link to comment
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.
Note: Your post will require moderator approval before it will be visible.

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...