mspraggs / potentia

Southampton Game Jam 2015
0 stars 0 forks source link

New Collision System #20

Closed DivFord closed 9 years ago

DivFord commented 9 years ago

I'm planning to re-do collisions.

Thoughts?

mspraggs commented 9 years ago

Ok sure. I'm still a bit uncertain what changes we're doing. Did we all agree on a strategy?

Fyll commented 9 years ago

No, but we may as well do this while we remember.

DivFord commented 9 years ago

Thus far, I'm in favor of Command as a pattern, but we'd need to plan out the implementation.

Fyll commented 9 years ago

"Command as a pattern"?

DivFord commented 9 years ago

http://gameprogrammingpatterns.com/command.html

Didn't you do the reading?

Fyll commented 9 years ago

Whoops, must have missed that!

mspraggs commented 9 years ago

It's ok, I've link spammed a few times but it wasnt' obligatory. I'll read the bit on Command.

Fyll commented 9 years ago

Hmm. I'm not sure I see how that relates to what we're discussing. Are you saying you have a problem with the Player class reading from INPUT? I thought we were discussing the problems about separating graphics and gameplay, and sorting out collisions.

DivFord commented 9 years ago

So, here's an idea. We split the codebase into Gameplay, Graphics and Physics, with a controller to tie it all together. Functions return commands, which the controller passes to all three modules on the next update.

eg. We call Gameplay::update(), which calls the input scan, returning Input commands. Gameplay converts these to PlayerMove commands, which it returns to the controller. Next loop, controller passes the PlayerMove commands to Physics (well, to everyone, but only Physics cares), which does the collision checking, returning PlayerCollide commands for Gameplay to use, and PlayerPosition commands for Gameplay and Graphics to use.

Fyll commented 9 years ago

Sure, I understand (mostly). My question isn't how it'd work, but why we should use it. What's the benfit to be gained by implementing this? It seems more confusing if anything, compared to now, where if something wants to know if you've inputted something, it just asks.

DivFord commented 9 years ago

The benefit is that the three systems never have to communicate directly, so they're easier to maintain.

Since all the commands are passed to everything, we don't need to work out where new functions go, just stick them in update and tell them what events (commands) to respond to.

mspraggs commented 9 years ago

This would greatly simplify the interaction of the player with the props.

Fyll commented 9 years ago

But all of the inputs /are/ already passed to everything!

@mspraggs : How? The player input has no interaction with collisions.

DivFord commented 9 years ago

Yes, but commands don't just mean inputs.

Whenever Physics determines that the player collides with something, it returns a PlayerCollide command, with the info on the collided object. That gets passed back to gameplay on the next update along with everything else, so whatever needs to trigger off it is easier to do. For example, if we get PlayerCollide(fire), we deal damage.

Fyll commented 9 years ago

Would it not be easier though if, when the player bumped into the fire, he asked the fire "what happens now", then the fire says "you die", then the player dies?

DivFord commented 9 years ago

Hackery! For that to happen, player has to talk to props directly, which is causing a buttload of trouble already.

mspraggs commented 9 years ago

The idea is to create a common channel for game control that all actions go through, which will make the code easier to debug and maintain.

mspraggs commented 9 years ago

Actually I'm a little bit confused by this too. If we look at the fire example, does that mean that fire sends a kill Command? All the examples in this article are concerned either with the player or other actors in the world, but not so much static elements.

Fyll commented 9 years ago

What trouble is it causing? Someone, somewhere has to know both parties which won't reduce any of the complexity.

I'll admit that some of the stuff in the code is quite obtuse, but this is something that isn't. The collision has to be spotted by one or both of them, then they need to eventually get the messaget hrough to the other party, who then needs to react appropriately (possibly sending a return message). Making all such messages go through a common route won't be any cleaner than having them where they're used.

Fyll commented 9 years ago

A general Collision singleton would be better, so each prop can contain a function pointer from Collision, which it calls when it collides.

Fyll commented 9 years ago

Wait, scrap that. It'd be better to have both Props and the Player share a parent, so the function can be from the PropPlayerParent class. That way, fire could smash crates.

DivFord commented 9 years ago

I tried implementing Collision as a singleton, but ran into circular referencing. That may just be me being bad at C++ though. If you think you can pull it off, it might be simpler.

Fire could send a kill command, or playerUpdate could kill the player on receiving a PlayerCollide(fire) command. Though there probably still needs to be some kind of Command, for the world update to load a new room.

My theory is Game calls update(), which calls update on Physics, Gameplay and Graphics, passing them each the command list. Those then return new commands, which get passed by the next game update. The updates on the three modules would each work in the same way, so the commands would all pass down the update hierarchy, then get returned back up.

Fyll commented 9 years ago

Something that's been nagging me for a while: shouldn't Player be in World? That'd simplify things a bit (and makes more sense) I'd imagine.

I'm currently trying to write a nice Object class. It all seems good so far.

mspraggs commented 9 years ago

The recommendation of the above book is to use singletons sparingly, as it encourages global state: http://gameprogrammingpatterns.com/singleton.html

DivFord commented 9 years ago

