About Monkey 2 › Forums › Monkey 2 Development › Collision module and performance
This topic contains 43 replies, has 8 voices, and was last updated by
peterigz
2 years, 8 months ago.
-
AuthorPosts
-
June 19, 2016 at 6:49 pm #1179
My latest round of optimisations is now up to 5.6mill/sec which I’ll settle for for now, really pleased with that. I’ve learnt quite a few things along the way, and also some oddities. It’s definitely ok to modify the fields of a struct in some cases so I won’t worry to much about that, for example this:
[/crayon]Monkey123456789[crayon-5cba16c0ce008474389588 inline="true" ] Method TFormBoundingBox()'After the bounding box is updated, it needs to be moved into world space.boxoffset.x = tl_corner.xboxoffset.y = tl_corner.ytl_corner.x+=world.xtl_corner.y+=world.ybr_corner.x+=world.xbr_corner.y+=world.yEndworked out quicker than:
[/crayon]Monkey123456[crayon-5cba16c0ce00e041622705 inline="true" ] Method TFormBoundingBox()'After the bounding box is updated, it needs to be moved into world space.boxoffset = tl_corner.Clone()tl_corner+=worldbr_corner+=worldEndSo I guess if your struct already exists and you need to clone it or change values then it can be ok. But in this case:
vec.Normalise()
Where the normalise method modifies the fields of the vector was quite a bit slower than:
vec = vec.Normalise()
Where it returns a new normalised vec. It’s really nice that mx2 gives you that extra control to make a difference with the speed of a program.
June 19, 2016 at 7:51 pm #1180Have a look at Operator+=
Mx2 will synthesize one for you, but you can provide your own too.
June 19, 2016 at 9:32 pm #1181Also, just cleaning up another issue and there appear to be several places in timelinefx where you use ‘Stack’ or List’ without any type, eg:
Method GetObjectsInBox:Stack(area:tlBox, Layer:Int[], GetData:Int = False)
This was compiling before but wont with the next release. Full list of errors with my release…
D:/dev/monkey2/modules/timelinefx/quadtree.monkey2 [246] : Error : Type ‘Stack<T?> is generic
D:/dev/monkey2/modules/timelinefx/quadtree.monkey2 [291] : Error : Type ‘Stack<T?> is generic
D:/dev/monkey2/modules/timelinefx/quadtree.monkey2 [841] : Error : Type ‘Stack<T?> is generic
D:/dev/monkey2/modules/timelinefx/quadtree.monkey2 [936] : Error : Type ‘Stack<T?> is generic
D:/dev/monkey2/modules/timelinefx/collision.monkey2 [1068] : Error : Type ‘List<T?> is genericJune 19, 2016 at 10:37 pm #1182Thanks, fixed. Although I still have work to do on some of those quadtree methods. Is there an equivalent to .Last for stacks by the way? I’m guessing Top is the same as First?
I see what you mean about += operator, yes that does seem to sort it. The Clone method really kills it though (about 500k less), a bit odd?
[/crayon]Monkey123[crayon-5cba16c0d781f018771980 inline="true" ] Method Clone:tlVector2()Return New tlVector2(x, y)EndBut then again I get different results elsewhere and clone seems fine. I think I’ll just put it down to the compiler and how it evaluates things in its own exotic way!
June 19, 2016 at 10:55 pm #1183I mean ‘Operator+=’, not ‘Operator+’, eg:
Monkey12345Operator+=( v:tlVector2 ) 'no return value!x+=v.xy+=v.yEndIf you’ve defined an Operator+() but not an Operator+=(), mx2 will rewrite…
p+=v
…as…
p=p+v
…but if you’ve defined Operator+=(), mx2 will use that instead.
I’m guessing Top is the same as First?
Top is really ‘last’, ie: the last thing pushed/added. blah[0] is ‘first’. You can use a stack pretty much how you’d use a c++ std::vector or java ‘ArrayList’, ie: index with [i], so blah[blah.Length-1] is also ‘last’ or ‘Top’.
June 20, 2016 at 4:04 pm #1191Thanks Mark, yes I actually realised what you meant about the += and edited my post before you saw I think. I did add that operator to my vec class and it did help so that’s good.
That’s good about Top too, I was hoping it’d be the same as Last
June 25, 2016 at 11:27 pm #1228Got this pretty much all working now
I do have one issue though, I just started updating the docs but now for some reason it hangs when compiling, doesn’t get passed “Parsing”:
[/crayon]Monkey123456[crayon-5cba16c0de553525117479 inline="true" ]C:\monkey2\bin>mx2cc_windows makemods timelinefxMX2CC V0.011***** Making module 'timelinefx' *****Parsing...I’m not sure sure what I’ve done other then add in some docs. Latest version is on github: https://github.com/peterigz/timelinefx.monkey2
June 26, 2016 at 12:36 am #1229There are a few issues…but what’s hanging the compiler is a stray ‘=’ before a ‘#End’ in quadtree, ie: search for ‘=#’.
Will fix!
June 26, 2016 at 12:47 am #1230There is also a bit of an issue with markdown ‘#’ clashing with ‘#’ for the preprocessor…need to come up with some kind of work around for this.
June 26, 2016 at 12:59 am #1231Thanks! All fixed now. Thought there might be other issues as I had to merge some changes but obviously couldn’t test
August 2, 2016 at 2:14 am #2672So I’ve found a little bit of time to play with the collision module, and I have to say it’s working great!
My next step is to try to use this with my own entity system. In my old one, each entity used to have a “Transform” object that provided much of the functionality you already have in tlBox, like coordinates, dimensions, moving with collision, etc., so I’m going to just use tlBox instead this time.
There’s one little thing I wanted to ask what’s the best way to implement: hierarchies, so that moving the parent moves all its children as well. Notice that in this case, objects need to store their local coordinates, and then calculate the world coordinate before they can do anything useful.
Should I add a step somewhere that adds the coordinates together on every frame before displaying and checking collisions? Os is there a better, built in way to do that?
Thanks!
P.S. Here’s a quick test I did to get my feet wet:
Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293#Import "<timelinefx>"Using mojo..Using std..Using timelinefx..Const BOX := 0Const CIRCLE := 1Const POLY := 2Function Main()New AppInstanceNew ColTestApp.Run()End' *************************** Window ***************************Class ColTest Extends WindowField player := New Entity( 200, 240, 40, 40, CIRCLE )Field box := New Entity( 400, 240, 100, 100, BOX )Field circle := New Entity( 300, 360, 50, 50, CIRCLE )Field poly := New Entity( 320, 100, 50, 50, POLY )Method New()Super.New( "ColTest", 640, 480 )EndMethod OnRender( canvas:Canvas ) OverrideApp.RequestRender()player.Update()For Local e := Eachin Entity.alle.Draw( canvas )NextEndEnd' *************************** Entity class ***************************Class EntityField collider:tlBoxField speed:= 5.0Field result := New tlCollisionResultGlobal all := New Stack< Entity >Method New( x:Double, y:Double, width:Double, height:Double, shape:Int )Select shapeCase 1collider = CreateCircle( x, y, width )Case 2Local verts := New Float[]( 0, 0, 1, 1, 0, 2, -1, 1 )collider = CreatePolygon( x, y, verts )collider.SetScale( width, height )Defaultcollider = CreateBox( x, y, width, height )Endall.Add( Self )EndMethod Update()Local vel := New Vec2fIf Keyboard.KeyDown(Key.Up)vel.Y -= speedElseif Keyboard.KeyDown(Key.Down)vel.Y += speedEndIf Keyboard.KeyDown(Key.Left)vel.X -= speedElseif Keyboard.KeyDown(Key.Right)vel.X += speedEndcollider.Move( vel.X, vel.Y )For Local e := Eachin allIf Not ( e = Self )result = CheckCollision( collider, e.collider )PreventOverlap( result )EndNextEndMethod Draw( canvas:Canvas )collider.Draw( canvas )canvas.DrawPoint( collider.WorldX(), collider.WorldY() )EndEndAugust 2, 2016 at 10:20 am #2684I think my approach was to separate the collision box from the entity rather then try to use it as the thing that manages all the coordinates of the entity. I guess you could do it like that but as tlBox doesn’t come with a local vector (only world) you would have to extend it and then override tForm() to transform stuff from local to world.
So I would have the entity have it’s own vectors to manage its position and update it’s collision box each update, which is a little bit more overhead but ultimately more flexible. That also goes back the other way if you use prevent overlap, whereby the collision box would need to update the entity coordinates after a collision.
Under the particles branch on github there is gameobject which might help (https://github.com/peterigz/timelinefx.monkey2/blob/particles/gameobject.monkey2). I think use a couple of collision boxes, one for actually calculating the collisions, and a container box, which updates to envelope the whole entity for off screen culling and such. I wrote it a while ago though so I’m not sure what everything does!
August 3, 2016 at 5:00 am #2695That’s great, thanks! I’ll dig into that gameobject code and see how I could adapt it as soon as I find a bit of time again.
Just out of curiosity, I see that you added a lot more classes and stuff, but has the collision code changed much since last month’s commit (which is what I’m using currently)?
I think I’ll go with a “transform” object just to keep that stuff separated from entity events and components, and I’ll handle the transform inheritance and collisions through the transform class. Thanks for sharing!
August 3, 2016 at 10:43 am #2710I haven’t touched the collision code, only added all the extra timelinefx stuff so it should be all the same when I eventually merge it all.
-
AuthorPosts
You must be logged in to reply to this topic.