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 ENDIFAn 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, Fri Jan 5, 2018 12:16 AM.