jbs30000 #1 Posted December 5, 2010 This post will be kind of long, but I need to give plenty of information in order to ask for help. In my Super Mario game adaptation I recently created a routine to determine if a collision occurs. There's three outcomes. 1, no collision occurs - 2, Mario lands on top of an enemy killing it - 3, an enemy collides with Mario killing him. I have a couple of problems. Sometimes I'd land on both enemies, kill them, walk a few steps to the right, and die for no apparent reason. So I REMed out the code to check for a crash into enemy 1. If I land on and kill enemy 2, enemy 1 dies as well. This shouldn't happen. There are two enemies, one is player 0 and the other is player 1. Since players 0 and 1 make up Mario I have variables to hold the various positions: Mario dim X_Pos=k.l dim Y_Pos=m Enemy 1 dim Enemy1X=q dim Enemy1Y=r Enemy 2 dim Enemy2X=s dim Enemy2Y=t I also have two variables to determine if enemies 1 and 2 exist or not: rem See if Enemy number 1 is on screen or not - (E)nemy (S)creen def ES1=p{1} rem See if Enemy number 2 is on screen or not - (E)nemy (S)creen def ES2=p{2} If the bit is set, the enemy is on the screen. If it is not set, no enemy. Finally, some DEFs in my program: dim Crash_Value=y def No_Crash=0 def Land_on_Enemy=1 def Killed_By_Enemy=2 With that, here is the code to determine a crash: function Crash_Detection rem temp1 - 1=Enemy1, 2=Enemy2 if temp1=2 then goto Crash_Detect_Enemy2 Crash_Detect_Enemy1 if !ES1 then return No_Crash rem If Mario is in front of or behind an enemy then no contact has been made. temp1=Enemy1X-8: temp2=Enemy1X+8 if k<=temp1 || k>temp2 then return No_Crash rem If Mario is 1 or more pixels above an enemy then no contact has been made temp1=Enemy1Y-9 if Y_Pos<temp1 then return No_Crash rem All remaining options are that a collision took place. The following code will determine what type. rem If Mario is jumping or he's not jumping or falling then it's an instant kill. if Jumping then return Killed_By_Enemy if !Falling then return Killed_By_Enemy rem If Mario is falling, then if he's right on top of an enemy, or 4 pixels into an enemy, then he's landing on them and kills them. temp1=Enemy1Y-4 if Y_Pos<=temp1 then return Land_on_Enemy return Killed_By_Enemy Crash_Detect_Enemy2 if !ES2 then return No_Crash rem If Mario is in front of or behind an enemy then no contact has been made. temp1=Enemy2X-8: temp2=Enemy2X+8 if k<temp1 || k>temp2 then return No_Crash rem If Mario is 1 or more pixels above an enemy then no contact has been made temp1=Enemy2Y-9 if Y_Pos<=temp1 then return No_Crash rem All remaining options are that a collision took place. The following code will determine what type. rem If Mario is jumping or he's not jumping or falling then it's an instant kill. if Jumping then return Killed_By_Enemy if !Falling then return Killed_By_Enemy rem If Mario is falling, then if he's right on top of an enemy, or 4 pixels into an enemy, then he's landing on them and kills them. temp1=Enemy2Y-4 if Y_Pos<=temp1 then return Land_on_Enemy return Killed_By_Enemy end Here is the code to see if a crash has happened. rem Check to see if Mario has collided with an Enemy if !ES1 then goto CV2 Crash_Value=Crash_Detection(1) if Crash_Value=Killed_By_Enemy then goto End_Game if Crash_Value=Land_on_Enemy then ES1=0: Enemy1X=0: Enemy1Y=0 CV2 if !ES2 then return otherbank Crash_Value=Crash_Detection(2) if Crash_Value=Killed_By_Enemy then goto End_Game if Crash_Value=Land_on_Enemy then ES2=0: Enemy2X=0: Enemy2Y=0 return otherbank Does anybody see any obvious errors that I am overlooking? Quote Share this post Link to post Share on other sites
+Random Terrain #2 Posted December 5, 2010 (edited) I barely understand my own code, so I probably can't help. I do know that my program stopped following common sense and I think it probably broke the laws of physics and might have opened up a wormhole. Sometimes code that should work doesn't. At random times, bB will start requiring that only one thing can be on a line or it won't compile, or it will decide to ignore REM and run any code after it, or it will require that then goto be used within the same bank when smartbranching is on. I suspect that too many DEFs causes the problem, but I don't have proof. Programming is hard enough when things are working correctly, but when the fabric of reality starts ripping apart, it's tempting to give up and do something easier, like build a spaceship and fly to Mars. Edited December 5, 2010 by Random Terrain Quote Share this post Link to post Share on other sites
+RevEng #3 Posted December 5, 2010 Nothing jumps out at me. Can you open up the resulting .asm file and post the assembly code that resulted from line "if Crash_Value=Land_on_Enemy then ES1=0: Enemy1X=0: Enemy1Y=0"? Quote Share this post Link to post Share on other sites
jbs30000 #4 Posted December 5, 2010 (edited) Nothing jumps out at me. Can you open up the resulting .asm file and post the assembly code that resulted from line "if Crash_Value=Land_on_Enemy then ES1=0: Enemy1X=0: Enemy1Y=0"? .L0553 ; if Crash_Value = Land_on_Enemy then ES1 = 0 : Enemy1X = 0 : Enemy1Y = 0 a5 ee LDA Crash_Value c9 01 CMP #1 d0 0c BNE .skipL0553 .condpart142 a5 e5 LDA p 29 fd AND #253 85 e5 STA p a9 00 LDA #0 85 e6 STA Enemy1X 85 e7 STA Enemy1Y And, for comparison's sake .L0557 ; if Crash_Value = Land_on_Enemy then ES2 = 0 : Enemy2X = 0 : Enemy2Y = 0 a5 ee LDA Crash_Value c9 01 CMP #1 d0 0c BNE .skipL0557 .condpart145 a5 e5 LDA p 29 fb AND #251 85 e5 STA p a9 00 LDA #0 85 e8 STA Enemy2X 85 e9 STA Enemy2Y Everything looks OK. Oh well. I'll figure it out eventually. Edit: Actually, looking at some other code, I have a question: .L0550 ; if !ES1 then goto CV2 a5 e5 LDA p 29 02 AND #2 d0 03 BNE .skipL0550 .condpart140 4c bd 98 jmp .CV2 .skipL0550 .L0551 ; Crash_Value = Crash_Detection ( 1 ) and .L0554 ; if !ES2 then return otherbank a5 e5 LDA p 29 04 AND #4 d0 03 BNE .skipL0554 .condpart143 4c dd ff JMP BS_return .skipL0554 .L0555 ; Crash_Value = Crash_Detection ( 2 ) So in the first one, if ES1 is 0, skip to the label CV2. But the asm seems to be doing the opposite. OK, ES1 is bit 1 or a value of 2, so this part seems right. LDA p AND #2 However, this next part doesn't seem right BNE .skipL0550 .condpart140 jmp .CV2 .skipL0550 Now it's checking to see if bit 1 is off, or 0. ANDing p with 2 should return 0, the values aren't equal, so shouldn't it be BNE .CV2 ? Same thing with checking on ES2. Edited December 5, 2010 by jbs30000 Quote Share this post Link to post Share on other sites
+RevEng #5 Posted December 6, 2010 The assembly looks right. p{0} would be the rightmost bit, and p{1} (ES1) is the next one over, so a mask of #2 is appropriate. In a nutshell, the assembly code... 1. loads the byte with the ES1 bit into the A register. 2. keeps only the bit for ES1. 3. If the result is non-zero then a branch is taken to skip over the "jmp .JV2" code. Functionally, that's the same as your basic code. Want to post or PM the code? Quote Share this post Link to post Share on other sites
jbs30000 #6 Posted December 6, 2010 The whole program? No. There's a lot of code, it's kind of sloppy, and some of the variables are horribly named (like ES1 and ES2). I'm re-writing the program so that the code is a lot neater and over-all it's easier to read. If I'm still having a problem then I'll post it for others to look at. Quote Share this post Link to post Share on other sites