New module - rigz.collision
BlitzMax Forums/BlitzMax Programming/New module - rigz.collision
| ||
I've added a new module to my slowly growing collection - rigz.collision. As well as being able to check for collisions between boxes, circles lines and polys, (plus you can do ray casting), you can also use quadtrees for spatial partitioning. To get it you can either grab from SVN here: http://subversion.assembla.com/svn/timelinefx-module - checkout into rigz.mod or download here: http://www.rigzsoft.co.uk/files/rigz.mod.zip (this is compiled for windows, so if you download on the Mac just makemods to recompile it) Lot's of people can take some credit for this module as I learnt a lot from various tutorials and source code here and on the internet. The whole thing is fully documented with examples, but I'd say it's still a beta at the moment as I'm sure they'll be a few bugs/quirks about :) Here's a copy and paste of the overview from the docs: Not much in the way of a screen shot but here's an example of using a quadtree to draw a maze (Thanks to impixi from the blitz forums for the TDungeon code in archives found here: http://www.blitzbasic.com/codearcs/codearcs.php?code=1891 ) and prevent a player from overlapping the walls. Thanks to the quadtree, culling off screen tiles and only checking for collisions in the immediate vicinity is easy and fast. |
| ||
thanks, very generous |
| ||
Some good-looking stuff in this module -- thanks! |
| ||
Thanks a lot, seems like a super-great module! |
| ||
Hi Pete, I thought I should re-visit http://www.blitzbasic.com/Community/posts.php?topic=85634 one day and polish it up a bit now that I know BMax better, then I saw this and thought I needn't bother now. However I just noticed this today; Thanks to matibee, Leadwerks and Oddball from the Blitzmax forums, plus the authors of various sites (see docs for links) Nice one :D For the latest samples based on my code try; http://www.blitzmonkeys.com/index.php?topic=188.0 |
| ||
Hi matibee, yes I saw your samples on blitzmonkeys, I didn't have any kind of collision response at that point so it was a useful reference, as was the quadtree stuff :) |
| ||
that platformer example is pro |
| ||
I thought I had already replied to this topic. Maybe it was somewhere else? Anyway, nice module. I can use this :-). |
| ||
I wish I had seen this a week ago. I've been going half mad trying to do some circle/line-segment intersection code. I'm rubbish at math and it took me about a whole day of gibbering before I got something working. Good stuff! :) |
| ||
This is great :) I'm playing with this module now and it's very easy to implement. I do have a question though: I create a poly for a midhandled bitmap object, but they don't align with eachother - is centering handled differently? EDIT: Not a problem anymore!! I had the coordinates wrong :) Also FYI: drawing the bounding box with a poly doesn't take into consideration the offsetX and offsetY passed along with the poly.draw method. |
| ||
Glad you like it! The handle of the polygon is set to the middle by averaging all the vertices automatically, but I see you've solved that anyway :) I have fixed the offset problem and committed the changes via SVN if you can use that? Otherwise I'll upload a new downloadable version soon. |
| ||
I'll grab the SVN version no probs! I also had some issues when scaling the polygon differently in X and Y even though scaling the bitmap the same amount. I'll dig into this further though, could be me again :) By the way - have you done any performance testing with this system, i.e. how does it compare to the native bitmap collisions? |
| ||
Hmm, yeh I seem to have muddled the matrices a bit there! I committed a fix on SVN. I didn't do any direct tests, but then there's no kind of quadtree implementation for the bitmap collisions so it's hard to compare, on top of the other features such as preventing overlap. The main performance test is the maze example (screenshot above) where it's testing for a collision with 30 odd thousand sections of wall (and doing off-screen culling). Using a quadtree means only the immediate sections of wall are tested so each check is under 1ms. |
| ||
I'm still playing around with this and loving it =) My next observations are: I) If I fire a bullet with a collision poly into another collision poly it will quite often end up inside the target poly if the angle is quite shallow. When this happens the bullet will bounce around inside the target poly like crazy. I've tried using a circle for the bullet instead with same result. Finally I've also tried making sure that the target is stationary and nonrotating and with high update frequency 100hz, same issue. 2) When you do GetReboundVector, what is the best way to have both objects rebound off eachother if they are both moving? |
| ||
Do you have any example code of the first problem? This could be a problem called tunnelling where fast moving objects can miss their collision or end up inside stuff, but when you say it happens when the angle is shallow I'd it might be something else. As for the 2 objects bouncing off each other currently nothing is really implemented yet for this. For that I'd need to introduce mass to objects to correctly calculate that, which I might do at some point, it shouldn't be too hard to implement given that so much of the ground work is done already. But there's only so far I'd want to take it in that direction before you may as well just use a physics engine like box 2d. I'll probably stop at a snooker balls bouncing off each other and leave it there :) The closest you can get at the moment would be something like object1.velocity=GetReboundVector(collisionresult,object1.velocity) object2.velocity=GetReboundVector(collisionresult,object2.velocity) But that won't work if the 2 objects are travelling in similar directions, some kind of physics calculation would be needed to do it properly. Thanks for putting it through its paces! |
| ||
It must be a combination of the code I use where I have my own little 2D physics with the collision system because if I only use more or less the poly coordinates the problem isn't too frequent. This example code will demonstrate how some objects slides around the boundary of a target which commonly happens in my little game as well in addition to them actually landing inside the target: SuperStrict Import rigz.collision Import rigz.vector Graphics 800, 600 Global target:TObj= TObj.Create(300,300,[0.0,120.0,12.0,28.0,42.0,2.0,82.0,0.0,111.0,11.0,133.0,3.0,182.0,12.0,197.0,52.0,189.0,103.0,153.0,130.0,99.0,152.0,82.0,154.0,75.0,161.0,35.0,157.0,10.0,142.0]) While Not KeyDown(KEY_ESCAPE) Cls Local bullet:TObj = TObj.Create(10,Rand(230,350),[20.0,3.0,25.0,2.0,25.0,5.0,20.0,4.0]) bullet.setVelocity(Rnd(5,15),Rnd(-1.0,4.0)) TObj.update() TObj.draw() DrawText "Objects: " + CountList(TObj.LObjects),10,10 DrawText "Press space to rotate target",10,25 Flip 1 Wend Type TObj Global LObjects:TList = CreateList() Field link:TLink Field x:Float Field y:Float Field angle:Float Field velocity:tlVector2 = CreateVector2(0,0) Field poly:tlPolygon Function Create:TObj(x:Float, y:Float, verts:Float[]) Local obj:TObj = New TObj obj.x = x obj.y = y obj.poly = CreatePolygon(x,y,verts) obj.link = LObjects.AddLast(obj) Return obj End Function Method setVelocity(x:Float, y:Float) Self.velocity.x = x Self.velocity.y = y End Method Method setAngle(angle:Float) Self.angle = angle Self.poly.setAngle(angle) End Method Function update() For Local obj:TObj = EachIn LObjects obj.x:+obj.velocity.x obj.y:+obj.velocity.y obj.poly.setPosition(obj.x,obj.y) If obj <> target Then Local result:tlCollisionResult = CheckCollision(obj.poly, target.poly) If Not result = Null Then PreventOverlap(result) obj.velocity = GetReboundVector(result,obj.velocity) obj.poly.setAngle(ATan2(obj.velocity.y, obj.velocity.x)) End If Else If KeyDown(KEY_SPACE) obj.setAngle(obj.angle+1) End If If obj.x > GraphicsWidth() Or obj.x < 0 Or obj.y > GraphicsHeight() Or obj.y < 0 RemoveLink obj.link Next End Function Function draw() For Local obj:TObj = EachIn LObjects obj.poly.draw() Next End Function End Type |
| ||
Ha! how strange is that? Thanks for the sample, it's actually quite a simple solution. When the system prevents an overlap, it will move the tlPolygon so that it no longer overlaps, therefore you need to update your tObj to reflect this as well. This was essentially causing the result of the overlap prevention to be ignored so on the odd occasion a bullet started to skate round the edge :) I've updated the documentation to highlight this a bit more. Here's what I put in your sample to fix it: If obj <> target Then Local result:tlCollisionResult = CheckCollision(obj.poly, target.poly) If Not result = Null Then PreventOverlap(result) obj.velocity = GetReboundVector(result, obj.velocity) obj.poly.setAngle(ATan2(obj.velocity.y, obj.velocity.x)) obj.x = obj.poly.GetWorldX() obj.y = obj.poly.GetWorldY() End If Else If KeyDown(KEY_SPACE) obj.setAngle(obj.angle+1) End If |