Jump to content
IGNORED

Placeholder tutorial: collisions!


ggn

Recommended Posts

I got asked about this via private message and while I think it's a great idea, this is mostly raptor specific and unfortunately I have almost zero knowledge about raptor itself! So I'll just drop some hints here. Your mission, should you choose to accept it, is to take these hints, read the raptor docs, experiment, make some example projects and report back with your findings. Any relevant knowledge to this topic in the replies will be added to this first post here.

 

Generally about collisions: two of the most frequent ways to check for collisions between two objects are: 1) check each pixel of one object with each pixel of the other and see if they match in coordinates, 2) Check the boundaries of an object with the boundaries of the other object, and see if they intersect.

 

The first one gives more accurate results but it takes a lot more time to execute. So usually collisions are handed using method 2, or so called bounding boxes. In a nutshell we wrap the two objects we want to check with boxes - then it's much easier to check if the boxes intersect - just by checking the coordinates of the edges of the boxes will do. This is often a very good compromise, much faster, and allows you to tune the gameplay better.

 

Looking at the shootbang project we can see a reference to rhit command. Reading the quickref doc we find that:

 

rhit (<source first object>, <source last object>, <target first object>, <target last object>) will return 1 (hit has occurred) if anything within the specified range has collided. This is only a general indication of a collision and further interrogation via the 'was_hit' variable will let you know which object has actually collided with any of the source objects. The values of damage variables of the source objects is deducted from the target objects. raptor can be set to automatically kill an object when its hitpoint variable reaches -1 (dead) by setting the object variable 'remhit' to 'cd_remove' (1) The collision check will only work on objects that have their 'colchk' variable set to 'can_hit' (1), objects that are set to 'cant_hit' (-1) will be skipped.

So this tells us that when we call rhit it will check one range of objects with another range of objects for collision. So if we have objects 5-10 defined as bullets and 20-40 defined as enemies, "result=rhit(5,10,20,40)" will check if the bullets hit any enemy objects. However, result will only tell us if at least one collision happened. After we get a collision we'll need to check each suspect's was_hit property to see which one(s) collided. So, to copy/paste and simplify some stuff from shootbang:

 

    IF RHIT(bullet_start_object,bullet_end_object,enemy_start_object,enemy_end_object)=1 THEN
        ' Something was hit, so check each object for fine grained collision
 
        FOR i=bullet_start_object TO bullet_end_object
            IF RGETOBJ(enemy1+i,R_sprite_was_hit)<>-1 THEN     
                'this particular enemy was hit, do something about it!
            ENDIF
        NEXT i
    ENDIF
An important quote from the raptor manual is this: The sprite_was_hit flag needs to be reset before another collision test occurs.

 

Right, so how do we define the hitboxes? Let's turn to our good "friend", rapinit.s:

 

R_sprite_coffx: Collision box x offset - pixel distance from centre of sprite

R_sprite_coffy: Collision box y offset - pixel distance from centre of sprite

R_sprite_hbox: Width of collision box in pixels

R_sprite_vbox: Height of collision box in pixels

 

But why don't we just define the hitbox to be exactly the object's dimensions? Why do we need extra fields for this? Well, imagine if you have an object of 32x32 but your sprite is actually 26x12 and the rest of the pixels are blank. Oops! If you then use a 32x32 hitbox then your object will collide outside the area the viewer perceives as the border of the sprite - not fair! Another example is bullet hell shooters. In that case you will deliberately want to make the hitbox much smaller so your ship actually has a chance of dodging the tens of bullets on screen all coming at you at a breakneck pace.

 

And to check if a collision happened to this object we have:

 

R_sprite_was_hit: Did the sprite collide with another? Set to not hit to begin with, used later to flag collisions

 

Some more advanced stuff:

 

R_sprite_remhit: What to do if a collision is detected.

R_sprite_bboxlink: Bounding box for collision detect 'single'. Or address of table

Edited by ggn
  • Like 6
Link to comment
Share on other sites

And if the object is an odd shape, eg, something like T or H, then you can use multiple bounding boxes instead of a single one to mask out areas on the sprite.

 

You can also use the offset values to shift the bounding box off-center of the sprite. A practical example would be a 16x16 pointer arrow, where only the top left would need to 'collide'. You could shift the box -7 (x) and -7 (y) and then make the hitbox 2 pixels wide to cover the corner 4 pixels of the sprite.

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