Jump to content

Photo

how to disable specific copy of enemy


23 replies to this topic

#1 easmith OFFLINE  

easmith

    Chopper Commander

  • 148 posts
  • Location:Alexandria, VA

Posted Sat Jan 20, 2018 11:09 AM

Ok so my "retirement " lasted 2 days....  going down the hole..

Thanks for the awesome help.  Makes it easier to keep going.

 

 

 

I now have a my P1 enemy copied three times .  My code skips the enemy draw if  the enemy is hit my missile.

 

This makes all three copies disappear of course if any of them are hit.

 

How to get the specific enemy hit to disappear is my current challenge.

 

Perhaps this involves more complicated timing and redrawing a single copy on multiple lines.  But even this seems like it would eliminate all  enemy images if any are hit.

 

Changing the NUSIZ1 register would reduce the copies but would not remove the correct one.

 

Again, probably missing something obvious.  This might be a level 10 skill for a level 1 user.

Attached Files



#2 ZackAttack OFFLINE  

ZackAttack

    Dragonstomper

  • 745 posts
  • Location:Orlando, FL US

Posted Sat Jan 20, 2018 11:34 AM

NUSIZ1 can remove the correct one if you also adjust the position to compensate. I.e. change 3 med to 2 med and move right 16 to remove the left enemy

#3 easmith OFFLINE  

easmith

    Chopper Commander

  • Topic Starter
  • 148 posts
  • Location:Alexandria, VA

Posted Sat Jan 20, 2018 4:26 PM

I suppose it will take two consecutive hmoves of 8 to accomplish the shift right to remove left alien after NUSIZE1 from 3 med to 2 med  ....

To remove middle , 3 med to 2 wide I suppose

to remove right, 3 med to 2 med ....

But how to keep track of which copy was hit?  



#4 ZackAttack OFFLINE  

ZackAttack

    Dragonstomper

  • 745 posts
  • Location:Orlando, FL US

Posted Sat Jan 20, 2018 7:42 PM

I don't know how existing games have chosen to implement this, but if I were to do it I'd view the three enemies as a single enemy. This aggregate enemy would have 8 states corresponding to which of the three copies is active. (3 copies, 2 states, 2^3=8 states total)

 

The collision flag can tell you that the enemy was hit somewhere, then you have to compare missile position with enemy position and transition to a different state based on which copy was hit and which state you're currently in. Since there's only 8 states and 3 copies you could have a table to track which state to transition to. That should only be 24 bytes of ROM. Simply take copyHit, shift left 3, bitwise OR with currentState and you have the index into the table to update currentState with. You'll probably want some tables to lookup the NUSIZ1 value for each state (8 ROM bytes), and the horizontal offset for each transition (24 ROM bytes). Still it's only taking up 56 bytes of ROM total for the state management lookup tables.

 

I wouldn't use hmoves to adjust the position when the left copy is removed. Instead I'd just add 16 to the variable which stores P1's horizontal position. You're going to have to keep track of it's position for the collision detection anyway so I'd use the PositionObject() routine each frame instead of using hmove to move around the enemies.

 

Hope that helps.



#5 easmith OFFLINE  

easmith

    Chopper Commander

  • Topic Starter
  • 148 posts
  • Location:Alexandria, VA

Posted Sat Jan 20, 2018 8:54 PM

alright, this one should keep me busy for a while.....  thanks again



#6 vidak OFFLINE  

vidak

    Moonsweeper

  • 458 posts
  • Location:Sydney, Australia

Posted Sat Jan 20, 2018 8:54 PM

I don't know how existing games have chosen to implement this, but if I were to do it I'd view the three enemies as a single enemy. This aggregate enemy would have 8 states corresponding to which of the three copies is active. (3 copies, 2 states, 2^3=8 states total)

 

