4
\$\begingroup\$

I'm writing a 2d game for Android in Java using LibGDX. The game consists many interactions between different types of objects. Most of them happen between enemies and bullets. At the beginning, I needed to check every moment if any enemy collide any bullet (if their masks overlaps each other). The code for checking overlap is clear to me. My question is how should I make the interactions be checked between everyone every moment?

What I did is creating a class called InteractionsManager which takes the array of all enemies and the array of bullets and checking in every step collision between each other (if collision happens, it calls the object's onCollision(Object object) method).

My problem got bigger when I needed to check other interactions types (like if enemy is in a specific distance from other type of object and other stuff like that).

I thought about passing to each object the InteractionsManager object and it should tell it whatever interaction it needs.

\$\endgroup\$
  • \$\begingroup\$ What is your problem? Code is too complex or performance is decreasing? \$\endgroup\$ – Mayuso Jan 15 '16 at 7:32
  • \$\begingroup\$ I believe both. At start I wanted to avoid that every game object would have reference to every "main" object (like InteractionsManager), so the code won't be too complex but I find myself having trouble implementing more complex interactions. About performance, I'm not sure if it's a good idea running through all game object and checking interactions (in addition to that I'm already running through all object calling their update() method). \$\endgroup\$ – Gad Wissberg Jan 15 '16 at 7:42
  • 1
    \$\begingroup\$ If you are worried about performance, maybe you could use a quadtree instead of arrays to store objects. However, i think it may contribute to add more complexity to your code and wouldn't totally solve your problem, depending on what all your complex interactions are. \$\endgroup\$ – Khopa Jan 15 '16 at 12:29
  • \$\begingroup\$ It sounds like what you might be looking for are physics/collision layers & layer masks, and spatial partitioning strategies like bucketing/quadtrees as Khopa suggests, to reduce the number of object pairs that need to be considered for collision, and to filter other queries like range checks. These are normally the responsibility of the physics engine within the game, so researching physics engine architecture may give you some useful insights. \$\endgroup\$ – DMGregory Jan 15 '16 at 17:30
2
\$\begingroup\$

I'm not sure if its a good solution but i use to add x, y and z (gonna call this XYZ from now) and store it in a linked list with an object identifier and the average side size (we gonna asume that, in this example the object is a cube of 20x20x20 so 20*3/3 = 20).

//PSEUDOCODE
MYOBJECT ob(/*id*/ 1, /*size*/ 20, /*x*/ 30, /*y*/ 12, /*z*/ 4);

forward_list<float[3]> control;

control.push_back([1 /*ID*/ , 46 /*sum of all axis*/, 20 /*size*/]);

And, in every iteration, loop through the control list and check for collisions only between the object's who has XYZ equal or greater than his own XYZ (+/-) his own size*2.

//PSEUDOCODE
obj A
check B if
    (A.XYZ - (A.S * 3) >= B.XYZ + (B.S * 3)) &&
    (A.XYZ + (A.S * 3) <= B.XYZ - (B.S * 3))
if true add [A,B] to check_if_collide

I use this approach cause it doesn't check for collisions in objects too far and does not asume two objects are colliding when they aren't cause, after this "filter" you would have to check the collision as you would normally, but you gonna have a much short array of objects that are probably hitting each others.

hope it helps

\$\endgroup\$
  • \$\begingroup\$ Is that a sorted linked list? If yes, sorted by which attribute? I'm trying to understand what you suggested. \$\endgroup\$ – Gad Wissberg Jan 15 '16 at 11:34
  • 1
    \$\begingroup\$ its not sorted, but you can sort it if you want by XYZ value, the main thing is just looping through it and store in a secondary array all elements that returns true to the XYZ test, then you gonna have an array with all the elements that are susceptible to collide \$\endgroup\$ – PRDeving Jan 15 '16 at 11:45
  • \$\begingroup\$ "(A.XYZ - (A.S * 3) >= B.XYZ + (B.S * 3)) && (A.XYZ + (A.S * 3) <= B.XYZ - (B.S * 3))" but this expression already checks for collision, why check again? \$\endgroup\$ – Gad Wissberg Jan 15 '16 at 11:47
  • 1
    \$\begingroup\$ cause it doesnt, XYZ is just the sum of O.x, O.y and O.z, it just check if they "could" collide \$\endgroup\$ – PRDeving Jan 15 '16 at 11:49
  • 1
    \$\begingroup\$ cool, i thought in this solution once i had to code a really big sandbox, so, there was tons of elements. You can also check for the collisions "on fly" (in every match), it will be faster this way. the speed increment's thanks tho the linked list, it's iterations and memory usage are much eficient than normal arrays or objects \$\endgroup\$ – PRDeving Jan 15 '16 at 12:05
0
\$\begingroup\$

Disclaimer: This answer is 100% subjective, it is related to code design personal preferences and might not be the best answer.

I would delete InteractionsManager class.

The idea of having 2 lists (arrays) and checking for collision in a loop is nice, but you can do that on your Screen class. (just create a checkCollisions() method and call it on render()). The code will remain the same, no performance increase, but usually having too many classes might make the code hard to understand.

If you need more interaction types, you can follow the same idea: create a new function in your Screen class and call it on render().

I can´t really help you with performance without seeing the code.

\$\endgroup\$
  • 3
    \$\begingroup\$ "just create a checkCollisions() method and call it on render()" - That's not good advise. Game mechanics and rendering should always be separated. Otherwise you will either have projectiles pass through enemies when the framerate is low or have game speed dependent on the speed of the users hardware. \$\endgroup\$ – Philipp Jan 15 '16 at 8:08
  • \$\begingroup\$ I have created 3 games already for android and PC ( all 3 run on the two platforms), and never had any problem doing this. LibGDX fixes fps to 60 by default, so every device has the same refresh rate. \$\endgroup\$ – Mayuso Jan 15 '16 at 8:13
  • \$\begingroup\$ But if I want to add lots of interactions I think its best to let other class take care of it, don't you think? \$\endgroup\$ – Gad Wissberg Jan 15 '16 at 9:45
  • 1
    \$\begingroup\$ Maybe it's overkill, but I would personnaly go for one implementation per kind of interaction instead, especially if the gameplay is mainly based on these "interactions". \$\endgroup\$ – Khopa Jan 15 '16 at 12:58
  • 1
    \$\begingroup\$ This doesn't answer the question about how to scale performance to high object counts, and as Philipp describes it actively goes against industry best practices of separating gameplay & rendering, and maintaining narrow & clearly-defined responsibilities for each class. I would consider this answer to be an anti-pattern, actively harmful to the goal of scaling the game to large numbers of objects & interactions. \$\endgroup\$ – DMGregory Jan 15 '16 at 17:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.