Perfect Ricochet?

Masked

  • Posts: 76
I'm trying to make an actor ricochet off tiles, and I could use some help. First I'll describe by initial method of doing this and then explain why that didn't work. Then I'll beg for assistance.

So I have a bullet actor. It's long (about 20-30 pixels) and short (3 pixels high). I've set it up to have a round collision box (sphere?) at its tip. I set its bounciness to 1.0, and gave it a behavior with a boolean attribute "Has Ricocheted?" that's set to false by default. When it collides with a tile, "Has Ricocheted?" is set to true, and then any additional collisions will kill the actor. Here are my problems with that system.

The actor, being long and thin, spins out of control after bouncing off a surface. Naturally, this is something I want to avoid, as it looks weird for a bullet (+ its streak, it's like a tracer bullet I guess) to spin out. I'd prefer if it just stayed facing whatever angle it bounced off at. Also, when it hits tiles at angles close to 90 degrees, it must collide twice for some reason and never ricochets at all. I'm guessing that it registers one collision, sets "Has Ricocheted?" to true, and then collides again and kills itself all at one point.

And that's my problem. I could use some help. Thanks.

Alexin

  • *
  • Posts: 3130
Either use a single circle for the collision shape or fake the ricochet yourself, instead of relying on the physics engine.

I say the easiest solution is to a single circle, so the engine takes care of everything else. You just have to align the bullet with its trajectory ([set angle to [atan2[y-velocity, x-velocity]]]). Obviously, the drawback with this approach is the incorrect shape (it should be a rectangle), but if the bullet is small enough I think it's a good commitment.

The other solution is to use a rectangle shape (or whatever you want for that matter) and fake the ricochet.
When the bullet hits a tile, use its collision points to get the normal corresponding to the tile. Use that vector to reflect the direction of the bullet and invert the velocity vector.

As I said, I'd go with the first solution if I were you.
"Find the fun"
alexin@stencyl.com

Joe

  • *
  • Posts: 2480
The other solution is to use a rectangle shape (or whatever you want for that matter) and fake the ricochet.
When the bullet hits a tile, use its collision points to get the normal corresponding to the tile. Use that vector to reflect the direction of the bullet and invert the velocity vector.

I actually created a nice Behavior in the Java engine to do this, but I never ported it over.

Masked

  • Posts: 76
Alexin, while your solution to preventing spinning worked perfectly, I still face the problem of the bullet not ricocheted at most angles. I made the bullet spawn sparks at its collision points so that I could tell where they were being registered, and they're constantly appearing inside tiles, in strange places, etc. I've considered a number of possibilities for reasons as to why the bullet won't properly ricochet, all of which have to do with collision - when I made the bullet invincible it would still disappear at many angles when it hit a tile. This is probably due to the fact that the collision circle is at the very end of the bullet's sprite, so, with rotation and all that added in, stuff gets messed up when the actor tries to bounce off of things.

I'll try the same method with a perfectly round, 3 by 3 bullet later this afternoon (though that won't have the same visual "oomph" as the streak I'm using now) to see if that fixes the problems with collision, and if that doesn't work I'll experiment with your second suggestion. (Though to be honest I'm not sure how to do the math to calculate that second path for the ricocheted bullet).

If worst comes to worst I'll make the bullets not ricochet, though I think giving them that ability makes for a much more tactical experience.

Also thanks for your help.

Alexin

  • *
  • Posts: 3130
Try enabling continuous collision detection (there's a block for that) and set the friction to 0.0, while keeping the bounciness to 1.0.
"Find the fun"
alexin@stencyl.com

Darkhog

  • Posts: 1243
Either use a single circle for the collision shape or fake the ricochet yourself, instead of relying on the physics engine.

I say the easiest solution is to a single circle, so the engine takes care of everything else. You just have to align the bullet with its trajectory ([set angle to [atan2[y-velocity, x-velocity]]]). Obviously, the drawback with this approach is the incorrect shape (it should be a rectangle), but if the bullet is small enough I think it's a good commitment.

The other solution is to use a rectangle shape (or whatever you want for that matter) and fake the ricochet.
When the bullet hits a tile, use its collision points to get the normal corresponding to the tile. Use that vector to reflect the direction of the bullet and invert the velocity vector.

As I said, I'd go with the first solution if I were you.

Or maybe we can use something like that:

More like bullet, right? This is hybrid of both solution - physics engine will take care of collisions and shape of bullet is natural.

There are no impossible things. There is only lack of skills.
Don't click this if your computer has less than 641 kilobytes of RAM.
Stencyl stencyling stencylish stencylers :D

Alexin

  • *
  • Posts: 3130
It could work but you'd have to add another circle at the other end. As it is, it would respond correctly upon the first collision only. But then, Masked only wants one bounce...
"Find the fun"
alexin@stencyl.com

Masked

  • Posts: 76
Try enabling continuous collision detection (there's a block for that) and set the friction to 0.0, while keeping the bounciness to 1.0.

Stencyl
There's a block for that.©

Constant collision fixed the problem, along with making the bullet have little to no weight. I thought I'd made it weightless before, but apparently it kept switching it back to the previous value (20 kg) I'd entered until I switched it using the arrows instead of entering it manually (Er.. I just typed in a number close to the weight I wanted it to be, then had to click the arrows a few times to get it to stay. Minor bug.).

The long, thin actor shape results in some annoying visual errors, but I can see where those are coming from and can fix it by making the actor one large square.

Thanks a lot, guys.