The collision flag can tell you that the enemy was hit somewhere, then you have to compare missile position with enemy position and transition to a different state based on which copy was hit and which state you're currently in. Since there's only 8 states and 3 copies you could have a table to track which state to transition to. That should only be 24 bytes of ROM. Simply take copyHit, shift left 3, bitwise OR with currentState and you have the index into the table to update currentState with. You'll probably want some tables to lookup the NUSIZ1 value for each state (8 ROM bytes), and the horizontal offset for each transition (24 ROM bytes). Still it's only taking up 56 bytes of ROM total for the state management lookup tables.

 

I wouldn't use hmoves to adjust the position when the left copy is removed. Instead I'd just add 16 to the variable which stores P1's horizontal position. You're going to have to keep track of it's position for the collision detection anyway so I'd use the PositionObject() routine each frame instead of using hmove to move around the enemies.

 

Hope that helps.

 

Well I sure learned something here.

 

This is amazing help, in my opinion.



#7 easmith OFFLINE  

easmith

    Chopper Commander

  • Topic Starter
  • 148 posts
  • Location:Alexandria, VA

Posted Sun Jan 21, 2018 11:28 AM

I don't know how existing games have chosen to implement this, but if I were to do it I'd view the three enemies as a single enemy. This aggregate enemy would have 8 states corresponding to which of the three copies is active. (3 copies, 2 states, 2^3=8 states total)

 

The collision flag can tell you that the enemy was hit somewhere, then you have to compare missile position with enemy position and transition to a different state based on which copy was hit and which state you're currently in. Since there's only 8 states and 3 copies you could have a table to track which state to transition to. That should only be 24 bytes of ROM. Simply take copyHit, shift left 3, bitwise OR with currentState and you have the index into the table to update currentState with. You'll probably want some tables to lookup the NUSIZ1 value for each state (8 ROM bytes), and the horizontal offset for each transition (24 ROM bytes). Still it's only taking up 56 bytes of ROM total for the state management lookup tables.

 

I wouldn't use hmoves to adjust the position when the left copy is removed. Instead I'd just add 16 to the variable which stores P1's horizontal position. You're going to have to keep track of it's position for the collision detection anyway so I'd use the PositionObject() routine each frame instead of using hmove to move around the enemies.

 

Hope that helps.

 

perhaps you could give me a bit more of a hint on what you are envisioning with the table. I am not sure I can see it/ too dumb to see it.

 

 

As for determining which copy was hit, here is an example of my logic for 3 active copies:

 

1.  determine missile x pos  ( player x pos + 8  at time of fire , player is double wide) ( assuming player x position is left edge of player)

2. if collision detected

    add 12 to enemy left copy x   and store ( position half way between copy 1 and 2)

   add another 16  to enemy left copy x and store ( position half way between copy 2 and 3)

3. if missile x pos>  (left copy x +28)  then copy 3 was hit

   else 

   if missile xpos <  (leftcopy x +12) then copy one was hit

  else copy 2 was hit.

 

Seems like this should work  but it is not......


Edited by easmith, Sun Jan 21, 2018 11:38 AM.


#8 ZackAttack OFFLINE  

ZackAttack

    Dragonstomper

  • 745 posts
  • Location:Orlando, FL US

Posted Sun Jan 21, 2018 7:59 PM

perhaps you could give me a bit more of a hint on what you are envisioning with the table. I am not sure I can see it/ too dumb to see it.
 
 
As for determining which copy was hit, here is an example of my logic for 3 active copies:
 
1.  determine missile x pos  ( player x pos + 8  at time of fire , player is double wide) ( assuming player x position is left edge of player)
2. if collision detected
    add 12 to enemy left copy x   and store ( position half way between copy 1 and 2)
   add another 16  to enemy left copy x and store ( position half way between copy 2 and 3
)
3. if missile x pos>  (left copy x +28)  then copy 3 was hit
   else 
   if missile xpos <  (leftcopy x +12) then copy one was hit
  else copy 2 was hit.
 
Seems like this should work  but it is not......

 
Your hit detection algorithm appears to be correct. You probably just have a bug in the implementation of it. Don't forget to post asm and bin files for problems like this. We can't help with debugging without them.
 
