easmith Posted January 20, 2018 Share Posted January 20, 2018 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. shooter4.asm shooter.bin Quote Link to comment Share on other sites More sharing options...
ZackAttack Posted January 20, 2018 Share Posted January 20, 2018 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 1 Quote Link to comment Share on other sites More sharing options...
easmith Posted January 20, 2018 Author Share Posted January 20, 2018 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? Quote Link to comment Share on other sites More sharing options...
ZackAttack Posted January 21, 2018 Share Posted January 21, 2018 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. Quote Link to comment Share on other sites More sharing options...
easmith Posted January 21, 2018 Author Share Posted January 21, 2018 alright, this one should keep me busy for a while..... thanks again Quote Link to comment Share on other sites More sharing options...
vidak Posted January 21, 2018 Share Posted January 21, 2018 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. Quote Link to comment Share on other sites More sharing options...
easmith Posted January 21, 2018 Author Share Posted January 21, 2018 (edited) 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 January 21, 2018 by easmith Quote Link to comment Share on other sites More sharing options...
ZackAttack Posted January 22, 2018 Share Posted January 22, 2018 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 Quote Link to comment Share on other sites More sharing options...
easmith Posted January 22, 2018 Author Share Posted January 22, 2018 (edited) 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 shooter4.asm shooter4.bin shooter7.asm shooter7.bin Edited January 22, 2018 by easmith Quote Link to comment Share on other sites More sharing options...
ZackAttack Posted January 22, 2018 Share Posted January 22, 2018 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!!! Quote Link to comment Share on other sites More sharing options...
easmith Posted January 22, 2018 Author Share Posted January 22, 2018 (edited) 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 ) shooter8.bin Edited January 23, 2018 by easmith Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted January 22, 2018 Share Posted January 22, 2018 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. 1 Quote Link to comment Share on other sites More sharing options...
easmith Posted January 22, 2018 Author Share Posted January 22, 2018 cool thanks. I am not using missile 1 right now I will give the star effect a try . Quote Link to comment Share on other sites More sharing options...
easmith Posted January 24, 2018 Author Share Posted January 24, 2018 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. Quote Link to comment Share on other sites More sharing options...
easmith Posted January 24, 2018 Author Share Posted January 24, 2018 (edited) 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 shooterefire.asm shooterefire.bin Shooter.bin Edited January 24, 2018 by easmith Quote Link to comment Share on other sites More sharing options...
easmith Posted January 24, 2018 Author Share Posted January 24, 2018 (edited) getting warmer... had my enemy missile initialized above screen should have been at bottom . shooterefire.asm shooterefire.bin Edited January 24, 2018 by easmith Quote Link to comment Share on other sites More sharing options...
easmith Posted January 25, 2018 Author Share Posted January 25, 2018 (edited) 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 . shooterefire3.asm shooterefire.bin Edited January 25, 2018 by easmith Quote Link to comment Share on other sites More sharing options...
ZackAttack Posted January 25, 2018 Share Posted January 25, 2018 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 Quote Link to comment Share on other sites More sharing options...
iesposta Posted January 25, 2018 Share Posted January 25, 2018 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. Quote Link to comment Share on other sites More sharing options...
easmith Posted January 26, 2018 Author Share Posted January 26, 2018 (edited) 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 ! shooterefire3.asm shooterefire.bin Edited January 26, 2018 by easmith Quote Link to comment Share on other sites More sharing options...
ZackAttack Posted January 26, 2018 Share Posted January 26, 2018 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 Quote Link to comment Share on other sites More sharing options...
ZackAttack Posted January 26, 2018 Share Posted January 26, 2018 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 Quote Link to comment Share on other sites More sharing options...
easmith Posted January 26, 2018 Author Share Posted January 26, 2018 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 shooterefire4.asm shooterefire.bin Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted January 28, 2018 Share Posted January 28, 2018 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. 2 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.