Page 2 of 2
Posted: Sat Oct 28, 2006 2:15 am
by Bregalad
Again, I prefer myself use only one byte for speed, and the high nyble is the integer part and the low nybble the fraction part.
You will never want to have something move less than 1/16th pixel per frame nor anything moving faster than 7+15/16th pixel per frame.
So :
$10 is move one pixel per frame forward
$18 is move one pixel and a half per frame forward
$e8 is the same speed as above, but backwards
etc...
You can also use the whole full 8-bits to allow to move up to 15+15/16th pixel per frame, and have a sign bit in a separate variable, I do that in my current game. (because when a monster is knocked back, I "cheat" and make it moving 15+15/16th pixel per frame for one frame, making them go back arround 16 pixels).
This will make you write a programm a little bit more complex, dealing with shifts and all, but save significant size of RAM arrays. Plus if you're new to the dev scene that will make you a good exercice, and it's nothing near impossible to deal with shifts.
Posted: Sat Oct 28, 2006 3:52 am
by Memblers
Bregalad wrote:
This will make you write a programm a little bit more complex, dealing with shifts and all, but save significant size of RAM arrays.
Do you mean ROM? Because using a full 8-bits for the sub-pixel resolution still only requires one byte of RAM (unless you want the adjustable speeds in RAM. then you'll want a wider ranger of speeds anyways and it'll require 2 bytes, but I seriously doubt anyone would do that for much more than their main sprites). I guess it depends on the type of game. If you have a lot of individual objects, the extra processing for the shifts and stuff will really add up. If you have fewer objects made up of several sprites that move together, it won't matter as much.
Posted: Sat Oct 28, 2006 5:28 am
by Bregalad
No, I mean RAM, because the speed of projectiles is kept in RAM.
Only the speed of ennemies is kept in ROM, but they act just the same (they just are consant) in my game. But that all depdends of the game. But anyway I think it is easier to work with one single byte in most cases.
Posted: Sat Oct 28, 2006 10:45 am
by VanOccupanther
That was useful to me for figuring out how fast and slow the one byte speed method could go. (7+15/16th and 1/16th)
----------
Well, i tried the one byte method and it ended up using two bytes. Here's what's there:
Code: Select all
lda $18
sta speed
lda speed
and #%00001111
sta speed_low
lda speed
and #%11110000
lsr
lsr
lsr
lsr
sta speed_high
Is that the only way to do it? You said use one byte, but really, it ended up using two.
Posted: Sat Oct 28, 2006 12:38 pm
by Bregalad
Wait, you got the thing, but now you don't have to use two bytes. I'll just show you some example :
Code: Select all
lda Speed
asl A
asl A
asl A
asl A
clc
adc PositionL
sta PositionL
lda Speed
lsr A
lsr A
lsr A
lsr A
adc PositionH
sta PositionH
Note that only the 4 high bits of Position L are used, and the low bits aren't affected at all so they can be used for anything else.
To do it signed, just test the sign of the original Speed variable, and then do the whole thing using one routine that add, and one routine that substract in function of the original sign (but the negative bit must be masked when substractuing after the 4 "LSR A"s).[/code]
Posted: Mon Oct 30, 2006 5:50 pm
by VanOccupanther
Having problems. Here's the code:
Code: Select all
;**************
; movement_speed start
;**************
lda #$10
sta speed
lda y_portion_decimal
;sta look2
sta multiplicand
lda speed
asl
asl
asl
asl
;sta look4
jsr multiply
lda product
;sta look6
sta bullettable+1 ;y_portion_decimal
lda y_portion
;sta look
sta multiplicand
lda speed
lsr
lsr
lsr
lsr
;sta look3
jsr multiply
lda product
;sta look5
sta bullettable ;y_portion
lda x_portion_decimal
;sta look8
sta multiplicand
lda speed
asl
asl
asl
asl
;sta lookA
jsr multiply
lda product
;sta lookC
sta bullettable+3 ;x_portion_decimal
lda x_portion
;sta look7
sta multiplicand
lda speed
lsr
lsr
lsr
lsr
;sta look9
jsr multiply
lda product
;sta lookB
sta bullettable+2 ;x_portion
;**************
; movement_speed end
;**************
here is multiply's header:
Code: Select all
multiply: ;******
;must give multiplicand a value
;multiplier value should be stored in accumulator
;
;answer will be stored in product
;******
Multiply works multiplying a byte with a byte.
The problem.. for example when shooting toward the southwest
y_portion = 00
y_portion_decimal = D6
speed = 10 (one pixel per frame)
so speed_high = 01
and speed_low = 00
so y_portion * speed_high = 00
and y_portion_decimal * speed_low == 00
It takes 00D6 and changes it to 0000.

It should take 00D6 and give back 00D6. Since this is multiplication maybe each 00 should be changed to a 01, but i don't know. The x_portion and x_portion decimal is FF72. But, it gives FF72 [-.72] * 0100 [1.0] = FF00 [-1.0].
Please help me to figure out what's wrong with the multiplication here?
Posted: Fri Nov 03, 2006 9:28 pm
by VanOccupanther
Multiplying two two byte numbers is hard. Here is my attempt (A,B,C,and D are variables.)
Code: Select all
A.B
x C.D
-----
step1 = D * B
step2 = carry_from_step3 + C * A
step3 = C * B
step4 = carry_from_step1 + D * A
step1 x 1 = val1
step2 x 100 = val2
step3 x 10 = val3
step4 x 10 = val4
val1 + val2 + val3 + val4 = answer
lda answer
tay
asl
asl
asl
asl
sta y_portion_decimal
tya
lsr
lsr
lsr
lsr
sta y_portion
But there's a problem with the answer. For example:
When calculating val3, it moves the bits 4 to the left, that's why we lost the F. Also, the answer should look like 00.FC00 so the whole number part is lost too. How can you do this? How would you do this? Please help me fix this.
Posted: Fri Nov 03, 2006 10:12 pm
by tepples
Multiplying 16 bits by 16 bits should be straightforward. The classic algorithm does four calls to the 8x8 multiply followed by several adds:
Code: Select all
$aabb
* $ccdd
-----
bdbd
bcbc00
adad00
+acac0000
---------
value
I don't see where nibble-wise operation ever comes into play.