Jump to content

Recommended Posts

This thread is to develop a demonstration of a ship movement routine in 7800bas that produces a result that looks similar to Omega Race / Asteroids.

 

This initial post is a starting point only and does not display the desired characteristics.

 

All programmers, mathematicians, rocket scientists as well as anyone who has constructive input are welcome to participate.

 

ardemo.zip

 

  • Like 2
Me:

I have been searching for a way to achieve this for a long while now and so far I have been frustrated but hopefully, working through this here

will help me understand it and maybe help someone in the future who references this thread.


Most sources I have tried to follow convert the angle from degrees to radians before doing cos and sin. 7800bas doesn't have COS or SIN built

in at this point but, we can calculate those values with a PC and create a lookup table of the results for each angle.


A professional told me this:


Pro:

Let's say that STARSHIP has 16 possible angles of movement. Starting from "North", we'll number these 0 through 15. Each angle is 22.5 degrees apart.

Now, to determine our vector, we're going to always assume a 'length' of one.

Now, evil geometry says that sin (vector) = opposite over hypotenuse. cos (vector) = adjacent over hypotenuse.

Thankfully we always know that our hypotenus, at this step, is equal to one.

This means that sin(vector) = opposite, which happens to be our "DY". And our cos(vector) happens to be our "DX".

So, to determine our DX for any given angle, DX = cos(angle). And DY = sin(angle).


Me:

Now, I don't know but I think perhaps in this case it does not matter if we are using degrees or radians because we are just trying to get a proportional value

in order to assign a percentage of thrust to each axis.


That professional also advised to multiply by 100 to loose the nasty decimal places

Then the professional says when we are ready to move our ship we need to do this

;X = X + (DX * THRUST) / 100; // Correct for the pixels used in movement

;Y = Y + (DY * THRUST) / 100; // Correct for the pixels used in movement


What I am thinking is doesn't the division just bring back the decimals? So, why get rid of them in the first place. I mean if we can't handle them in one place, how can we handle them in another?


So what I have done in the attached example is to calculate the DX = cos(angle). And DY = sin(angle) for the eight possible rotations of the ship and then place those values into a lookup table as fixed point numbers. The values in the table are absolutes as the signage will be done in the player movement routine when the the dx and dy get added to or subtracted from each axis. The decimal places have been truncated to one place.


So, can anyone help me understand what is wrong with the attached example? Does anybody have an alternate method or working code?

ardemo try1.zip

Edited by SIO2

Is 16 angles enough? I'm not sure what Asteroids, Star Castle, and Omega Race use, but the more the merrier, I think.

I think OR had 64 angles of rotation but for simplicity I think we should model fewer. Another issue is trying to display them. Do we need them if we can't see them? If we don't know where we are pointed when we thrust, how is that different than being out of control? Edited by SIO2

One thing that the easy peasy model so far presented lacks is accounting for existing velocity. Right now the dx dy values split the thrust to the each axis but that value becomes the sole velocity used to move the ship which results in a sharp turn. I think a vx and vy are needed to store the history of velocity on each axis so that vx=vx+dx and vy=vy+dy. New velocity = old velocity + acceleration. My difficulty with doing that is handling the sign (positive or negative) of the thrust because if we are in motion and flip the ship 180 degrees and thrust then we are actually subtracting velocity rather than adding. Any suggestions about ways to deal with negative numbers in 7800bas would be appreciated.

Edited by SIO2

I was going to mention your overwriting of the velocity as one of the problems. I've been trying to do a similar thing to this in graze for homing missiles, although it gets more complicated for those things since you're not manually feeding/changing velocities for it.

 

For dealing with negative numbers, this might help or might be worth trying out:

 

if we're actually slowing down due to going in the opposite direction, then perhaps do a test to see which is bigger?

 

if vx > dx, do normal subtraction (vx - dx) and you should be good to go.

 

if vx = dx, set vx to 0 and call it good.

 

if vx < dx, do (dx - vx) instead, and switch the sign/direction.

 

That might do something.

 

 

Also you'll need a slow drag on your velocities when the player isn't actively trying to move (as per Asteroids). For that, I'd probably recommend subtracting a tiny portion from vx/vy on any frame the player is not actively accelerating in the particular direction. If you get to a frame where vx < drag, just set it to 0 so it finally stops.

Awesome Mord. Glad to see you join the discussion. I will have to check that out.

 

