| |
jamiefuller Account closed
Registered: Mar 2018 Posts: 25 |
Simple "look at" function, avoiding atan2
Hi All,
I am writing a game that requires the player character to aim his gun at a movable point around the screen, I would usually calculate the angle using atan2 but don't want the overhead of a fully blown atan2 routine ( http://codebase64.org/doku.php?id=base:8bit_atan2_8-bit_angle )
The player can be any random x,y and the crosshaor can be any other random x,y
The gun sprite only needs to point in one of 8 directions so I can't help think that it must be easier to calculate/table. but I'm drawing a major blank :(
Any pointers or suggestions would be much appreciated.
Thanks |
|
| |
JackAsser
Registered: Jun 2002 Posts: 2014 |
So you just want to find octant. Just calculate dx and dy. This will give you quadrant immediately. Then you compare abs(dx) with abs(dy) to get octants.
From the top of my head, you bug fix it:
\ | /
\2 |1 /
\ | /
3 \|/ 0
-----+-----
4/|\ 7
/ | \
/ 5|6 \
/ | \
0,1: dx>0, dy>0
0: |dx|>|dy| else 1
2,3: dx<0, dy>0
2: |dy|>|dx| else 3
4,5: dx<0, dy<0
4: |dx|>|dy| else 5
6,7: dx>0, dy<0
6: |dy|>|dx| else 7
|
| |
JackAsser
Registered: Jun 2002 Posts: 2014 |
Or use a simple table like this:
a = sgn(dx)
b = sgn(dy)
c = sgn(abs(dx)-abs(dy))
a b c
0: + + +
1: + + -
2: - + +
3: - + -
4: - - +
5: - - -
6: + - +
7: + - -
|
| |
jamiefuller Account closed
Registered: Mar 2018 Posts: 25 |
thanks so much JackAsser, That gives me some info to work through.
The only issue I can think of is that the octants are slightly offset to that,
see this image, excuse my terrible scribble :)
|
| |
ChristopherJam
Registered: Aug 2004 Posts: 1409 |
Just set
x'=x+y/2
y'=y-x/2
before using Jackie's method. Your thresholds will be 4° off, but I don't think that'll be noticeable.
(or, (x*2.5+y, y*2.5-x) if you want to just be 0.7° out) |
| |
JackAsser
Registered: Jun 2002 Posts: 2014 |
CJam applies a simple rotation matrix. Ideally you want to mul by sin(0.5) but sin(0.5) ~= 0.5 |
| |
jamiefuller Account closed
Registered: Mar 2018 Posts: 25 |
Damn you guys are good!, I'm still struggling to get my head around the first reply :)
Thanks to you both. |
| |
Martin Piper
Registered: Nov 2007 Posts: 722 |
Calculate dx and dy. Shift the values, or lookup, so they're both fitting in 4 bits. You can vary the shift to maintain nearby accuracy or fit far away tests as long as you shift the same for both values.
Combine them into a 8 bit value.
Use that to index into a direction table.
The final lookup gives you the ability to finely tweak the direction sprite for whatever skewed quadrants you want. |
| |
jamiefuller Account closed
Registered: Mar 2018 Posts: 25 |
Thanks everyone for your ideas, honestly some of them were well over my head but certainly put me on the right path.
This is the code I ended up with, which works well for my case needs. it doesn't compensate for my "offset" yet but it still looks pretty good and I may just skip that bit.
Huge thanks again everyone!
pointgun
lda x1
sec
sbc x2
sta dx
bcs @at10
eor #$ff
@at10
sta absdx
rol octant
lda y1
sec ; this bit just compensates for different starting co-ordinates
sbc #$0c ; this bit just compensates for different starting co-ordinates
lsr ; this bit just compensates for different starting co-ordinates
sec
sbc y2
sta dy
bcs @at20
eor #$ff
@at20
sta absdy
rol octant
sec
sbc absdx
rol octant
lda octant
and #$07
tax
lda guntab,x
sta 2046 ;store anim frame in sprite
rts
guntab BYTE $8E,$8F,$8D,$8C,$91,$90,$92,$93
x1,y1,x2,y2,dx,dy,absdx and absdy and octant are all just zeropage variables. |
| |
ChristopherJam
Registered: Aug 2004 Posts: 1409 |
Nice.
I was thinking an alternate way to solve the offsets problem is to just have your artwork pointing the gun NNE, ENE, ESE, SSE etc :)
(oh, and warning - your "this bit" section is subtracting y2 from half of y1 at the moment; you'll probably want to make a halved version of y2 to subtract instead if you keep that) |
| |
jamiefuller Account closed
Registered: Mar 2018 Posts: 25 |
Quote: Nice.
I was thinking an alternate way to solve the offsets problem is to just have your artwork pointing the gun NNE, ENE, ESE, SSE etc :)
(oh, and warning - your "this bit" section is subtracting y2 from half of y1 at the moment; you'll probably want to make a halved version of y2 to subtract instead if you keep that)
Yeah the "this bit" section adjusts for the fact that y1 and y2 have very differing co-ordinate systems in my game, y2 only has 2 pixel resolution so to speak, so is multiplied by 2 when drawing the sprite later on :)
I also just noticed that the code above can be optimised quite a bit by removing the "sta dx", "sta dy" and the "sta absdy" as none of them are used for anything else later on.
:) |
| |
TWW
Registered: Jul 2009 Posts: 545 |
In which case you only need to LDA X1 CMP X2 |
| |
jamiefuller Account closed
Registered: Mar 2018 Posts: 25 |
Quote: In which case you only need to LDA X1 CMP X2
Good point, and I had to double check my code to make sure :)
but in this case while I am not using dx later, I am using dx to calculate absdx, so I still need to do the subtraction to calculate dx, just not store it anywhere, only store absdx.
But I think I could probably do that for the last subtraction
sec
sbc absdx
which calculates absdy-absdx and only uses the sign of the output. I'll give it a try :) |