dontblowincartridge Posted December 23, 2018 Share Posted December 23, 2018 I want to use #mobshadow to check collision. Is it possible do to even do that? I want to be able to use #mobshadow(index+18) to check for a collision to avoid doing a series of IF statements to check for every possible collision between mobs 1,2..,7 How exactly does COL0, COL1,... COL7 work? How could I do the same check with #mobshadow(index+18)? I am doing something like: REM NOTE: This is snippets from my project (not complete code) REM I want to emulate the COL0, COL1,... COL7 functionality but REM dynamically using #mobshadow REM Array to hold the values for hit sprites from constants DIM #collision_index(7) #collision_index(0) = HIT_SPRITE1 #collision_index(1) = HIT_SPRITE2 #collision_index(2) = HIT_SPRITE3 #collision_index(3) = HIT_SPRITE4 #collision_index(4) = HIT_SPRITE5 #collision_index(5) = HIT_SPRITE6 #collision_index(6) = HIT_SPRITE7 CONST HIT_SPRITE1_THROUGH_SPRITE7 = HIT_SPRITE1 + HIT_SPRITE2 + HIT_SPRITE3 + HIT_SPRITE4 + HIT_SPRITE5 + HIT_SPRITE6 + HIT_SPRITE7 REM index starts at 1 then goes to 7 in a loop but for these snippets REM consider it at 1 index = 1 #collision_check = HIT_SPRITE1_THROUGH_SPRITE7 - #collision_index(index-1) REM basically, this should be the same has REM #collision_check = HIT_SPRITE2 + HIT_SPRITE3 + HIT_SPRITE4 + HIT_SPRITE5 + HIT_SPRITE6 + HIT_SPRITE7 WAIT REM this should be the same has REM IF COL1 and HIT_SPRITE2 + HIT_SPRITE3 + HIT_SPRITE4 + HIT_SPRITE5 + HIT_SPRITE6 + HIT_SPRITE7 THEN IF #mobshadow(index+18) and #collision_check THEN S_F_B_XY_LOOP: REM get new position REM NOTE: box_pos_x, and box_pos_y are previously set, VISIBLE + HIT REM so collision for this loop happens but the collision register REM does not update after setspritex setspritey call. And this becomes REM a infinite loop... Why does the mob register not update? box_pos_x(index-1) = RANDOM(BOX_SPAWN_RANGE_X)+SPAWN_RANGE_ADJ_X box_pos_y(index-1) = RANDOM(BOX_SPAWN_RANGE_Y)+SPAWN_RANGE_ADJ_Y REM change position setspritex(index,box_pos_x(index-1)) setspritey(index,box_pos_y(index-1)) REM #mobshadow(index+18) stic register collision WAIT IF #mobshadow(index+18) and #collision_check THEN GOTO S_F_B_XY_LOOP END IF What is a effective way to collision checks like using #mobshadow? Am I doing something wrong? Quote Link to comment Share on other sites More sharing options...
intvnut Posted December 23, 2018 Share Posted December 23, 2018 (edited) If I understand #mobshadow correctly, indices $18 through $1F end up indexing to the internal variables _col0 through _col7 (at least with the IntyBASIC 1.2.9 epilogue code). Those variables contain the previous frame's MOB collision status. The hardware registers get cleared every frame, and so the status is only valid for a single frame. (And, if I'm not mistaken, the COL0 through COL7 IntyBASIC variables just map to _col0 through _col7). The hardware collision variables contain a 10-bit value. Bit #x of COLy will hold a 1 if MOB x and MOB y collided. Bit 8 says whether the MOB collided with the background and bit 9 says whether the MOB collided with the border. Collision here means that the two MOBs (or MOB and background) both overlapped by at least one "on" pixel. Or in the case with MOB and border, that the MOB had an "on" pixel in the border-collision area. And, a MOB never collides with itself: Bit #x of COLx will always be 0. If you want to quickly check whether MOB x and MOB y collided, then something like this should work: . IF #mobshadow(mobx + $18) and bitmask(moby) THEN .... ' they collided. . You just need to include the following bitmask table to quickly generate the necessary bit mask: . bitmask: DATA 1, 2, 4, 8, 16, 32, 64, 128, 256 DATA 512, 1024, 2048, 4096, 8192, 16384, 32768 . This should allow you to dynamically ask the question "Did X collide with Y" with the two values X and Y determined at run time. Now, if you want to answer the question "Did X collide with any of {...fixed set known at compile time...}", then you should be able to construct a constant at compile time with that fixed set, and say: . CONST BADGUY_MOBS = ' some bitmap here. ... IF #mobshadow(index + $18) and BADGUY_MOBS THEN .... ' do something here. . Now one last thing to note: The offset is $18, not 18. $18 is a hex value, and is equivalent to 24 decimal. It could be you were already on the right track to accomplish what you wanted. I noticed you're using the decimal 18 rather than the hexadecimal $18, and that won't work. Edited December 23, 2018 by intvnut Quote Link to comment Share on other sites More sharing options...
dontblowincartridge Posted December 23, 2018 Author Share Posted December 23, 2018 @intvnut #mobshadow(index+$0018) not #mobshadow(index+18 dec) YUP that was it thanks! For some reason when I read the manual "#MOBSHADOW(x) Access elements of MOB buffer (the place where is saved the SPRITE data) The indexes 0-23 replicate exactly the locations 0-23 of STIC." I thought the index for mobshadow(index) was in dec.Like an array. I didn't realize it was in hex.With the index of 0-23 this of course means that #mobshadow() can't reach everything in the STIC registers right? Because the documentation says that there are $0000 - $007F.Can I pick your brain further? Considering I have never used a array in IntyBasic over $000A are all arrays index in hex? Should be clearer in the manual imo. No big deal though. How do you use poke? I am interpreting it like a pointer in C/C++ but not sure how to deference and reference. And when it comes checking collision with #mobshadow I learned that the collision registers only update with the use of SPRITE Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted December 24, 2018 Share Posted December 24, 2018 (edited) @intvnut #mobshadow(index+$0018) not #mobshadow(index+18 dec) YUP that was it thanks! For some reason when I read the manual "#MOBSHADOW(x) Access elements of MOB buffer (the place where is saved the SPRITE data) The indexes 0-23 replicate exactly the locations 0-23 of STIC." I thought the index for mobshadow(index) was in dec. Like an array. I didn't realize it was in hex. With the index of 0-23 this of course means that #mobshadow() can't reach everything in the STIC registers right? Because the documentation says that there are $0000 - $007F. Can I pick your brain further? Considering I have never used a array in IntyBasic over $000A are all arrays index in hex? Should be clearer in the manual imo. No big deal though. Hexadecimal, Decimal, and Binary are number systems, and in this context they are merely representations of a particular value. IntyBASIC lets you use either Hexadecimal or Decimal for any expression representing a numeric value. Therefore, the answer to your specific question is: all array indices are numeric. Whether you represent this number in Hex or in Decimal, is up to you. Sometimes Hex values look cleaner because they are more compact, and directly relate to the way the machine organizes its memory map and devices. The issue you had accessing the mobshadow wasn't that you used Decimal instead of Hex (well, there's a subtle distinction, so please follow me here). The problem was that you used the wrong value. Let me explain. The Hex value $0018 is equal to the Decimal value 24. So you could either use $0018 or 24 for that value and it would have worked exactly the same (think of it like saying the same word in two different languages: you are saying the exact same thing, even though it sounds different). However, by forgetting the "$" symbol, you told IntyBASIC that the value was in Decimal, so it took "18" to mean the Decimal value 18. Obviously this is not the same as the Decimal value 24, so your computation of "(index + 18)" was off. Does this make sense? How do you use poke? I am interpreting it like a pointer in C/C++ but not sure how to deference and reference. IntyBASIC treats the first argument to POKE as either an address or a pointer to an address. That is, if you give it a direct address like: ' These two do the same exact thing ($200 Hex = 512 Dec) POKE $200, 0 POKE 512, 0 It will put the second argument value into that address. If you use a variable instead, it will treat the variable like a C pointer, expecting its value to be an actual memory address, and store the value in there. For example: ' This does the same thing as above #addrs = $200 POKE #addrs, 0 If you instead want to poke to the actual variable itself, you can use the "VarPtr" directive to get the address to the variable. ' This changes the value in #addrs to zero POKE VarPtr #addrs, 0 ' It is the same as #addrs = 0 PEEK works the same way but in reverse: it returns the value at the address given; or if a variable is given, it returns the value pointed to by the variable, assuming the value of the variable is a memory address. And when it comes checking collision with #mobshadow I learned that the collision registers only update with the use of SPRITE IF #mobshadow(index+18) and #collision_check THEN S_F_B_XY_LOOP: box_pos_x(index-1) = RANDOM(BOX_SPAWN_RANGE_X)+SPAWN_RANGE_ADJ_X box_pos_y(index-1) = RANDOM(BOX_SPAWN_RANGE_Y)+SPAWN_RANGE_ADJ_Y REM change position REM setspritex(index,box_pos_x(index-1)) REM setspritey(index,box_pos_y(index-1)) WAIT SPRITE index, HIT + VISIBLE + box_pos_x(index-1), box_pos_y(index-1), SPR00 + SPR_PURPLE WAIT IF #mobshadow(index+18) and #collision_check THEN GOTO S_F_B_XY_LOOP END IF Actually, collision registers are updated when the HIT flag of the sprite is set (which you are doing in the SPRITE statement), and directly after the vertical blanking interrupt, i.e., at the beginning of a frame, after a WAIT statement. It perhaps means that you didn't have the HIT flag set on your sprite, so when you issued your SPRITE statement with the HIT flag, the collision registers were updated on the next frame. You only need to set the HIT flag once to enable collisions and it sticks until you clear it in another SPRITE statement. And sometimes I notice it misses or does not work right because of the use of WAIT or the register getting cleared before frame. I seem to be able to get this check to work 100% of the time but only by adding in like 3 waits before IF #mobshadow(index+18) and #collision_check THEN but this causes considerable delay and lag. The MOB collision registers are updated right after a WAIT, not before. IntyBASIC's runtime engine traps the vertical blanking interrupt and first reads and updates the STIC (the video chip) registers, along with a few other housekeeping tasks, before returning control to your program. Here is a simple description I wrote some time ago on how "WAIT" works. http://atariage.com/forums/topic/284783-get-papi-collision-tilesprite-in-8-directions-problem/?p=4152169 Does this mean that this would work better with ON FRAME? I am not sure how to use ON FRAME. How do you use ON FRAME without crashing your program? I think I may have to move on from doing collision checks using mobshawdow and do series of hardcoded if statements with COL1, COL2,..COL7 for efficiency sake at the cost of elegant code It may work better with ON FRAME. This directive basically waits on its own for the vertical blanking interrupt, which indicates the beginning of a new frame, and calls your routine after performing all its internal housekeeping tasks. You use it like this: ' Calls subroutine MyFrameRoutine ' at the beginning of every frame. ON FRAME GOSUB MyFrameRoutine Your frame subroutine will get called at the beginning of every frame. In this subroutine you could check for collisions or do any other cyclical tasks you need to perform on every frame. It will get called at 60Hz (on NTSC; 50Hz on PAL). At the risk of sounding glib, if it's crashing, you are doing something wrong. Make sure that if you call it with "GOSUB" that there is not a "GOTO" somewhere in the subroutine which is causing it to break away without returning to its caller. In general, try to avoid GOTO unless you know precisely what you are doing and are able to follow the ensuing spaghetti flow. You should still be able to write your collision detection elegantly, many people do. You could also use bit masks to test the collisions of all sprites, and even do it in a loop to re-use code. Just post your code or questions and someone will surely help. -dZ. Edited December 24, 2018 by DZ-Jay 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.