Not logged inGosu Forums
Forum back to libgosu.org Help Search Register Login
Up Topic Gosu / Gosu Exchange / Gosu collision classes
- - By lol_o2 Date 2013-10-12 12:51 Edited 2013-10-29 19:00
When making a game, many problems come from collisions of objects. Most of games use simple bounding boxes, but they are not useful in all situations.
Well, what I'm showing here are not pixel-perfect colliders, but still they are pretty useful. To standard bounding box I added a circular collision, but this would be too simple. So I made the boxes rotating.

I based on this: http://www.gamedev.net/page/resources/_/technical/game-programming/2d-rotated-rectangle-collision-r2604
And this: http://www.migapro.com/circle-and-rotated-rectangle-collision-detection/
So our rectangles and circles can now collide with themselves upon any angle. They are just helper classes to attach to object and then check if they intersect.

The code is here: http://pastebin.com/Yxu9NTEy
Just copy it to your project and use the classes.
Example is attached to post.

initialize method of Collision_Box takes x, y, width, height and angle of box in degrees
And Collision_Ball takes x,y and radius
Both classes provide methods called set for setting position of collider and move which moves collider (well, rather useless one)
And of course, to check collision, you use collides? method passing another collider as argument.

Well, enjoy.

EDIT:
I forgot to mention that boxes can be rotated only around center.

EDIT2:
Added Collision_Group. Shapes in Collision_Group move relatively to group and any of them triggers collision of whole group.

EDIT3:
Now all objects from group rotate around group origin.
Attachment: Collision_Test.zip (3k)
Parent - - By jlnr (dev) Date 2013-10-12 15:05
I suspect it would be more efficient without the Vector class - especially on 64-bit versions of Ruby 2.0.0 where Floats "immediate" :)
Parent - - By lol_o2 Date 2013-10-13 10:03
First I wanted to use simple arrays, but besides looking quite confusing, would they be more efficient? I'm not such expert in optimisations.
Parent - - By jlnr (dev) Date 2013-10-13 12:53
No, that would still be a burden on the GC. Using the Floats directly should be the fastest way to do it in pure Ruby.

Of course, this library is a prime candidate to be turned into a C extension, if performance is ever an issue :) That would easily beat optimised Ruby.
Parent - - By lol_o2 Date 2013-10-15 13:54
Ok, I removed vectors and it still works. The code is updated, but not the example.
I also added some simple Collision_Group class.
Parent - By ml Date 2013-10-17 06:09
This sounds very exciting - especially the rotating rectangular collisions. I am looking forward to trying it out soon.
Parent - - By RavensKrag Date 2013-10-29 11:55
Just curious, but why are you implementing your own system instead of just using Chipmunk?
Parent - - By lol_o2 Date 2013-10-29 14:52
Using your own code gives more control and my way it's easier to use than Chipmunk.
Anyway, I never used Chipmunk, but instead some inconvenient simple equations. I was looking for some rotated collisions for XNA, found these articles and one day I just wanted them to port into Gosu.
Parent - - By RavensKrag Date 2013-11-05 16:34
I suppose by "easier to use" you mean it's easier to get the sort of motion you desire?

I find the syntax of Chimpunk (at least through Ruby) to be really nice,
but I do agree that using a physics engine to do character movement or something can be tricky.