Regarding the tables. Here's some more details.
 
Variables:
enemyHitIndex - Should be 0 for the left copy, 1 for the middle copy and 2 for the right copy
enemyX - X position of enemy stored as distance between left side of screen and left side of left copy in pixels. This should always apply to the left copy regardless of it being active to keep hit detection simple.
enemyXOffset - offset to be added to the enemyX position when calling the PostionObject routine.
enemyState - 3 bit value indicating the state of the enemy. Spawn with state 7 for 3 active copies, and don't draw for state 0 because there are no copies left. Each bit corresponds to a single copy. 1 indicates the copy is active(visible), and 0 indicates it is inactive(hidden) I.E. %00000101 = X _ X and %00000110 = X X _
 
Lookup Tables:
EnemyXOffsetLooup - Use the same index as the EnemyStateTransitionLookup to determine what value to add to the current enemyX value. This compensates for deactivating the leftmost active copy of the enemy by moving it right to where the next copy starts.
EnemyStateTransitionLookup - Index into this table with the hit detection result and enemyState to determine what the next state should be. Index is the concatenation of the 2 Hit bits (H) and 3 State bits (S) in the format %000HHSSS
EnemyNusizLookup - Index into this table with the enemyState value to determine the correct NUSIZ1 value.
 
Here's some sample code. It's untested, but should be close to what you need.
 

; Calculate state transition index
  enemyHitIndex
  asl
  asl
  asl
  ora enemyState
  tax

; update X offset
  ; assumes C flag is cleared by code above. If something else comes between this two sections add a CLC instruction here
  lda EnemyXOffsetLooup,x
  adc enemyXOffset
  sta enemyXOffset

; update current state
  ; x still has transition index
  lda EnemyStateTransitionLookup,x
  sta enemyState

; Set NUSIZ1.
  ; assumes A contains enemyState. If this is done late you must replace tax with ldx enemyState
  tax
  lda EnemyNusizLookup,x
  sta NUSIZ1

 
The tables shouldn't be difficult to generate manually. The states are 3 bits, just visualize which copies are still active after a hit occurs. The offsets will be 0 except for a few cases where the left copy is hit, in those cases the value will be 16. The NUSIZ lookup is just mapping the state to the right count and spacing for the remaining active copies.
 
EnemyXOffsetLooup

00000 - 0 ; 
...
00100 - 0 ; Left copy hit, but already inactive. No action required.
00101 - 16 ; Left copy hit and middle is already gone So move over 32 because right copy is all that's left
00111 - 16 ; Left copy hit which means the middle copy will be the new location. So move over 16
...
01011 - 16 ; middle copy hit leaving only the right copy. So move over 16
...

 
EnemyStateTransitionLookup​:

00011 - 011 ; State unchanged because inactive enemy was hit, normal execution will never go here
...
00111 - 011 ; Left copy hit and deactivated
...
01111 - 101 ; Middle copy hit and deactivated
...
10111 - 110 ; Right copy hit and deactivated

 
EnemyNusizLookup:

000 - 7 ; make it quad cause we should never draw this
001 - 0 ; single copy for the right copy
010 - 0 ; single copy for the middle copy
011 - 1 ; 2 copies close for middle and right copies
100 - 0 ; single copy for the left copy
101 - 2 ; 2 copies med for left and right copies
110 - 1 ; 2 copies close for left and middle
111 - 3 ; 3 copies close for left, middle, right


#9 easmith OFFLINE  

easmith

    Chopper Commander

  • Topic Starter
  • 148 posts
  • Location:Alexandria, VA

Posted Sun Jan 21, 2018 11:15 PM

thanks..  I am pretty darn impressed by your skills....

 

 

But I couldn't  move on to yet to transitions from 3 enemies until I figured out the correct detection of which enemy is hit

 

For simplicity,  I reduced to 2 enemy copies to  get the basic detection logic correct .

This seems to be working now, the key was keeping track of enemy x and repositioning each frame, as you suggested.

 

