Fast projectiles don't always hit

2019-07-17 19:36发布

问题:

So for my game, a have a fast moving Bullet object, with a sprite that's 5x5 (roughly). Moving at about a speed of 30, it needs to impact a relatively thin Enemy object with a thickness of only about 5 pixels. At certain regular intervals of distance, the Bullets pass through the enemy without a collision.

I think its because the bullet is moving so fast that it happens to "jump" over the enemy, hence the regular intervals. other than increasing the width of the Bullet or Enemy, is there a way to guarantee that a collision is properly detected?

回答1:

test the area that the sprite jumps.

so, for the collision box, test all the way from the bullet's previous forward-most position until it's new forward-most position. so for if the bullet is moving right:

bullet.collisionbox.x = bullet.x
bullet.colisionbox.y = bullet.y
bullet.collisionbox.width = bullet.x + bullet.width + newpos.x
bullet.collisionbox.height = bullet.height

graphically:

>[____________>]

so you're not increasing the width of the bullet or enemy, just the collision detection for the bullet to the enemy.



回答2:

in Flash i use HitTest method to test if an object collides with another object, i think there is an collision you just need to add some code to change the direction,speed or appearance of the bullet when the Hit becomes true, it will pass through the object even though it Hits/have contact with it if you have no codes for changing its properties when the Hit Event happens

OR

You can test the area of the Bullet and the Moving object

IF (AreaofBullet=AreaofMovingobject)
Change The Appearance, properties of the bullets and the object
else
Do nothing

Hope this helps

thanks :)



回答3:

There are many solutions to the problem, like:

a) Using move_contact_... functions for moving bullet

b) Moving bullet in loop with lengthdir_ functions and manual collision checking, like:

var i;
for (i = sprite_width; i <= speed; i += sprite_width)
{
   if place_meeting(x + lengthdir_x(i,direction), y + lengthdir_y(i,direction), o_wall) // is a wall in this position?
   {
       x += lengthdir_x(i, direction); // moving to position of the collision
       y += lengthdir_y(i, direction);
       event_perform(ev_collision, o_wall); // call collision event 
   }
}

c) Using collision_line after position changing, like if collision_line(x, y, xprevious, yprevious, obj, false, true)!=noone { ... }

and many other...



回答4:

You can descrease the speed of the bullet to 4 or less to guarantee that a collision will be detected. Also, you can increase the collision mask of the bullet behind the end without making the sprite larger. Doubling the bullet's mask width allows you to make the bullet have a maximum speed of 9.



回答5:

Your problem is that your bullet is moving too fast. The bullet isn't actually moving through space. So if you set your bullet's x speed to 5 each time through the game loop the bullet is redrawn 5 pixels over. If the bullet's speed is 30 then it's redrawn 30 pixels over without actually going through those pixels. If an enemy is between the two locations the bullet would be drawn the bullet will never collide.

Consider this. Your enemy is at position (5, 5) and is a 5x5 square. Your bullet is coming from a position of (0, 7). and is a 1 pixel big. If your bullet travels in the x direction at a speed of 20 pixels then the bullet will be drawn at (0, 7) and then at (20, 7). Neither of those locations intersect your enemy.

My recommendation is to either slow down your bullet or resize the bullet sprite. The bullet sprite could still be a small pellet and you could leave the rest of the sprite transparent. Kind of like making the collision box bigger for your bullet.

Hope this helps :)



回答6:

You can change the collision box, but ultimately you will want to use collision line because the direction could be different. (If not, then you can use collision box anyway)

Always point the collision line ahead of where the bullet is to avoid it looking like it passed the object before being destroyed. Do this using the degree of direction with a distance of the speed.

You will want to take off any collision detection methods and use only the one that works for your situation to keep things efficient... as possible anyway.