(Though I think if you set velocities instead of using forces it's exactly the same as rolling your own thing (I've never actually done that... but I'm considering it for my next project))
Parent - - By lol_o2 Date 2013-11-05 20:09
I don't know exactly how is it in Chipmunk, but my collision classes are simple 'attachments'. You don't need any special 'space' nor any forces or velocities. You move your character in your own way then only update the position of box/circle to follow it. And collision testing is as simple as calling method of Collider A while passing Collider B as argument.
Parent - By RavensKrag Date 2013-11-07 00:38
I like the concept of a Space, because that way you have a collection where all the physics stuff is.  You can't figure out things like "which object are in this area" without looping over a bunch of collision classes.  Might as well store them all in a collection which can optimize queries by breaking up the game world into smaller bits. (Avoids looping over ALL objects every query).

Velocities are just changes in position over time, which is almost the same as moving a position by a certain amount each frame.  The main difference is that you can move to thinking in real time units, instead of game ticks.

-----

For collision testing between two objects, Chipmunk allows you to set up callbacks, which fire when objects collide.
I prefer callbacks over having to manually poll the system
(I do input parsing in Gosu::Window#button_down rather than using #button_down? as well)
but I will concede that is simply a matter of personal taste.

I think callbacks make it easier to organize code, allowing you to split up different types of collisions into separate files.
(Chipmunk callbacks are also tied to objects, so you can use inheritance if you want to :D)

Also, having a system to compute collision pairs for you removes the need to check if you're currently testing
"A1 with B1" or "B1 with A1"
both of which are the same collision, and you only want to process that collision once.
- - By lol_o2 Date 2014-09-02 19:50
I know this topic is very old (the time just flies, lol).
The classes I made seemed to be good, until I used them in game. Then they proved to be useless, because more complex game needs more than 10 colliding objects at once.
So, following the suggestion by RavensKrag and the popularity of my lighting helper I posted some time ago (7 downloads, wow), I'm sharing the 'ultimate closure' to this topic.
This means I used Chipmunk to make automated collision manager. It sets the space for you and manages colliders. It works almost like my previous classes, but the objects are now dependent on the manager. This adds 1 additional argument to each of objects' constructor (or none, if you make manager global) and 3 lines of code to your game, so it's still simple.
But the most important: efficiency. It easily manages 500+ objects with 60 FPS. It would be much more, but drawing in the example is not optimized.

Download it HERE.
Hope someone finds it useful.
Parent - - By RunnerPack Date 2014-09-02 23:53
Hey, this is great! Thanks for sharing!

Tiny suggestion: Add one argument to pass a Gosu::Window to Collision_Manager's constructor, and use its #update_interval instead of hard-coding the delta-time. It could also be used for "debug drawing", if one wanted to add that (it would be pretty easy to convert your existing example code).

Also, I noticed some references to "lights" in the readme, which was a little confusing at first (copy/paste error?)
Parent - - By lol_o2 Date 2014-09-03 09:00
Delta time uses only one constant, but maybe it's better to change it, since everyone would just use the FPS value.
I'm not sure about the debug drawing, because you have no access to the shape's vertices (as far as I know), so you need additional variables.
And the mistake in readme is because I copied the content from my previous light helper. Sorry :)

Updated the file.
Parent - - By RavensKrag Date 2014-09-29 16:08
You can get the vertices of any CP::Shape::Poly object by using #vert(i), where i is the index of the vert you want to retrieve. You can see how many verts there are by using #num_verts.

This interface is taken directly from the C API, and as such is very clunky and extremely un-Ruby-like.

I plan to submit a patch to the Chipmunk repo eventually with my interface modification to make this much more pleasant
(but don't hold your breath :P I think I've been saying that for at least a year now)

If you want some clean interface goodness RIGHT NOW feel free to use this monkeypatch:
https://gist.github.com/RavensKrag/f64eae75de5e4eb68378

That's the code I wrote, and have been using in my projects.
It defines various names for iterators over the vertices in a Poly object.

Feel free to use whatever interface feels the most natural to you.
Parent - - By lol_o2 Date 2014-09-29 17:12
Provided method returns only absolute position of vertices (same as initial ones). I have to add body position and calculate rotations, so it doesn't do anything new :/ Your method is probably the same?
Parent - - By RavensKrag Date 2014-09-29 22:37
Yes, my code is just a interface tweak over the raw functionality.

However, you can turn local-space coordinates to world-space ones using CP::Body#local_to_world(vec). This will take into account the position and rotation of the body. Totally already part of Chipmunk :D

(I should probably at least consider adding iteration over the world-space coordinates as well.)
Parent - - By lol_o2 Date 2014-09-30 12:42
Actually it's #local2world(vec), but thanks anyway.
Parent - By RavensKrag Date 2014-09-30 13:24
oh derp. I could have sworn I double-checked that before posting.

Yes, you are right. I always mess that up.
Parent - - By RavensKrag Date 2014-09-29 15:59
Chipmunk expects a fixed timestep, and the simulation can degrade rapidly if the timestep is not fixed.

This is related to the compounding error of the integration solver. The Euler method assumes that the error will level out when taking fixed steps of small size. But when the steps start to get large (which is possible when the timestep is not fixed) then things can get weird.

This is the canonical article on the subject, but it can indeed be a bit confusing.
http://gafferongames.com/game-physics/fix-your-timestep/

The takeaway as I understand it is that you should think about how the physics system will degrade as the game starts to lag, and not just about how the game will run in the best case.
Parent - - By RunnerPack Date 2014-09-29 17:01
My point wasn't to give the game the ability to alter the time-step "on the fly". I just thought it would be better to have the time-step match whatever the programmer already chose for Gosu's update rate. This way, there is only one place to make the change, so they will always match.

Thanks for that bit of insight into physics engines, though.
Parent - By RavensKrag Date 2014-09-29 22:40
Ah, sorry, my mistake. I guess I didn't understand how #update_interval works as well as I thought I did. Yes, that sounds like a fine idea.

(Sounds like my post was still somewhat useful, so at least there's that.)
Up Topic Gosu / Gosu Exchange / Gosu collision classes

Powered by mwForum 2.29.7 © 1999-2015 Markus Wichitill