I think before, when I was positioning before the main loop,  my enemy  x position counter was ending up out of step with the actual screen positon due to the horizontal wraparound?

 

At any rate , now my enemies have a "jitter" .  I can't figure out why this is happening.  When I positioned the enemy before main loop the enemy motion was smooth ( decreasing right to left)

 

see difference from shooter 4 to shooter 7

Attached Files


Edited by easmith, Sun Jan 21, 2018 11:16 PM.


#10 ZackAttack OFFLINE  

ZackAttack

    Dragonstomper

  • 745 posts
  • Location:Orlando, FL US

Posted Mon Jan 22, 2018 2:24 PM

I think what happened is that the position alien routine has been broken, but since you only used it for the initial position in version 3 it went unnoticed. Now that you're using it every frame it's noticeable. The problem is that you can't write to any of the HMxx registers immediately after you strobe HMOVE. You must wait at least 24 cycles or it will interfere with the HMOVE process. (See stella programmer guide pg9)

 

This may also explain the problems you're having with detecting which copy was hit. That's not going to work so well if the objects are not positioned where you think they are.

 

You're routine is also a few cycles off for other reasons. Why don't you just use the code from the collect tutorial? No need to make your own unless you're trying to do something advanced like positioning objects while also drawing a playfield.

    sta WSYNC
   sta HMOVE
    lda #0
    sta HMP1 ;TOO SOON!!!



#11 easmith OFFLINE  

easmith

    Chopper Commander

  • Topic Starter
  • 148 posts
  • Location:Alexandria, VA

Posted Mon Jan 22, 2018 3:51 PM

 

I think what happened is that the position alien routine has been broken, but since you only used it for the initial position in version 3 it went unnoticed. Now that you're using it every frame it's noticeable. The problem is that you can't write to any of the HMxx registers immediately after you strobe HMOVE. You must wait at least 24 cycles or it will interfere with the HMOVE process. (See stella programmer guide pg9)

 

This may also explain the problems you're having with detecting which copy was hit. That's not going to work so well if the objects are not positioned where you think they are.

 

You're routine is also a few cycles off for other reasons. Why don't you just use the code from the collect tutorial? No need to make your own unless you're trying to do something advanced like positioning objects while also drawing a playfield.

    sta WSYNC
   sta HMOVE
    lda #0
    sta HMP1 ;TOO SOON!!!

 

 

 

ok ----I was missing a shift in my positioning code. That and removing the hmp1 clear too soon  fixed it   .   I remember reading that in the Stella guide , but it's a lot to keep track of.    Man what a finicky sucker this  is....

 

Thanks again, see attached.   ( Keyboard 1 resets ) 

Attached Files


Edited by easmith, Mon Jan 22, 2018 6:35 PM.


#12 SpiceWare OFFLINE  

SpiceWare

    Draconian

  • 12,411 posts
  • Medieval Mayhem
  • Location:Planet Houston

Posted Mon Jan 22, 2018 4:00 PM

I remember reading that in the Stella guide , but it's a lot to keep track of.    Man what a finicky sucker this  is....

True, but doing the wrong thing often leads to useful results.  Hitting the HMxx registers at the wrong time leads to stars, while hitting HMOVE at the wrong time can eliminate the black bars that normally occur when repositioning objects mid-screen.
 



#13 easmith OFFLINE  

easmith

    Chopper Commander

  • Topic Starter
  • 148 posts
  • Location:Alexandria, VA

Posted Mon Jan 22, 2018 4:18 PM

cool thanks. I am not using missile 1 right now I will give the star effect a try .



#14 easmith OFFLINE  

easmith

    Chopper Commander

  • Topic Starter
  • 148 posts
  • Location:Alexandria, VA

Posted Tue Jan 23, 2018 9:02 PM

ok,something weird has happened .    All of a sudden the game stopped firing when the button pressed , although I did not change the code..........

 

Could this be a  corrupt dasm ?   A few times I got a message saying dasm could not open when trying to compile .

 

