Jump to content
IGNORED

Collision Check with #mobshadow? IntyBasic


Recommended Posts

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?

Link to comment
Share on other sites

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 by intvnut
Link to comment
Share on other sites

@intvnut

 

#mobshadow(index+$0018) not #mobshadow(index+18 dec) icon_surprised.gif

YUP that was it thanks! icon_thumbsup.gif icon_thumbsup.gif icon_thumbsup.gif

 

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
  
Link to comment
Share on other sites

@intvnut

 

#mobshadow(index+$0018) not #mobshadow(index+18 dec) icon_surprised.gif

 

YUP that was it thanks! icon_thumbsup.gif icon_thumbsup.gif icon_thumbsup.gif

 

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.

 

 

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 icon_tears.gif

 

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 by DZ-Jay
  • Like 1
Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...