# 8-bit Projectile Logic: How do you do it?

##### New Member
Please note that when I refer to projectiles I refer to them in the gaming sense not the physics sense IE: "Bullets" that are unaffected by gravity If you've ever played Gradius (or even better... Parodius!) for the MSX or other 8 bit consoles, you'll notice the massive amounts of homing projectiles.
Whether it's wall turrets spewing bullets in your general direction or floating baddies moving directly to your current position, it's a great mechanic!

In today's world of vector maths and floating point values it's relatively simple to do this sort of thing but my one question is;
How would you do this sort of thing on such limited hardware without resorting to C's built in floats? (As that would most likely be inefficient)

How would I calculate the "angle" that the bullet would take?
How would I deal with moving it in values of less than 1 pixel? (Say for instance a bullet needed to move 1 vertical pixel for every 2 horizontal pixels)
Would it be most efficient to use a bunch of pre-calculated tables for this sort operation?

#### JoshuaScholar

##### New Member
is it up, down or on a row with you
is it right, left or on a column
Now you already have chosen between 8 vectors just by answering those questions.
Want better, start comparing how up to how left, multiplying and dividing may be slow but multiplying and dividing by 2 is fast.
Is it more up than left?
Is it more than twice as much up as left?
etc.

• #### JoshuaScholar

##### New Member
There are other options. When I was a 6502 programmer I replaced missing instructions with tables a lot.

• #### JoshuaScholar

##### New Member
Third option, take the vector toward the object, and divide it down to something approaching a pixel size but fixed point. Keep the position of the projectile in fixed point... Once again, divide is slow but divide by 2 isn't and you can do that repeatedly and you could also do other tricks.

I like math so I always keep the impression that even though the 6502 is slow as molasses there's always a fast way to approximate any math you need.

• ##### New Member
Another cool trick I've thought of to get more angles and speeds is to use a SIGNED integer for projectile speeds (x and y) with negative values meaning "move 1 pixel every ABS(value) frames" seeing as a projectile is unlikely to move at a speed of over 64 pixels per frame.

#### TomXP411

##### Moderator
Staff member
Yes, fixed point integer math is how I'd do it. When I worked in banking, we used to actually store bank account information (like balances) as a 32 bit integer. You could do the same thing for sub-pixel positioning for objects in a game.

For example, if your position can be expressed in one byte, use two bytes. You use the high byte when displaying the object, but use both bytes when doing the math to move the object.

Let's look at a simple case. This is the Y component of a vector:

Position: \$20 A3, Velocity: \$00 62

In the first frame, the object displays on row \$20.
\$2003 + \$0062 = \$2105
So in the second frame, you display the object on row \$21
\$2105 + \$0062 = \$2167
Now the object is on row 21.

So that's your sub-pixel positioning taken care of.

The other issue is how to handle computing angles. Let's assume that a turret or ship can be positioned in 256 positions. This lets you store 64 SIN and 64 COS values in your lookup tables. Since those values with necessarily be two bytes, you need 256 bytes to store the table.

You can pre-compute the sins with a loop like this:

Code:
``````0 PRINT "{clear}"
10 DIM SH(64):DIM SL(64)
20 DIM CH(64):DIM CL(64)
30 S= /128
40 FOR A=0 TO 64
50 SH(A)=INT(SIN(A*S))
60 SL(A)=INT((SIN(A*S)-SH(A))*256)
70 CH(A)=INT(COS(A*S))
80 CL(A)=INT((COS(A*S)-CH(A))*256)
90 NEXT
REM VERIFICATION LOOP
REM THIS PRINTS OUT THE ANGLES SO YOU CAN CHECK THEM BY HAND
REM THE ANGLE AT 32 SHOULD BE 0 181 (0.707 * 256)
100 PRINT:PRINT "ANGLE","SINH","SINL","COSH","COSL"
110 FOR A=0 TO 64 STEP 4
120 PRINT A, SH(A), SL(A), CH(A), CL(A)
130 NEXT``````

Remember that SIN and COS use radians in BASIC, and a full rotation in Radians is 2π. So to get 256 even angles, we need to divide 2π by 256. However, we only need to store 64 values, since you can get the other half of the curve by negating the number. ie: SIN(RIGHT) is 90 and SIN(LEFT) is -90.

Of course, if you have the room to spare, you can store all 128 values, and this will speed things up slightly.

• #### BruceMcF

##### Active Member
One of the old tricks was to only allow things to fire at the 8 cardinal and sub-cardinal directions (N NE E SE S SW W NW). Then the pixel direction is always either horizontal, vertical, or at a 45 degree angle. So if you have subpixel virtual positioning, you only need to know how many sub-pixels it moves per frame horizontally / vertically and how many sub-pixels it moves per frame when moving at a 45 degree angle.

• #### MJoergen

##### New Member
The way I would do it - as others have hinted at - is to use fixed point arithmetic, more precisely have 8 fractional bits. So a pixel x-coordinate will use one extra byte, where the lowest order byte is the fractional part. That way, you don't have to do any shifting. So an increment of half a pixel corresponds to adding the value \$000080.

• • 