That is one problem.

 

The other problem is that my new version , now just still has 2 enemies, but I added enemy fire ( M1) and collision detection with player.

 

but now nothing seems to work   :  collision detection , firing of either missile.  I think my programming logic is sound...

 

 

can someone please compile  the shooter7.asm and see if the player fire works and perhaps my dasm is broken

 

Also , can someone help me figure out why the shooterefire.asm with  shooterefire.bin  player fire and enemy fire are not registering?

 

thanks.    



#15 easmith OFFLINE  

easmith

    Chopper Commander

  • Topic Starter
  • 148 posts
  • Location:Alexandria, VA

Posted Tue Jan 23, 2018 10:17 PM

I  figured out the player fire bug in the old file , I had changed a bcs to bcc by accident .  I think I lost version control.

 

still can't figure out the enemy fire or collision detection bug in new version  shooterefire

 

the "shooter " is old version where collision works

 

 

 

Attached Files


Edited by easmith, Tue Jan 23, 2018 10:20 PM.


#16 easmith OFFLINE  

easmith

    Chopper Commander

  • Topic Starter
  • 148 posts
  • Location:Alexandria, VA

Posted Tue Jan 23, 2018 10:59 PM

getting warmer...

 

had my enemy missile initialized above screen should have been at bottom .  

Attached Files


Edited by easmith, Tue Jan 23, 2018 11:44 PM.


#17 easmith OFFLINE  

easmith

    Chopper Commander

  • Topic Starter
  • 148 posts
  • Location:Alexandria, VA

Posted Wed Jan 24, 2018 10:14 PM

 

I think what happened is that the position alien routine has been broken, but since you only used it for the initial position in version 3 it went unnoticed. Now that you're using it every frame it's noticeable. The problem is that you can't write to any of the HMxx registers immediately after you strobe HMOVE. You must wait at least 24 cycles or it will interfere with the HMOVE process. (See stella programmer guide pg9)

 

This may also explain the problems you're having with detecting which copy was hit. That's not going to work so well if the objects are not positioned where you think they are.

 

You're routine is also a few cycles off for other reasons. Why don't you just use the code from the collect tutorial? No need to make your own unless you're trying to do something advanced like positioning objects while also drawing a playfield.

    sta WSYNC
   sta HMOVE
    lda #0
    sta HMP1 ;TOO SOON!!!

 

 

 

 

ok. I used the hor positioning code from the tutorial.  I  froze the motion of the enemy to check positioning.  looks good.  However , collisions don't work anymore still.

 

I wonder if I a using too many cycles on a scanline for the main play area??  See code in blue .   I am not sure if I can accurately count cycles ( I got around 66 with branches??)

 

Note how when you move player off the screen to the left there is a weird jitter.  Also there is part of a brown line on the lower right and the top of the ground .

 

Something has to be off but I just cannot find it .

Attached Files


Edited by easmith, Wed Jan 24, 2018 10:33 PM.


#18 ZackAttack OFFLINE  

ZackAttack

    Dragonstomper

  • 745 posts
  • Location:Orlando, FL US

Posted Thu Jan 25, 2018 12:25 AM

The weird jitter you see is because you're writing to GRP1 at that time. You use too many cycles at the beginning of the scan line. Move some of that logic into vblank. If you want to hide the alien you should put its Y position outside the visible screen or set it's graphics pointer to a block of 0's



#19 iesposta OFFLINE  

iesposta

    River Patroller

  • 3,818 posts
  • Retro-gaming w/my VCS
  • Location:Pennsylvania

Posted Thu Jan 25, 2018 7:21 AM

I could find no information on this used back in the day technique. 

I made a routine in batari Basic, gave it to Random Terrain to post on his site.

He fixed a bug and found some of the code wasn't needed at all. 

 

It it does what you are doing in assembly.

Checks for collision, then checks where: left, middle, or right of triple, or left, right of double.

Then it changes NUSIZ and repositions if necessary. 

 

