Jump to content

Photo

Dragon Racer: Trials of the Wyrm


11 replies to this topic

#1 Revontuli OFFLINE  

Revontuli

    Combat Commando

  • 5 posts

Posted Sun Jun 3, 2018 7:13 PM

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

 

Attached File  DragonRacer_6_4_2018.bin   8KB   17 downloads

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]


Edited by Revontuli, Mon Jun 4, 2018 2:21 PM.


#2 RevEng OFFLINE  

RevEng

    River Patroller

  • 4,796 posts
  • Bitnik
  • Location:Canada

Posted Sun Jun 3, 2018 8:30 PM

Nice little game, Revontuli. Well done :thumbsup:

I was able to kick the computer's butt in most of the tracks, but it turned the tables in that open arena one.

#3 kdgarris ONLINE  

kdgarris

    Moonsweeper

  • 320 posts

Posted Mon Jun 4, 2018 5:56 AM

Simple but fun!  I personally found the quickly-changing background color to be distracting, but others may like it,



#4 Revontuli OFFLINE  

Revontuli

    Combat Commando

  • Topic Starter
  • 5 posts

Posted Mon Jun 4, 2018 1:12 PM

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.



#5 Random Terrain OFFLINE  

Random Terrain

    Visual batari Basic User

  • 28,682 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Mon Jun 4, 2018 1:41 PM

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



#6 TrekMD OFFLINE  

TrekMD

    River Patroller

  • 3,499 posts
  • Location:Coral Gables, FL

Posted Mon Jun 4, 2018 2:09 PM

Cool, I will be trying this out.



#7 Revontuli OFFLINE  

Revontuli

    Combat Commando

  • Topic Starter
  • 5 posts

Posted Mon Jun 4, 2018 2:24 PM

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.



#8 RevEng OFFLINE  

RevEng

    River Patroller

  • 4,796 posts
  • Bitnik
  • Location:Canada

Posted Mon Jun 4, 2018 2:45 PM

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]

#9 Revontuli OFFLINE  

Revontuli

    Combat Commando

  • Topic Starter
  • 5 posts

Posted Mon Jun 4, 2018 4:43 PM

 

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!



#10 RevEng OFFLINE  

RevEng

    River Patroller

  • 4,796 posts
  • Bitnik
  • Location:Canada

Posted Mon Jun 4, 2018 5:17 PM

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.

#11 Revontuli OFFLINE  

Revontuli

    Combat Commando

  • Topic Starter
  • 5 posts

Posted Mon Jun 4, 2018 11:27 PM

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.



#12 iddod OFFLINE  

iddod

    Space Invader

  • 40 posts

Posted Thu Jun 7, 2018 11:38 AM

 

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






0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users