@Fyll, the only problem with that is that if we want to load a new world when the current one is completed, it will reset the player's guns. There's probably an easy way to fix that though.

Fyll commented 9 years ago

...And? His guns reset at the start of every level anyway. Or are you thinking ahead to when he acquires new guns as he progresses? If so, there are ways around it.

DivFord commented 9 years ago

I'm thinking ahead. Not very far though - to be honest, I assumed that was just a hacky fix to get a prototype working for the showcase.

Fyll commented 9 years ago

Fair enough.

On the Singleton problem, the only valid complaint seems to be about multi-threading, which we're not doing (because it's terrifying). I don't think we will have to worry.

DivFord commented 9 years ago

The global variables point was important too, but so long as we comment things properly and don't overuse singletons, I can't see it being a problem. Maybe we need to use the wiki?

mspraggs commented 9 years ago

I think the other issue is that you have a global state that can be accessed anywhere in the program. If it can be accessed or changed from everywhere, it can make tracking changes to this state when you're debugging very difficult.

Fyll commented 9 years ago

However, of the 4 singletons (Window, GraphicPool, Input, and Game), only Game (and at the moment, Window) should cause any problems, and Game's only used like that for messy redirecting, which should be cleared up in all of this.

mspraggs commented 9 years ago

@DivFord Which wiki are you referring to?

DivFord commented 9 years ago

The github page lets us add a wiki. I thought it might be good to document our API.

Fyll commented 9 years ago

Okay, I think I've got a nice looking Object class.

mspraggs commented 9 years ago

CopyPasta?

Fyll commented 9 years ago

It's a bit long. I'll add it and push.

mspraggs commented 9 years ago

Ok cool. It looks good. I've made a few tweaks and pushed.

Fyll commented 9 years ago

Eh... The reason I didn't pass by reference or write any set functions was 'cause I thought one of the whole points of this step was to not allow anything outside of Object to alter its contents through unapproved means.

Also, what's with all of the consts on the parameters? I haven't tried changing any of the values inside the functions, so it shouldn't be necessary, should it? EDIT: Blargh. I've just read up on const correctness and give up. All it seems to do is move runtime errors to compile time, while making the code a lot uglier, but fair enough, it will make things a bit easier to determine what's going on (even though the increased character density makes it harder to read).

Also also, what was the point of the move function being separate to the update again? If update is called first, then collisions are checked, then move, no collisions will be detected, as nothing has moved yet.

EDITx2: Why is the destructor vitual now?

mspraggs commented 9 years ago

Sorry, the corrections weren't meant as criticisms.

You're correct, the idea with const-correctness is to avoid errors creeping in at runtime by checking at compile-time. It's also a way of signalling to users of your function whether it's safe to pass a variable that they don't want changed. In the end it's all just interface design.

Yes, I have returned by reference, but what I've also done is make the function const, which means the method can't be used to alter the class instance in any way, including by altering the returned reference. EDIT: Looks like I cocked this up. I've returned by const reference now to fix this.

I think the idea was to update all the velocities etc before moving the objects, so you avoid the situation where you're changing the observable you're measuring. E.g. you move an object, but then a neighbour no longer needs to react, as it's out of range, and so it doesn't.

DivFord commented 9 years ago

A side note: Suicide seems to restart directly without going through the outro now. I assume that's intentional?

Fyll commented 9 years ago

No no, I didn't see it as criticisms, I was just confused/irked about the reference returning, as well as the setVel() and setAcc() functions.

Surely we can't check if they've collided though unless one of them actually moves into the place?

@DivFord : Nope, that's a bug. I'm looking into it.

DivFord commented 9 years ago

It seemed like a good feature until I realized it happened when you died as well...

Fyll commented 9 years ago

Okay, having spent the last while trying to sort this out and just ending up deeper and deeper in bugs, what say you we sort out this update? :P

DivFord commented 9 years ago

Who is that directed at? I haven't been looking at the new code at all.

Fyll commented 9 years ago

No one in particular, just generally saying how cleaning up bugs is hard and pointless.

DivFord commented 9 years ago

Well, not pointless exactly...

Fyll commented 9 years ago

Here's my proposal: Singletons: Window, Input, GraphicPool, Game

Object will be a parent to all of Player, Gun, Bullet, and Block, and contain (among other things) a Sprite. Block will be a parent to Prop.

When the update loop in Game is called, it updates all of the positions, and checks if there are any collisions. If there are, it tells the two collidees who they bumped in to (an Object*), then they each do their thing to the other.

When Game calls the draw loop, it goes through the same list of Object*s and draws each one's Sprite in turn. The Sprite will contain a Vector for the separation between the top left corner of the bounding box and the sprite.

DivFord commented 9 years ago

That sounds like it should work.

mspraggs commented 9 years ago

With the move vs update thing, the point is that the interactions between objects are purely based on their position, but they react through changes in velocity/acceleration. So first their velocities/accelerations change, then a second move step is called on them afterwards to actually make them move. If two object have collided, one could react by save moving away from the other.

mspraggs commented 9 years ago

How's the rewriting going Iain?