It it would be interesting to compare the compiled assembly to the coded assembly. 

I would guess the compiled basic would be larger, more wasteful, and possibly redundant. 

 

I'm just glad to see others figuring this out. 



#20 easmith OFFLINE  

easmith

    Chopper Commander

  • Topic Starter
  • 148 posts
  • Location:Alexandria, VA

Posted Thu Jan 25, 2018 7:37 PM

The weird jitter you see is because you're writing to GRP1 at that time. You use too many cycles at the beginning of the scan line. Move some of that logic into vblank. If you want to hide the alien you should put its Y position outside the visible screen or set it's graphics pointer to a block of 0's

 

so I have altered the hor. positioning routines to match the Collect tutorial.

I have moved the logic for deciding whether to show enemy if hit twice to overscan.

this removed the enemy jitter.

I have fixed the weird jitter of player0 by restricting the movement range between x=0 and x= 159.

 

But the collisions ( M0-P1 and M1 - P0 ) are still not registering even though the logic is the same as a previous version where the collisions were detected and the appropriate enemy copy removed.  Once I added in the Missile 1 dynamic the collisions stopped registering . 

 

I am truly stumped at this point.  I cannot figure out what is wrong.   Case of  beer  to anyone that can figure out my bug  !   :)

Attached Files


Edited by easmith, Thu Jan 25, 2018 7:37 PM.


#21 ZackAttack OFFLINE  

ZackAttack

    Dragonstomper

  • 745 posts
  • Location:Orlando, FL US

Posted Thu Jan 25, 2018 9:58 PM

One problem is that you're initializing the SP to a random value. (Forgot # to make ldx immediate)

      ldx $ff   ; stack pointer
      txs  ; assign stack $ff <- SP is no whatever random value $ff was initialized to. If it's < $80 the game will probably crash


#22 ZackAttack OFFLINE  

ZackAttack

    Dragonstomper

  • 745 posts
  • Location:Orlando, FL US

Posted Fri Jan 26, 2018 12:25 AM

I'd also like to suggest that you clean up your code some. The easier it is to read, the easier it is to debug. Suffix labels with : when you declare them. Keep indentation and white space consistent. Use SUBROUTINE and local labels like .1, .2, ... for procedural branch targets. Use empty lines to separate different pieces of the program. This might seem like a waste of effort, but you spend so much more time reading code than writing it that it pays huge dividends to put in some effort for readability.

 

Here's an example:

PositionObjects:  SUBROUTINE  
  sta HMCLR
  ldx  #3
.1
  lda PlayerX,x
  jsr PositionObject
  dex
  bpl .1
  sta WSYNC
  sta HMOVE

PollForVBlankEnd: SUBROUTINE
  sta WSYNC 
  lda INTIM       
  bne PollForVBlankEnd 
  sta VBLANK    


#23 easmith OFFLINE  

easmith

    Chopper Commander

  • Topic Starter
  • 148 posts
  • Location:Alexandria, VA

Posted Fri Jan 26, 2018 10:29 AM

Ok, I tried to clean the code up a bit, and fix the stack issue. Sorry about that .  I am not a programmer by trade so my etiquette is probably terrible.

 

At any rate I got the collisions to work again!!!   I did not mention this , but in the earlier version I had the logic for changing players and missiles x and y , and for collisions,  in Overscan .

 

In the newer version I had moved the collision detection to VBlank and left the other logic in Overscan .   So changing the order somehow threw everything off.

 

On to next step.  

 

Thanks Zach

Attached Files



#24 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,771 posts
  • Location:The land of Gorch

Posted Sun Jan 28, 2018 2:19 AM

An alternate solution to the original question is to always draw 3 copies...but draw blank bitmaps in place of the one(s) hit.  This has the added benefit of each sprite in the group allowed to be separate bitmaps, anyway (for a fancy "I am shot" animation or whatever).  Space Invaders does this pretty effectively...NUSIZ registers are only altered as bordering columns are removed completely.






0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users