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?

Fyll commented 9 years ago

I've just finished implementing bounding boxes, so you hopefully won't need to do anything extra there. The numbers I used were just made up, so feel free to change them (they're in PropList.hpp).

Otherwise, yeah, this seems like it would be really nice.

mspraggs commented 9 years ago

I did wonder whether we could use the existing Position class, but call it something like Object. We could then base all entities that appear on the screen upon this class via inheritance. If we gave a collision radius to this object, then for each Object instance, we pass the list of Objects to some member function, update say, then each object would adjust it's position to account for the Objects nearby.

Something like:

// Init object list. E.g. std::vector<std::unique_ptr<Object> > objects = get_objects
for (auto& object_ptr : objects)
  object_ptr->update(objects)

for (auto& object_ptr : objects)
  Window::instance().draw(object_ptr, sprite);
DivFord commented 9 years ago

How would that handle collision aspects other than position? Bullet impacts, for example.

mspraggs commented 9 years ago

Well everything drawn to the screen would be an instance of Object of one of it's child classes, so Bullet would just inherit Object.

DivFord commented 9 years ago

Ok, that seems better. It's going to mean a major rework to pretty much all the source files though. How should we coordinate this?

Fyll commented 9 years ago

Hmm. I like the idea, but I'd say it should be separate to Position. This way, it's position and dimensions can be Position instances, so both can move and change easily.

Fyll commented 9 years ago

Just nominate someone, and everyone else keep away from the code. That seems to be the simplest way.

mspraggs commented 9 years ago

I suppose I was considering it from the point of view that position only makes sense in the context of entities that actually have a position, and Position seems to encode more information than simply the coordinates of something, as it has velocity and acceleration as well.

Fyll commented 9 years ago

That's for if the object wants to move. This can also be use to scale the object's dimensions (if that's ever necessary) as dim is also a position.

DivFord commented 9 years ago

I think we should get rid of position, and instead have GameEntity (containing the position and bounds) with DynamicGameEntity deriving from that (adding velocity and acceleration). Then block can derive from game entity, while prop, player and projectile derive from DynamicGameEntity.

DivFord commented 9 years ago

I'm going to work on art for a while, so one of you two can handle this.

Fyll commented 9 years ago

Would the Sprite then be part of GameEntity? It'd need to know the pos and dim, which is what GameEntity is going to contain.

mspraggs commented 9 years ago

Position has many of the same properties as what you describe, and is a good starting point, I just think it makes more sense to refer to it as an object, then use inheritance to subclass it.

Here's a brief sketch of a possible class layout:

class Object // or GameEntity or some such
{
public:
  Object(const Vector& pos, const Vector& vel);
  virtual ~Object() { }

  virtual void update(/* Some list of objects */) { }
  virtual void destroy(); // Here we can destroy  ourself and any objects we have as children

  void setVelocity(const Vector& vel);
  void setAcceleration(const Vector& acc);

private:
  Vector position_;
  Vector velocity_;
  Vector acceleration_;
  float collisionRadius_;
  int index_;

  std::vector<Object*> children_; // Used to ensure children are destroyed, maybe?
};

I think if we could somehow set things so that you could pass each object into a draw function, which would look up the index of the object and fetch the sprite, then that way you can achieve better encapsulation of the graphics code.

DivFord commented 9 years ago

Agreed.

@Fyll : Sprite needs to know the pos, which we can presumably just pass as a vector, but it makes sense for sprite dimensions to be independent from gameplay dimension, so I don't think it needs to link to Matt's Object class.

mspraggs commented 9 years ago

I think it's really important that the only thing that can change GameEntity's position is its own update method. This way you simply have an entity that reacts to the objects around it with either a change in velocity or acceleration, then the position is updated automatically.

Actually it's going to be important to create a seperate move function that is called after update. If the position is changed by update, then when the next object in the list looks through to find it's neighbours, it'll encounter objects that have moved within the update step.

Fyll commented 9 years ago

The trouble with that is that the sprites are all on different sheets.

It may work if you have two indices, one the texture index, and the other the yIndex for things like props.

Also, I've tweaked Position a bit so gravity is separate to the normal acceleration, and acceleration also decays. From this, jumping and running and so on are done by supplying an acceleration rather than a velocity. It leads to smoother movement I feel, so we should probably keep something similar here.

@DivFord : Fair enough. The object dimensions are basically the topLeft and bottomRight positions at the moment.

DivFord commented 9 years ago

My comment may not have shown up, but I set jumping back to a velocity change. Otherwise it feels like a rocket taking off.

Fyll commented 9 years ago

@mspraggs : But wasn't part of the reason for doing this so that things could push one another? If they can't move each other, how will they accomplish this?

DivFord commented 9 years ago

They can move one another, they just have to do it by applying acceleration.

Fyll commented 9 years ago

One of the comments someone made during the final round of playing was that the jumping was too jarring. That's what made me think of changing it to an acceleration.

mspraggs commented 9 years ago

How about this? When you create an object, you know it's type and so forth. What you then do is to get it's index, and register that unique index with some sprite, so that way the graphics code just needs the index to look up the sprite.

@DivFord or indeed velocity

Fyll commented 9 years ago

GFX_POOL does that with the textures already.

mspraggs commented 9 years ago

Yes, but the point is that the actual code to call SDL to render the sprite to the screen is separated from the class that encodes the behaviour of the objects in the game. That way things are encapsulated better and it's easier to maintain.

EDIT: Then you're literally just passing an integer and a set of coordinates to the graphics system.

Fyll commented 9 years ago

Sprite contains the texture ID and performs the call to SDL. Position handles the manipulation and behaviour of the object in game. I don't see how what you're suggesting is different to this (in this respect).

DivFord commented 9 years ago

So, in Unity they have two of force modes, one that applies instant force, another that applies continuous force. Is it worth encapsulating velocity and acceleration, and instead accessing them through Force() and Impulse() ?

I think Sprite is fine as is, except referencing position.

Fyll commented 9 years ago

It has to reference position, as it otherwise doesn't know where to draw the sprite.

Forces would be the ideal way to do it (you're talking to two physicists :P), they just seemed like too much hassle during the Game Jam.

DivFord commented 9 years ago

That's what I'm saying, the sprite doesn't need all the velocity and acceleration aspects, all it needs is a position vector, not the position class. All sprite position should be is x and y.

mspraggs commented 9 years ago

@Fyll Ah I see what you're saying now. Yes, Position and Sprite do contain the sort of thing I was suggesting. However, what we currently have is a system where classes own instances of Sprite and Position. What I'm suggesting is to have Player, say, be a subclass of Position/Entity/Object, without a Sprite member variable. This way the Player instance has zero knowledge of what's going on with the graphics, which frees us from thinking about this when writing the game mechanics.

The other issue is that the graphical coordinates and game coordinates are currently one and the same. Whilst this isn't a big deal as we're working in 2D, it would be nice to be able to pass the game coordinates to the graphics engine, which would transform them into graphical coordinates before plotting them.

DivFord commented 9 years ago

Are they the same? I thought gameplay was in screenspace but graphics was in pixels.

Fyll commented 9 years ago

So, Game would contain an array of Sprites, and each Object would contain it's Sprite's index, the Game draws all of the Sprites itself, thus removing the Sprites from Object? That makes sense, but seems to be a roundabout way of doing things.

What about cases where the Sprite needs to be moved manually (like with the gate. It's not animated, it just switches its frame when you stop standing underneath it)?

I'm not sure I understand the bit about the graphics engine though.

@DivFord : They're both screenspace. EDIT: The only things in pixels are the initial window size, and the images as they're loaded up.

DivFord commented 9 years ago

If we have the sprite index, can we use that to call an animation function on the sprite?

Fyll commented 9 years ago

What do you mean, an animation function?

DivFord commented 9 years ago

Say, the sprite class has SetFrame(), AnimPlay(), AnimPause(), stuff like that.

mspraggs commented 9 years ago

Sorry, I perhaps I got confused about the coordinates.

Ok, how about this: there's also a base view class. Something that handles the drawing of an object to the screen. The base could just be drawing a sprite to at the given coordinates. Then you subclass it when you need additional functionality, such as an animation for change of state. The Game class would then link each object to it's respective view in some way.

mspraggs commented 9 years ago

So I suppose Sprite is akin to what I'm talking about at the moment, but it could potentially be subclassed to handle multiple sprites and the animation between them. EDIT: As David's just suggested :-P

DivFord commented 9 years ago

So, ideally we would have sprite subclasses for player, blocks, and props, right? They all animate (or not) in slightly different ways.

Fyll commented 9 years ago

I still don't see what the point of this is. Sprite already handles animation (not very elegantly mind, but that can be tidied up). I'm not sure how the various things you're proposing are any better.

The Object idea I can understand and get behind.

@DivFord : Do they?

DivFord commented 9 years ago

Yeah, Tilesets use an x coordinate based on tiling (and when I implement internal corners, I'm going to need that to affect y coordinate as well). Props have y coordinates based on prop, and x coordinates based on frame. Player (and presumably other units if we ever add them - we may want to avoid a naming conflict there) has different animation cycles at different y coords, and different frames at each x coord.

mspraggs commented 9 years ago

I think it would give us some flexibility if we later wanted to add behaviour to certain objects over others, but then needed to reflect this in the graphics. Say we subclass Object into Gate. Gate could have a boolean open. Sprite could then be subclassed into GateSprite, which would monitor the variation in Gate.open, and act accordingly.

Fyll commented 9 years ago

At the moment, they each handle their own sprite manipulation, which I can understand goes against the splitting of graphics and gameplay, but I don't really see how it's too much of a problem.

On that note actually, the Position class only updates the movement now, so I don't see why it needs to be removed.

But an open gate is just a solid prop to the closed gate's non-solid prop. There already is a boolean handling that.

DivFord commented 9 years ago

@mspraggs To be honest, that's just the lack of encapsulation the other way round, so there's no real benefit. I would rather gameplay call anim functions than graphics query gameplay.

mspraggs commented 9 years ago

Perhaps I'm overcomplicating things, I'm not sure. I'm just trying to think of a design pattern we can settle on so the code is well organised. I'll do some reading.

Fyll commented 9 years ago

Actually, if we're going to be doing some big changes to the underlying system, does someone want to back it up on here (or whatever) in case something goes wrong?

DivFord commented 9 years ago

Good point. Matt, can you make a branch?

mspraggs commented 9 years ago

I can do, yes. Branching only makes sense though if you want to keep updating the existing branch while you're working on the new branch. Are we planning on doing that? Otherwise I could tag the current commit as say version 0.0-1 or something, so it'd be easy to find if we want to revert.

DivFord commented 9 years ago

Yes, that second option would be better.

mspraggs commented 9 years ago

Great, I'll do that :-)

mspraggs commented 9 years ago

Can everyone confirm we're all committed and pushed, before I do this.

DivFord commented 9 years ago

I have a new tile set, but I haven't implemented it. I'll do that once all this changing is done.

Fyll commented 9 years ago

I'm all pushed.