Heaven/TQA #1 Posted July 18, 2005 as programming Boinxx i want to code some nasties (enemies) which haunt the player... i was always a fan of kind of dynamic approach and would like to ask you 6502 wizards how would you do that... i am thinking of flying objects like in the arcade game Sinistar by Williams... i would use 8.8 fixed point maths for the dynamics but i am not sure if this is too slow... maybe 4.4 is enough. i would need xp,yp [the positions of the nasty on screen] vx,vy [velocity] what else do we need? accelerationx,y? maybe there are existing models which i could adapt... Quote Share this post Link to post Share on other sites
vdub_bobby #2 Posted July 18, 2005 I'm not sure exactly what you're asking, so if this isn't it then just ignore But for the various things I've done with fractional positioning, this has worked well: Have 8.8 variables for position (x and y) and single bytes (integer) for velocity. Then, every frame (on the 2600) I add velocity to the fractional position and, if the fractional position overflows then I increment/decrement the integer position. Here's a code sample, edited for clarity (from the arkanoid clone I'm working on now): MoveBallSubroutine ;--first add velocity to fractional position lda BallX_fraction clc adc BallVelocityX sta BallX_fraction ;---now, if we overflowed (result is greater than +127 or less than -128) ; then we want to inc/dec integer position bvc NoOverflowBallX ;--so, we overflowed; therefore increment or decrement integer position ; (which way depends on carry flag) bcc MoveBallRight dec BallX ;--now, reset the fractional position (not always necessary) ; A still holds fractional position from above clc adc #120 sta BallX_fraction jmp UpdateBallY MoveBallRight inc BallX ;--now, reset the fractional position (not always necessary) ; A still holds fractional position from above sec sbc #120 sta BallX_fraction NoOverflowBallX UpdateBallY ;--and similar for Y position and etc. This is nice because it handles positive/negative velocity (-128 to +127). Main problem with this method is that it isn't possible to change the integer position by more than 1 per frame; so the upper limit of your speed is 1 pixel/frame. To get higher speeds I guess you would have to use fixed point velocity. Other issue with this is that it takes a little work to get positive and negative speeds to be symmetrical, since fractional position will overflow at -128 and +127. I've never stored acceleration; all velocity changes I've ever coded have been event driven. Quote Share this post Link to post Share on other sites
Cybergoth #3 Posted July 18, 2005 Hi there! Main problem with this method is that it isn't possible to change the integer position by more than 1 per frame; so the upper limit of your speed is 1 pixel/frame. Just call it twice or thrice per frame... Greetings, Manuel Quote Share this post Link to post Share on other sites
Heaven/TQA #4 Posted July 18, 2005 what about this... sorry. haven't read the source from arkanoid but what about this: 1 F=8 5 GRAPHICS 15+16 7 COLOR 1 9 DEG 10 ------------------------------ 20 REM ENEMY 30 ------------------------------ 40 PX=80 50 PY=96 60 VPX=0 70 VPY=0 80 ------------------------------ 90 EX=RAND(159) 100 EY=RAND(191) 110 VEX=1 120 VEY=1 125 DO 126 COLOR 1 127 IF PX<0 THEN 135 130 TEXT PX,PY,"P" 135 COLOR 2 140 TEXT EX,EY,"E" 150 EXEC CALC 170 I=I+3 171 C=C+3 175 IF I=180 THEN EX=RAND(159):EY=RAND(160):I=0:CLS #6 180 PX=INT(SIN(C)*80+79) 185 PY=INT(COS(C)*80+95) 999 LOOP 1000 PROC CALC 1010 VEX=PX-EX 1020 VEY=PY-EY 1040 VEX=(VEX/F) 1050 VEY=(VEY/F) 1060 EX=EX+VEX 1070 EY=EY+VEY 1099 ENDPROC it's written in atari turbo basic xl for rapid testing... and it was written having 6502 in mind... so don't afraid of the divisions as they are just ASLs... and some lookup tables... ignore the sin,cos there... it's just moving the "P" sprite around on the screen while the "E" sprite is trying to catch it. after 180 degrees (half circle) the enemy is position new. PX,PY = player position on screen VEX,VEY = velocity x,y enemy EX,EY = position enemy on screen so very straight forward...should be easy to implement... there is only one thing here... the enemy does not have a "boost" to catch the player.... as the player is moving faster than the enemy could... but i'll show you code how this can be handled.... now back to the 2600 arkanoid code in detail. Quote Share this post Link to post Share on other sites
vdub_bobby #5 Posted July 18, 2005 what about this... sorry. haven't read the source from arkanoid but what about this: I haven't posted the source to my 2600 Arkanoid demo, so don't be sorry it's written in atari turbo basic xl for rapid testing... and it was written having 6502 in mind... so don't afraid of the divisions as they are just ASLs... and some lookup tables... ignore the sin,cos there... it's just moving the "P" sprite around on the screen while the "E" sprite is trying to catch it. after 180 degrees (half circle) the enemy is position new. PX,PY = player position on screen VEX,VEY = velocity x,y enemy EX,EY = position enemy on screen so very straight forward...should be easy to implement... there is only one thing here... the enemy does not have a "boost" to catch the player.... as the player is moving faster than the enemy could... but i'll show you code how this can be handled.... now back to the 2600 arkanoid code in detail. Nah, don't go back to the arkanoid code unless you want to. Quote Share this post Link to post Share on other sites
vdub_bobby #6 Posted July 18, 2005 (edited) 1000 PROC CALC 1010 VEX=PX-EX 1020 VEY=PY-EY 1040 VEX=(VEX/F) 1050 VEY=(VEY/F) 1060 EX=EX+VEX 1070 EY=EY+VEY 1099 ENDPROC Won't this make velocity dependent on how far apart the two sprites are from each other? Is this intended? EDIT: And the behavior produced by this will be an enemy sprite who always moves towards the player, right? Something a little more interesting might be better - maybe updating the enemy velocity at infrequent intervals would produce more interesting behavior. ?? Or not allowing the enemy to turn sharply would reward evasive action on the part of the player. Edited July 18, 2005 by vdub_bobby Quote Share this post Link to post Share on other sites
vdub_bobby #7 Posted July 18, 2005 Here's another possible enemy behavior...in 6502 assembly. lda PX sec sbc EX beq EnemyInLineHorizWithPlayer bmi EnemyToRightOfPlayer ;--else enemy to the left of the player lda VEX clc adc #VELOCITY_CHANGE_CONSTANT sta VEX bvc DoneChangingVelocity ;--if overflow set, then we increased velocity beyond the maximum, so reset to maximum lda #127 sta VEX jmp DoneChangingVelocity EnemyToRightOfPlayer lda VEX sec sbc #VELOCITY_CHANGE_CONSTANT sta VEX bvc DoneChangingVelocity ;--if overflow set, then we decreased velocity below the minimum, so reset to minimum lda #-128 sta VEX DoneChangingVelocity EnemyInLineHorizWithPlayer ;---now change Y component of velocity...etc. etc. ;---done changing Y velocity, now: ;---apply velocity to position ;... The behavior of this enemy would be something similar to the player-controlled ship in Asteroids. This is set up to use code for applying the velocity to the position similar to the arkanoid code I posted above. Quote Share this post Link to post Share on other sites
Heaven/TQA #8 Posted July 18, 2005 as this code is only for one type of enemy... this type is trying to catch you... of course the player can move around and the enemy tries to catch you... this formular is very simple 2 improvements might be to do: 1st: the enemy is starting fast and slowing down as near as it gets to the player... maybe it must be the otherway around (start slow, move faster like homing missles) 2nd: right now the player is not reached when the enemy gets track of the player movement (as its moving not faster when its near...the max is as fast as the player...) i have some formulars to handle this but we will see... i am glad that i have found even this type... next will be to implement this into 6502... good exercise as it must use fixed point maths... and some divisions (ASLs or LSR depending on sign/unsign) i have printed out the numbers of VEX,Y and it never gets bigger than 8...so i could use 3.5 maths f.e. as well... but i never used this since 1986... my fixed point math experience was always 8.8 (8 byte integer, 8 byte fractional)... but i think thomas and the rest will help me Quote Share this post Link to post Share on other sites
Heaven/TQA #9 Posted July 18, 2005 vdup... have a look at sinistar in MAME or in any Williams arcade classics where the game is... asteroid is not the right one...but maybe you can imagine if the player ship would hunt you while you turn around and move around...then maybe it's more visible what i want to achive. unfortunatly i just can't remember a 2600 game doing that... what about warhawk on atari800 or zone ranger or crazy comets on c64.... Quote Share this post Link to post Share on other sites
Heaven/TQA #10 Posted July 18, 2005 but i will check your code out if it works similar as it looks straight forward... Quote Share this post Link to post Share on other sites
vdub_bobby #11 Posted July 19, 2005 Ok; sorry, I misunderstood your question. I played some Sinistar and now I understand what you're asking. I'm not sure exactly how to duplicate that flight pattern, but there is a 2600 rom for Sinistar that you could disassemble. Quote Share this post Link to post Share on other sites
Heaven/TQA #12 Posted July 19, 2005 just had a look on the 2600 sinistar.... definitly NOT this version... as there is no dynamics. the player ship seems to have 3 speeds (no velocity) and the enemies are flying around like in galaga...as well it seems no velocity... i don't know how you are rating this proto...but imho its ugly crap... Quote Share this post Link to post Share on other sites
vdub_bobby #13 Posted July 19, 2005 Okay...using the method I posted above for changing the velocity, you could then adjust the magnitude of the velocity in this way, so that the enemy ships move slower when they get closer to the player ship: lda PX sec sbc EX ;A holds PX-EX jsr GetAbsoluteValue;A holds abs(PX-EX) lsr lsr lsr lsr ;A holds abs(PX-EX)/16 -- range: 0 - 8 sta Temp lda PY sec sbc EY jsr GetAbsoluteValue lsr lsr lsr lsr clc adc Temp ;A holds abs(PX-EX)/16 + abs(PY-EY)/16 ;--rough distance between player and enemy, ;--range: 0 to 16 tax lda VelocityAdjusterTable,X tay beq DoneAdjustingVelocity lda VEX sta VEX_Adjusted lda VEY sta VEY_Adjusted AdjustVelocityLoop lsr VEX_Adjusted lsr VEY_Adjusted dey bne AdjustVelocityLoop DoneAdjustingVelocity ;---now apply VEX_Adjusted and VEY_Adjusted to EX and EY VelocityAdjusterTable .byte 6,6,5,5,4,4,3,3,2,2,1,1,0,0,0,0 ;adjust these values until ;the effect is what you want This is untested, so it may not work and it may not do what I think it should do, but I think that this, combined with the method I posted above, will give a quick and dirty approximation of the Sinistar enemy flight patterns. Quote Share this post Link to post Share on other sites
djmips #14 Posted July 19, 2005 This isn't a full solution but just an alternative calc for distance between two objects. x1,y1 - position of one object x2,y2 - position of other object dx = abs(x1-x2) dy = abs(y1-y2) dist = max(dx,dy) + 1/4(min(dx,dy)) The 6502 is just off the top of my head approxDist: lda x1 sec sbc x2 bcs pdx eor #255 adc #1 pdx: sta dx lda y1 sec sbc y2 bcs pdy eor #255 adc #1 pdy: sta dy cmp dx bcs dyg lsr lsr clc adc dx rts dyg: lda dx lsr lsr clc adc dy rts Quote Share this post Link to post Share on other sites