Meanwhile, I discovered an error in attempt 1 that prevented the ship moving up properly. I fixed that and then duplicated that structure for dealing with the sign on vx.

 

Check this out and see what you think.

ardemo try 2.zip

Here's a demo with a wedge omega-race style ship that has 16 positions, velocity, drag, and screen edge bounce.

 

The only place I had to resort to assembly was in the drag routine, where I take the current velocity and subtract 1/8th of the current value.

ardemo-16-positions.zip

  • Like 3

Hmm.. I probably should have explained thrust a bit better, but, yeah, you wind up multiplying the DX and DY by the current thrust when you add positions. Thrust should, of course, build up as you keep the button down, to its maximum, and then fade to zero again as the button's released.

 

I suppose I shouldn't have left that out. :S

Is 16 angles enough? I'm not sure what Asteroids, Star Castle, and Omega Race use, but the more the merrier, I think.

He's right on this one. 16 is pretty smooth for a raster game. If I remember right, most vector games use either 30 or 60 positions, keeping the math simple.

 

As for the division I mentioned, that idea was that all your other math was 'fixed point' , and you would only need to return to the truncated decimal when you're correcting for the pixel map. In higher-order programming, we just bit-shift that by whatever works for the screen resolution and avoid the whole math mess, but I wasn't sure what 7800bas offered as far as that goes.

Here's a demo with a wedge omega-race style ship that has 16 positions, velocity, drag, and screen edge bounce.

 

The only place I had to resort to assembly was in the drag routine, where I take the current velocity and subtract 1/8th of the current value.

 

Master, I am humbled by your magic. Thank you.

 

I love the demo. It didn't compile for me though on this computer. I think perhaps it is because I have the older Feb 22 release of 7800bas on here.

You're welcome. In addition to helping out your cause, I also figured that thrust mechanics are tricky enough that some demo code would be generally useful.

 

I think you're correct that the compile trouble is due to the older 7800basic version. Give the new version a shot.

 

I should mention that the source has a few different thrust tables available - strong, medium, and weak. The medium table is what the demo is using.

 

I probably will need to add in bullet routines at some point too, since they need to get velocity from a table, similar to the thrust routines.

 

I should probably embellish the comments some more too, but here are some key concepts...

 

The ship position and velocity are held as fixed point variables, which are basically 16-bit values, with one byte representing whole numbers, and one byte representing fractional numbers. This allows for "movement" smaller than 1 pixel per frame.

 

The code relies a fair bit on two's complement math, where (for example) 255 can mean 255 or -1, depending on how its used. ie. when you're using bytes for storage, 3-1=2, and 3+255=2. So I wind up adding the dx/dy velocity values to the ship position, whether they're negative or positive.

 

The thrust table is a sine wave, with an extra quarter wave so we can use the same table for cosine lookups. When we look up the thrust values using the ship's angle, it's analogous to finding a point for a given angle on the unit circle.

 

Understanding these concepts aren't a requirement to using the code - you can treat the routines as a black box - but modifications will be tricky otherwise.

  • Like 4

Ok, last update on this, barring any bugs. Now featuring:

  • Lots of code comments
  • Ship with 16 angles of rotation, and thrust system
  • 3 bullets with fire button debouncing
  • "Atmospheric" drag to slow down the ship
  • Optional code blocks to change the ship thrust power
  • Optional code blocks to change the bullet velocity
  • Optional code blocks to change bullet behaviors at edges: stop, bounce, or wrap
  • Optional code blocks to change ship behavior at edges: bounce or wrap
If you're OK with it SIO2, I'll add it to the 7800basic samples.

 

ardemo.reveng.zip

  • Like 5

I'm sure you've figured this out already, but for a limited number of rotation positions, lookup tables are the way to go for direction to X,Y anything. Note: while using reflections can reduce the size of the tables, it is often outweighed by the extra code (which costs cycles & space).

 

For SpaceWar! 7800 I used a lot of table lookups. Thrust was approximated as an acceleration in the direction of rotation, which was then added to the current velocity (which I think had a limiter on it). The gravity of the sun was another acceleration added to the velocity from a lookup based on the ship position. The velocity then gets added to the ship position every frame to produce movement. Everything is stored as signed fixed point values.

 

Oh, a quick approximation for the length of the hypotenuse is max(abs(x),abs(y)) + min(abs(x),abs(y))/2.

 

Remember you're making a game, not a physics simulation :-)

 

  • Like 1

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