artrag Posted February 15, 2018 Share Posted February 15, 2018 To whom it may concern, a small and fast snippet useful for bullet aiming and other game mechanics. The code is fully tested and optimized, ready to be used by coders in the IntyBASIC Programming Contest 2018. PS The post is about the function ATAN2(), sine and cosine come for free. '''''''''''''''''''''''''''''''''''''''''''''''' ' ;;;;;;;; atan(2^(x/32))*128/pi ;;;;;;;; atan_tab: data $20,$20,$20,$21,$21,$22,$22,$23,$23,$23,$24,$24,$25,$25,$26,$26 data $26,$27,$27,$28,$28,$28,$29,$29,$2A,$2A,$2A,$2B,$2B,$2C,$2C,$2C data $2D,$2D,$2D,$2E,$2E,$2E,$2F,$2F,$2F,$30,$30,$30,$31,$31,$31,$31 data $32,$32,$32,$32,$33,$33,$33,$33,$34,$34,$34,$34,$35,$35,$35,$35 data $36,$36,$36,$36,$36,$37,$37,$37,$37,$37,$37,$38,$38,$38,$38,$38 data $38,$39,$39,$39,$39,$39,$39,$39,$39,$3A,$3A,$3A,$3A,$3A,$3A,$3A data $3A,$3B,$3B,$3B,$3B,$3B,$3B,$3B,$3B,$3B,$3B,$3B,$3C,$3C,$3C,$3C data $3C,$3C,$3C,$3C,$3C,$3C,$3C,$3C,$3C,$3D,$3D,$3D,$3D,$3D,$3D,$3D data $3D,$3D,$3D,$3D,$3D,$3D,$3D,$3D,$3D,$3D,$3D,$3D,$3E,$3E,$3E,$3E data $3E,$3E,$3E,$3E,$3E,$3E,$3E,$3E,$3E,$3E,$3E,$3E,$3E,$3E,$3E,$3E data $3E,$3E,$3E,$3E,$3E,$3E,$3E,$3E,$3E,$3E,$3E,$3E,$3F,$3F,$3F,$3F data $3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F data $3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F data $3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F data $3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F data $3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F ' ;;;;;;;; log2(x)*32 ;;;;;;;; log2_tab: data $00,$00,$20,$32,$40,$4A,$52,$59,$60,$65,$6A,$6E,$72,$76,$79,$7D data $80,$82,$85,$87,$8A,$8C,$8E,$90,$92,$94,$96,$98,$99,$9B,$9D,$9E data $A0,$A1,$A2,$A4,$A5,$A6,$A7,$A9,$AA,$AB,$AC,$AD,$AE,$AF,$B0,$B1 data $B2,$B3,$B4,$B5,$B6,$B7,$B8,$B9,$B9,$BA,$BB,$BC,$BD,$BD,$BE,$BF data $C0,$C0,$C1,$C2,$C2,$C3,$C4,$C4,$C5,$C6,$C6,$C7,$C7,$C8,$C9,$C9 data $CA,$CA,$CB,$CC,$CC,$CD,$CD,$CE,$CE,$CF,$CF,$D0,$D0,$D1,$D1,$D2 data $D2,$D3,$D3,$D4,$D4,$D5,$D5,$D5,$D6,$D6,$D7,$D7,$D8,$D8,$D9,$D9 data $D9,$DA,$DA,$DB,$DB,$DB,$DC,$DC,$DD,$DD,$DD,$DE,$DE,$DE,$DF,$DF data $DF,$E0,$E0,$E1,$E1,$E1,$E2,$E2,$E2,$E3,$E3,$E3,$E4,$E4,$E4,$E5 data $E5,$E5,$E6,$E6,$E6,$E7,$E7,$E7,$E7,$E8,$E8,$E8,$E9,$E9,$E9,$EA data $EA,$EA,$EA,$EB,$EB,$EB,$EC,$EC,$EC,$EC,$ED,$ED,$ED,$ED,$EE,$EE data $EE,$EE,$EF,$EF,$EF,$EF,$F0,$F0,$F0,$F1,$F1,$F1,$F1,$F1,$F2,$F2 data $F2,$F2,$F3,$F3,$F3,$F3,$F4,$F4,$F4,$F4,$F5,$F5,$F5,$F5,$F5,$F6 data $F6,$F6,$F6,$F7,$F7,$F7,$F7,$F7,$F8,$F8,$F8,$F8,$F9,$F9,$F9,$F9 data $F9,$FA,$FA,$FA,$FA,$FA,$FB,$FB,$FB,$FB,$FB,$FC,$FC,$FC,$FC,$FC data $FD,$FD,$FD,$FD,$FD,$FD,$FE,$FE,$FE,$FE,$FE,$FF,$FF,$FF,$FF,$FF data $FF ' trick to cope with 256 '----------------------------------------------- ' Source: https://www.msx.org/forum/msx-talk/development/8-bit-atan2?page=0 ' 8-bit atan2 ' Calculate the angle, in a 256-degree circle. ' The trick is to use logarithms to get the y/x ratio and ' integrate the power function into the atan table. ' input ' #dx_in, #dy_in in -256,255 ' ' output ' angle in 0-255 ' ^ ' q1 | q0 '------+------> ' q3 | q2 ' | signed #dx_in signed #dy_in atan2: procedure if (#dy_in>0) then if (#dx_in>0) then gosub atan2_q0 ' q0 else #dx_in=-#dx_in ' q1 gosub atan2_q0 angle = (-angle) and $7F return end if else if (#dx_in>0) then #dy_in=-#dy_in ' q2 gosub atan2_q0 angle = -angle return else #dx_in=-#dx_in ' q3 #dy_in=-#dy_in gosub atan2_q0 angle = angle + 128 return end if end if return end atan2_q0: procedure if (#dx_in>=#dy_in) then angle = (-atan_tab(log2_tab(#dx_in)-log2_tab(#dy_in))) and $3F else angle = atan_tab(log2_tab(#dy_in)-log2_tab(#dx_in)) end if return end ';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ' input ' angle in 0-255 ' ' output ' #dy_out = sin(angle) in -256,256 ' #dx_out = cos(angle) in -256,256 getsincos: procedure #dy_out = #sin_table(angle) #dx_out = #cos_table(angle) end #sin_table: data 0, 6, 12, 18, 25, 31, 37, 43, 49, 56, 62, 68, 74, 80, 86, 92 data 97, 103, 109, 115, 120, 126, 131, 136, 142, 147, 152, 157, 162, 167, 171, 176 data 181, 185, 189, 193, 197, 201, 205, 209, 212, 216, 219, 222, 225, 228, 231, 234 data 236, 238, 241, 243, 244, 246, 248, 249, 251, 252, 253, 254, 254, 255, 255, 255 #cos_table: data 256, 255, 255, 255, 254, 254, 253, 252, 251, 249, 248, 246, 244, 243, 241, 238 data 236, 234, 231, 228, 225, 222, 219, 216, 212, 209, 205, 201, 197, 193, 189, 185 data 181, 176, 171, 167, 162, 157, 152, 147, 142, 136, 131, 126, 120, 115, 109, 103 data 97, 92, 86, 80, 74, 68, 62, 56, 49, 43, 37, 31, 25, 18, 12, 6 data 0, -6, -12, -18, -25, -31, -37, -43, -49, -56, -62, -68, -74, -80, -86, -92 data -97, -103, -109, -115, -120, -126, -131, -136, -142, -147, -152, -157, -162, -167, -171, -176 data -181, -185, -189, -193, -197, -201, -205, -209, -212, -216, -219, -222, -225, -228, -231, -234 data -236, -238, -241, -243, -244, -246, -248, -249, -251, -252, -253, -254, -254, -255, -255, -255 data -256, -255, -255, -255, -254, -254, -253, -252, -251, -249, -248, -246, -244, -243, -241, -238 data -236, -234, -231, -228, -225, -222, -219, -216, -212, -209, -205, -201, -197, -193, -189, -185 data -181, -176, -171, -167, -162, -157, -152, -147, -142, -136, -131, -126, -120, -115, -109, -103 data -97, -92, -86, -80, -74, -68, -62, -56, -49, -43, -37, -31, -25, -18, -12, -6 data 0, 6, 12, 18, 25, 31, 37, 43, 49, 56, 62, 68, 74, 80, 86, 92 data 97, 103, 109, 115, 120, 126, 131, 136, 142, 147, 152, 157, 162, 167, 171, 176 data 181, 185, 189, 193, 197, 201, 205, 209, 212, 216, 219, 222, 225, 228, 231, 234 data 236, 238, 241, 243, 244, 246, 248, 249, 251, 252, 253, 254, 254, 255, 255, 255 5 Quote Link to comment Share on other sites More sharing options...
intvnut Posted February 15, 2018 Share Posted February 15, 2018 Interesting approach, using logarithms to transform the division into a subtraction. That should be quite fast! I wonder, does it make sense to add an antilog table, so you could also get a cheap divide approximate as part of this math kit? That is, div_approx = antilog(log(x) - log(y)). That could be useful for normalizing vectors, when combined with something like dist_fast. Depending on what you're doing, that may be a more direct route. For example, if you know the delta-x and delta-y to the object you're aiming at, then you might want your target velocity to be roughly as follows: . dist = sqrt(dx*dx + dy*dy) vx = dx / dist vy = dy / dist . Of course, all this computation is very expensive. dist_fast lets you do the dist calculation quickly. If you could also do the divide quickly, then you'd be in good shape. Something like: . dist_log = log(dist_fast(dx, dy)) vx = antilog(log(dx) - dist_log) vy = antilog(log(dy) - dist_log) . FWIW, here is my BASIC translation of the veclen2 function from dist_fast. I have not tested it. Free for all to use, naturally. . ' From "Fast Linear Approximations of Euclidean Distance in Higher Dimensions" ' by Yoshikazu Ohashi, yoshi@cognex.com ' in "Graphics Gems IV", Academic Press, 1994 ' ' Takes input in #IX, #IY. Returns result in #T. ' Can be converted to 8-bit values trivially. DistFast PROCEDURE #IX = ABS(#IX) #IY = ABS(#IY) IF #IX < #IY THEN #IX = #IY XOR #IX : #IY = #IX XOR #IY : #IX = #IY XOR #IX #T = #IY + #IY/2 #T = #IX - #IX/32 - #IX/128 + #T/4 + #T/64 END Quote Link to comment Share on other sites More sharing options...
+nanochess Posted February 15, 2018 Share Posted February 15, 2018 Wow! pretty cool! you both are better in maths than me This is my atan2 code from Meteors, it returns the angle in the range 0-71, and my cos/sin table with 6 bit precision: It depends on x(1) and x(0) to be in the range 0-159 and y(0) and y(1) in the range 0-95. IF x(1) > x(0) THEN IF y(1) > y(0) THEN d = atan2((x(1) - x(0)) / 4 + (y(1) - y(0)) / 4 * 40) + 54 ELSE d = 54 - atan2((x(1) - x(0)) / 4 + (y(0) - y(1)) / 4 * 40) END IF ELSE IF y(1) > y(0) THEN d = 90 - atan2((x(0) - x(1)) / 4 + (y(1) - y(0)) / 4 * 40) ELSE d = atan2((x(0) - x(1)) / 4 + (y(0) - y(1)) / 4 * 40) + 18 END IF END IF IF d >= 72 THEN d = d - 72 atan2: DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DATA 18,12,8,6,5,4,3,3,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 DATA 18,15,12,10,8,7,6,5,5,4,4,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1 DATA 18,16,14,12,10,9,8,7,6,6,5,5,5,4,4,4,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1 DATA 18,16,15,13,12,11,10,9,8,7,7,6,6,5,5,5,5,4,4,4,4,4,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2 DATA 18,17,15,14,13,12,11,10,9,9,8,7,7,7,6,6,6,5,5,5,5,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,2,2 DATA 18,17,16,15,14,13,12,11,10,10,9,8,8,8,7,7,6,6,6,6,5,5,5,5,5,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3 DATA 18,17,16,15,14,13,13,12,11,10,10,9,9,8,8,8,7,7,7,6,6,6,6,5,5,5,5,5,5,4,4,4,4,4,4,4,4,4,3,3 DATA 18,17,16,15,15,14,13,12,12,11,11,10,10,9,9,8,8,8,7,7,7,6,6,6,6,6,5,5,5,5,5,5,5,4,4,4,4,4,4,4 DATA 18,17,16,16,15,14,14,13,12,12,11,11,10,10,9,9,9,8,8,8,7,7,7,7,6,6,6,6,6,5,5,5,5,5,5,5,5,4,4,4 DATA 18,17,17,16,15,15,14,13,13,12,12,11,11,10,10,10,9,9,9,8,8,8,7,7,7,7,7,6,6,6,6,6,6,5,5,5,5,5,5,5 DATA 18,17,17,16,16,15,14,14,13,13,12,12,11,11,11,10,10,9,9,9,9,8,8,8,7,7,7,7,7,6,6,6,6,6,6,6,5,5,5,5 DATA 18,17,17,16,16,15,15,14,14,13,13,12,12,11,11,11,10,10,10,9,9,9,8,8,8,8,8,7,7,7,7,7,6,6,6,6,6,6,6,5 DATA 18,17,17,16,16,15,15,14,14,13,13,13,12,12,11,11,11,10,10,10,9,9,9,9,8,8,8,8,8,7,7,7,7,7,7,6,6,6,6,6 DATA 18,18,17,17,16,16,15,15,14,14,13,13,13,12,12,11,11,11,10,10,10,10,9,9,9,9,8,8,8,8,8,7,7,7,7,7,7,6,6,6 DATA 18,18,17,17,16,16,15,15,14,14,14,13,13,13,12,12,11,11,11,11,10,10,10,9,9,9,9,9,8,8,8,8,8,7,7,7,7,7,7,7 DATA 18,18,17,17,16,16,15,15,15,14,14,14,13,13,12,12,12,11,11,11,11,10,10,10,10,9,9,9,9,9,8,8,8,8,8,7,7,7,7,7 DATA 18,18,17,17,16,16,16,15,15,14,14,14,13,13,13,12,12,12,12,11,11,11,10,10,10,10,9,9,9,9,9,8,8,8,8,8,8,7,7,7 DATA 18,18,17,17,16,16,16,15,15,15,14,14,14,13,13,13,12,12,12,12,11,11,11,11,10,10,10,10,9,9,9,9,9,8,8,8,8,8,8,8 DATA 18,18,17,17,17,16,16,16,15,15,14,14,14,14,13,13,13,12,12,12,12,11,11,11,11,10,10,10,10,10,9,9,9,9,9,8,8,8,8,8 DATA 18,18,17,17,17,16,16,16,15,15,15,14,14,14,13,13,13,13,12,12,12,12,11,11,11,11,10,10,10,10,10,9,9,9,9,9,9,8,8,8 DATA 18,18,17,17,17,16,16,16,15,15,15,15,14,14,14,13,13,13,13,12,12,12,12,11,11,11,11,10,10,10,10,10,10,9,9,9,9,9,9,8 DATA 18,18,17,17,17,16,16,16,16,15,15,15,14,14,14,14,13,13,13,13,12,12,12,12,11,11,11,11,11,10,10,10,10,10,9,9,9,9,9,9 DATA 18,18,17,17,17,17,16,16,16,15,15,15,15,14,14,14,13,13,13,13,12,12,12,12,12,11,11,11,11,11,10,10,10,10,10,10,9,9,9,9 cos: DATA 0 DATA 6 DATA 11 DATA 17 DATA 22 DATA 27 DATA 32 DATA 37 DATA 41 DATA 45 DATA 49 DATA 52 DATA 55 DATA 58 DATA 60 DATA 62 DATA 63 DATA 63 DATA 63 DATA 63 DATA 63 DATA 62 DATA 60 DATA 58 DATA 55 DATA 52 DATA 49 DATA 45 DATA 41 DATA 37 DATA 32 DATA 27 DATA 22 DATA 17 DATA 11 DATA 6 DATA 0 DATA -5 DATA -10 DATA -16 DATA -21 DATA -26 DATA -31 DATA -36 DATA -40 DATA -44 DATA -48 DATA -51 DATA -54 DATA -57 DATA -59 DATA -61 DATA -62 DATA -63 DATA -63 DATA -63 DATA -62 DATA -61 DATA -59 DATA -57 DATA -54 DATA -51 DATA -48 DATA -44 DATA -40 DATA -36 DATA -31 DATA -26 DATA -21 DATA -16 DATA -10 DATA -5 sin: DATA -63 DATA -63 DATA -62 DATA -61 DATA -59 DATA -57 DATA -54 DATA -51 DATA -48 DATA -44 DATA -40 DATA -36 DATA -31 DATA -26 DATA -21 DATA -16 DATA -10 DATA -5 DATA 0 DATA 6 DATA 11 DATA 17 DATA 22 DATA 27 DATA 32 DATA 37 DATA 41 DATA 45 DATA 49 DATA 52 DATA 55 DATA 58 DATA 60 DATA 62 DATA 63 DATA 63 DATA 63 DATA 63 DATA 63 DATA 62 DATA 60 DATA 58 DATA 55 DATA 52 DATA 49 DATA 45 DATA 41 DATA 37 DATA 32 DATA 27 DATA 22 DATA 17 DATA 11 DATA 6 DATA 0 DATA -5 DATA -10 DATA -16 DATA -21 DATA -26 DATA -31 DATA -36 DATA -40 DATA -44 DATA -48 DATA -51 DATA -54 DATA -57 DATA -59 DATA -61 DATA -62 DATA -63 2 Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted February 16, 2018 Share Posted February 16, 2018 I wonder how far I can really go making games without understanding (or implementing) any of these things. 1 Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted February 19, 2018 Share Posted February 19, 2018 Can I ask a stupid question? What's an application for this atan() routine? Where and why would I use it for? Quote Link to comment Share on other sites More sharing options...
+nanochess Posted February 19, 2018 Share Posted February 19, 2018 Can I ask a stupid question? What's an application for this atan() routine? Where and why would I use it for? It's the easiest way to point a shoot from an enemy to the player. Another way would be a Bresenham line but I'm lazy I think the startup calculations are too "heavy". Quote Link to comment Share on other sites More sharing options...
artrag Posted February 19, 2018 Author Share Posted February 19, 2018 (edited) Moreover using Bresenham for bullets of variable speed is not very practical, as you need to reiterate controls for each step of one pixel on the short side and it is not easy to calibrate the final speed (actually one could run two Bresenham algorithms, one on x the other on y, using time as short side, but things can get complex at will). Edited February 19, 2018 by artrag Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted February 19, 2018 Share Posted February 19, 2018 Sorry, if I'm really dense, but I still don't get how I would use this. I know how I would do this with bresenham (and like artrag said, it would require adjusting as you go along), but I don't know how to use the arctangent. (I also don't really recall much of my high-school trig). So you compute the angle at which to shoot, then what? Do you then use that to compute the x and y velocity components? Quote Link to comment Share on other sites More sharing options...
artrag Posted February 19, 2018 Author Share Posted February 19, 2018 Use cosine and sine of the resulting angle They are the dx and dy of the bullet Scale them to variate speed 3 Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted February 19, 2018 Share Posted February 19, 2018 Use cosine and sine of the resulting angle They are the dx and dy of the bullet Scale them to variate speed Aha! Got it. Thanks! -dZ. Quote Link to comment Share on other sites More sharing options...
intvnut Posted February 21, 2018 Share Posted February 21, 2018 I personally prefer to normalize the vector (dx, dy) if I can come up with a fast way to do that. Saves the trip through the arctan, sine and cosine and ends up being more accurate. atan2() though can also be useful for picking a picture to render for an object, if the picture needs to change with respect to the object's actual heading. Quote Link to comment Share on other sites More sharing options...
artrag Posted February 21, 2018 Author Share Posted February 21, 2018 (edited) I personally prefer to normalize the vector (dx, dy) if I can come up with a fast way to do that. Saves the trip through the arctan, sine and cosine and ends up being more accurate. atan2() though can also be useful for picking a picture to render for an object, if the picture needs to change with respect to the object's actual heading. I will try to use logarithms to avoid the division and the norm approximation you posted. For single bullets maybe it could be interesting. Anyway if you need to cast more bullets in a range of angles atan is the way. Edited February 21, 2018 by artrag Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted February 21, 2018 Share Posted February 21, 2018 I personally prefer to normalize the vector (dx, dy) if I can come up with a fast way to do that. What do you mean? Quote Link to comment Share on other sites More sharing options...
artrag Posted February 21, 2018 Author Share Posted February 21, 2018 (edited) DZ, when you cast a bullet from (x0,y0) to (x1,y1), the full computation should be: dx = x1-x0 dy = y1-y0 vx = s*dx/sqrt(dx*dx+dy*dy) vy = s*dy/sqrt(dx*dx+dy*dy) Where s is the speed of the bullet in pixels per loop iteration and (vx,vy) are the increments to be applied along the x and y to move the bullet Assuming to approximate sqrt(dx*dx+dy*dy) as above by dist_fast(dx,dy), you still need two divisions to get the increments norm = dist_fast(dx,dy) vx = s*dx/norm vy = s*dy/norm Divisions are very time consuming and should be avoided when possible A trick to avoid divisions is to resort to logarithms, because for positive numbers, if a=b/c, then a = 2^(log2(b)-log2( c)) Naturally if you want speed, you need to use tables of precomputed values, introducing some more approximations In our case, willing to use tables of max 256 elements, limiting dx in -128,128, we have: vx = s*dx/norm = sign(dx)* 2^(1/32*(32*log2(s)+32*log2(abs(dx))-32*log(norm))) same for vy so, we need a table of 128 values for the logarithm logtab(x) = round(32*log2(x)) with x = 1:128 and a table of 256 values for the antilogarithm antilog(x) = round(2^(x/32)) with x = 0:255 With the above tables you get vx = sign(dx)*antilog(logtab(s)+logtab(abs(dx))-logtab(norm)) You can keep the antilog array of sole 256 elements even using 36 instead of 32 in the above formulas if |dx|<128. This increases slightly the overall accuracy, but in the end you get quite approximated results especially for large values of s and of |dx| or of |dy|. This could be due to accumulated effects of the norm approximation and of the rounding in the tables when we use values close to 128. The pro is that it is very fast! You have done just 4 accesses to tables (3 if the speed s is constant) and a couple of additions. Computing vy too, you reach 6 table accesses and 4 sums/subtractions that should be added to the 8 sums/logical operation and 5 shifts needed by dist_fast() The other way is to use cosine and sine. DZ, What you need to know is that vx = s*dx/sqrt(dx*dx+dy*dy) = s * cos(alpha) vy = s*dy/sqrt(dx*dx+dy*dy) = s * sin(alpha) where alpha is the angle of the right-angled triangle of sides dx and dy opposite to the side dy Provided that tangent is defined in this way tang(alpha) = sin(alpha)/cos(alpha) = dy / dx and that arc-tangent is its inverse function for alpha in 0-180 degree, we have: alpha = atan(dy/dx) + k *180° where k can be determined by examining the signs of dx and dy separately. The above atan2(dx,dy) function returns alpha unrolled in the whole circle, resolving the 180° uncertainness of the normal atan() With this method, once you have dx and dy you need to do alpha = atan2(dx,dy) vx = s * cos(alpha) vy = s * sin(alpha) You get errors in any case when dx and dy are large, but the overall error is in +/- 1 step in the alpha angle The cost is 3 table accesses and an addition in atan2, plus two table accesses and two multiplications for vx,vy. Total 5 table accesses, 1 addition, two multiplications. In the end: dist_fast and logarithms are faster but less accurate atan2(), cos() and sin() are slower but more accurate PS: the latter method is more interesting if you want to cast more bullets at the same time, e.g. 3 bullets, one at alpha, one at alpha+beta and one at alpha-beta Edited February 23, 2018 by artrag 4 Quote Link to comment Share on other sites More sharing options...
artrag Posted March 11, 2018 Author Share Posted March 11, 2018 (edited) A small demo of atan2() just for fun, being lazy, I have left the PSG log player as background Sources and data included [EDIT] now correct sources included (I hope...) atan2_pt3_demo.rom atan2_pt3_demo.rar Edited March 11, 2018 by artrag Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted March 11, 2018 Share Posted March 11, 2018 A small demo of atan2() just for fun, Being lazy, I have leaved the PSG log player as background Sources and data included Awesome, artrag! It illustrates the case perfectly. Thanks for posting it. Nanochess, you should consider including something like this as a "contrib" in the next version of IntyBASIC. -dZ. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted March 11, 2018 Share Posted March 11, 2018 A small demo of atan2() just for fun, Being lazy, I have leaved the PSG log player as background Sources and data included artrag, The RAR archive contains all the scripts and logs to generate the music data, but not the IntyBASIC source code to illustrate how to use the arctan() function. Perhaps it was an oversight? -dZ. Quote Link to comment Share on other sites More sharing options...
artrag Posted March 11, 2018 Author Share Posted March 11, 2018 True, I will fix it tonight Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted March 11, 2018 Share Posted March 11, 2018 True, I will fix it tonight No worries. Thanks again! -dZ. Quote Link to comment Share on other sites More sharing options...
artrag Posted March 11, 2018 Author Share Posted March 11, 2018 (edited) No worries. Thanks again! -dZ. Try now in the previous post. I fixed the sources Here, instead, there is a slightly more advanced demo with 3 bullets atan2_pt3_demo.rar atan2_pt3_demo.rom Edited March 11, 2018 by artrag 1 Quote Link to comment Share on other sites More sharing options...
+nanochess Posted March 11, 2018 Share Posted March 11, 2018 A small demo of atan2() just for fun, Being lazy, I have leaved the PSG log player as background Sources and data included [EDIT] now correct sources included (I hope...) Pretty nice demo Awesome, artrag! It illustrates the case perfectly. Thanks for posting it. Nanochess, you should consider including something like this as a "contrib" in the next version of IntyBASIC. -dZ. I would be happy to include it if it's made to use a single source file. I don't have yet decided how to include multi-source contributions. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted March 12, 2018 Share Posted March 12, 2018 Try now in the previous post. I fixed the sources Here, instead, there is a slightly more advanced demo with 3 bullets That looks very nice! Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted March 12, 2018 Share Posted March 12, 2018 Pretty nice demo I would be happy to include it if it's made to use a single source file. I don't have yet decided how to include multi-source contributions. Also, I would recommend artag to include REM comments describing how the code works -- that's if he wants to submit it as a contribution to the SDK and the compiler's library. -dZ. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted October 21, 2021 Share Posted October 21, 2021 On 2/16/2018 at 7:58 AM, DZ-Jay said: I wonder how far I can really go making games without understanding (or implementing) any of these things. And the answer is ... not very far, apparently. * As soon as I needed a bullet in a game, this thread became relevant. Thanks again to @artrag, @intvnut, and @nanochess for the lively discussion. dZ. * Well, I can rip off artrag's code from this thread and still not know anything about how it works, so perhaps farther than expected. 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.