Pardon me for any incoherency but I am drunk and annoyed.
Over the course of the last week, I have had three programmers arguing with me that it is generally speaking a Good Idea to have a manager class in your game to handle collisions, instead of putting the collision resolution in one of the things that are actually colliding.
Their example is that you can have a single function batch-process all the collisions at once by taking an array of one thing that might collide, and iterating across another array of things they might collide with.
Bitch, where is your spatial partitioning?
You do not detect collisions like this. You detect collisions by iterating across ONE collection of objects, asking your spatial partitioning system for a list of things each collides with.
See, as your game operates, whenever an object moves… an insertion sort is performed on the new location, placing the object into a two-dimensional hash table where hash collision is resolved with a list. If object 257 is in location D-5, and D-5 is already occupied, object 257 is simply added to the end of the list of things in location D-5.
When you need to determine whether object 257 collides with anything, you ask the spatial partitioning system “what is colliding with object 257?” and it grabs the list. If object 257 is close to the left edge of D-5, you will get the list for C-5 as well. If it is close to the right edge, you will also get the list for E-5. Close to the top? D-4. Close to the bottom? D-6. Close to a corner? C-4, E-4, C-6, or E-6 as appropriate. The ultimate list provided is a combination of at most four lists. This combined list is iterated, and anything colliding with object 257 is added to a new list and handed over.
The manager class then has to tell object 257 about the collisions. This is objectively less efficient than just having object 257 ask “what is colliding with me?” in the first place.
And you do not want to get me started on the inefficiency of foreach(bullet in bullets) foreach(enemy in enemies) if (collide(bullet, enemy)) resolve_collision(bullet, enemy). What the entire fuck. Why would you do this. Look at you. You, who were once so proud. Go, and never return.
I am fairly sure that is exactly what these fucking idiots were recommending.
I am constantly running across people who complain that object oriented thinking is contaminating my approach to problems, whereupon they explain that you should solve the problem in the exact same way… except with bare functions and global variables.
Hey, I remember those days. They sucked. Do you know why they sucked? Because fucking stupid people just like you would go in and fuck with the data directly instead of using the proper protocols.
Like you have a vector representing the direction a character is facing. This vector is guaranteed to be a unit vector, because every single thing that updates it normalises the vector after updating. That is the rule: update, normalise. Everything that updates normalises.
But sooner or later someone doesn’t know what function in the library makes the update they want, but they know how to make the update directly. So they just update the vector and don’t normalise, because they don’t know they have to. This can go undetected for a surprisingly long time, because it would have to be the last update to the vector before something uses it and expects it to be normalised. And then you get a shockingly unhelpful bug report that “sometimes” shit gets weird.
It can take months or even years to stumble over the problem. It’s even possible that someone is scrolling past the problem and says “just as a point of style we should do that with the library function,” and they fix the bug without even knowing it was a bug. Then you never find the problem, so you never know who did it, and you can never go tell them for to not for to do that.
The modern programmer wants these days back, because they do not want to do things right, let alone well. They just want to be done as quickly as possible. If the code is broken, that’s fine! Job security for testers and programmers alike, because the code never works correctly so we’ll always need testing to report the bugs and programmers to fix them. Nobody wants to do the job right, because if the job is ever done, they might lose their job. You have to keep it perpetually broken so the contract never ends.
This is, incidentally, why I quit the defence industry. Defence contractors would get a contract, and make sure to deliver a product that (a) met every requirement, but (b) was unusable for the expected purpose. The FAR being what they were, it was absolutely guaranteed that we would get the contract to “fix” what we fucked up on purpose in the first place. I found this not only unethical, but borderline treasonous, and - unable to find anyone who didn’t do this shit - I went into the private sector.
Now people are doing that at the individual level, because they don’t care about their employer or the customer or even the project they are working on. They don’t even have the fundamental engineering drive to deliver something cool that works.
About twelve years ago, I was annoyed at the people in the Unity forums because not only did none of them understand basic software engineering, they lacked even the most rudimentary curiosity about it.
Now that’s the whole fucking industry. It’s everyone. They suck. They’re shitty at their job and they have no interest in being any less shitty. And it’s fucking disgusting.