Jump to content
IGNORED

Software collision detection with background


jlew715

Recommended Posts

Hey all,

 

Working on an IntyBasic game and I'd like to implement software-based collision detection rather than relying on the built-in Intellivision collision registers (mainly so I don't have to wait for the player-sprite to already be ~1px inside the wall before the collision is reported).

 

This is simple enough for MOB-on-MOB collisions, but I'm not sure how to implement this for collisions with background elements like walls. I'm envisioning the flow will be something like:

  1. Draw player sprite
  2. Determine target coordinates for next player move (based on Controller input or whatever).
  3. Get info about what type of card is currently shown on the target coordinates.
  4. If it's open, set player coordinates = target coordinates.
  5. If it's a wall, set player coordinates = last known good coordinates.
  6. GOTO 1.

Where I'm stuck is step 3. I'm guessing there is a way to convert the target coordinates into a "card number" (BACKTAB?), then load information about what is on that card (is it a wall? is it blank?). But I'm not sure how to A). translate the X/Y coords into a card, and B). how to tell what is displayed on a particular card (is it a wall?).

 

Additionally, I'm guessing that the "origin" for sprites is the upper-left corner. so drawing an 8x8 sprite at coordinates 10,10 would occupy the area from 10,10 to 18,18. Please correct me if I'm wrong.

 

Thanks!

 

 

Link to comment
Share on other sites

Hey all,

 

Working on an IntyBasic game and I'd like to implement software-based collision detection rather than relying on the built-in Intellivision collision registers (mainly so I don't have to wait for the player-sprite to already be ~1px inside the wall before the collision is reported).

 

This is simple enough for MOB-on-MOB collisions, but I'm not sure how to implement this for collisions with background elements like walls. I'm envisioning the flow will be something like:

  1. Draw player sprite
  2. Determine target coordinates for next player move (based on Controller input or whatever).
  3. Get info about what type of card is currently shown on the target coordinates.
  4. If it's open, set player coordinates = target coordinates.
  5. If it's a wall, set player coordinates = last known good coordinates.
  6. GOTO 1.

Where I'm stuck is step 3. I'm guessing there is a way to convert the target coordinates into a "card number" (BACKTAB?), then load information about what is on that card (is it a wall? is it blank?). But I'm not sure how to A). translate the X/Y coords into a card, and B). how to tell what is displayed on a particular card (is it a wall?).

 

Additionally, I'm guessing that the "origin" for sprites is the upper-left corner. so drawing an 8x8 sprite at coordinates 10,10 would occupy the area from 10,10 to 18,18. Please correct me if I'm wrong.

 

Thanks!

 

 

 

For MOB-to-Background collisions, you could do this:

  • Convert MOB screen coordinates into BACKTAB address: address = $200 + (((x + 4) / 8 ) + (((y + 4) / 8 ) * 20))
  • This will give you the card in BACKTAB over which the center of the sprite resides.
  • If your collision is against full cards, then just read the type of card by getting the card value from the BACKTAB word using a mask: card = (PEEK(address) AND $7F8) / 8
  • This will give you the card number, which you can either look up on a table or do something else with it.
  • If your cards have multiple facets (i.e., a card may contain multiple elements drawn inside), then you can get the Modulo 4 of the X and Y coordinates to determine an offset within the card as well.

On your last point, the origin of the sprites is indeed the upper-left corner, so you may want to offset your coordinates by 4 (or 3) before translation.

 

-dZ.

  • Like 1
Link to comment
Share on other sites

One other thing you can do: BACKTAB cards are 16-bit long, but the STIC only uses the lower 14 bits. That means that the 2 MSB are not touched and free for your own use. Two bits gives you capacity to store a value from 0 to 3, so if you have at most four kinds of walls, you could "mark" them by adding a value in those bits when you draw the screen. Then, it's a matter of masking them and shifting them in order to use them as an index into a table.

 

Ask for further details if anything here is not clear. :)

 

-dZ.

Link to comment
Share on other sites

I like the idea of encoding the card type (wall 1, wall 2, etc.) into the 2 unused bits of the each card. How do I got about setting these when Im PRINTing my walls earlier?

Say Im printing a wall along the top of the screen:

 

FOR I=0 TO 19

PRINT AT (SCREENPOS(I,0)), BG00

NEXT I

 

Say I wanted to set the MSB of those 20 cards to identify that they are walls - how can I do that? Something with POKE?

Edited by jlew715
Link to comment
Share on other sites

I like the idea of encoding the card type (wall 1, wall 2, etc.) into the 2 unused bits of the each card. How do I got about setting these when Im PRINTing my walls earlier?

Say Im printing a wall along the top of the screen:

 

FOR I=0 TO 19

PRINT AT (SCREENPOS(I,0)), BG00

NEXT I

 

Say I wanted to set the MSB of those 20 cards to identify that they are walls - how can I do that? Something with POKE?

Use the addition operator, for example BG00 + $8000 or BG00 + $4000.

Link to comment
Share on other sites

Use the addition operator, for example BG00 + $8000 or BG00 + $4000.

 

Or, to make it nicer to look at and understand in your program, you can just take the index value (0 to 3) and multiply it by 2^14 or $4000. Like this:

#var = BG00 + (0 * $4000)  ' Card 0
#var = BG00 + (1 * $4000)  ' Card 1
#var = BG00 + (2 * $4000)  ' Card 2
#var = BG00 + (3 * $4000)  ' Card 3

Essentially, we add the magic values for the bits like nanochess said, but instead of treating the bits as individual flags, we treat them as a field that allows us to store a 2-bit value, or a value from 0 to 3. We then take that 2-bit value and "shift" it to the left into position by multiplying it by 2^14.

 

To read it back, you first mask it, and compare to similar constants, for instance:

#card = #var AND $C000  ' Mask the upper 2 bits

IF (#card = (2 * $4000)) THEN
  ' Card is #2
END IF 

Or

IF ((#var AND $C000) = (2 * $4000) THEN)
  ' Same thing
END IF 

If you plan on using it as an index to a table, you'll have to shift the bits back, which you can do via division, but it may get expensive. Let us know how you plan on using it, and we can help.

 

All that is if you need to keep track of a value within 0 and 3. If all you have is a single flag telling you whether it's a wall or not, then adding a single bit like nanochess suggested would be more straightforward.

 

-dZ.

  • 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...