I am making a simple 2D game in the console in C# as a learning project. However I seem to be unable to come up with a decent design for a collision system.
The resolution of a collision presents the biggest problem for me.
Basically there can be any combination of the following 2 sets of effects:
1. The triggering object or tile is removed;
2. The remote object or tile is removed;
Or nothing can happen - the objects just stop moving(i.e. when both are invulnerable or something).
Any ideas towards that effect would be greatly appreciated.
How to detect a collision and how to respond to it are two totally different concerns and you should separate them.
The simplest way would be to have a virtual method in your base game object responding to collisions:
class GameObject
{
virtual protected void OnCollision(GameObject withObject) { }
}
In your collision detection system, whenever two objects collide, simply raise the collision event on the two objects: object1.OnCollision(object2); and object2.OnCollision(object1).
You will soon realise that this might become a mess at some point and will want to learn about multiple dispatch and how to emulate it on languages that don't support it.
Related
If for instance I have a game which consists of just a single scene, and in that scene I make the user chose between the normal play mode or the tutorial play mode. The game has 4 different objects: a ball, 4 squares and a squarecontroller. In the tutorial mode i want to provide the user with a pointing arrow while pausing the game and continue after the user pressed the object being pointed at. Should I make a script for the normal mode and another one for the tutorial mode, make one script and check if a tutorial boolean is true or false in every function (boolean should be true if user pressed the tutorial button) or do some kind of preprocessing?
In the squarescript for example:
void OnCollisionEnter2D () {
if (isTutorial) {
PauseGame();
arrow.position = GetRelativePosition();
arrow.setActive(true);
} else {
if (canCollide) {
score++;
} else {
GameOver();
}
}
In the ballscript:
void OnMouseDown () {
if (!isTutorial) {
return;
}
ResumeGame();
}
We know nothing of your game so it's hard to answer. But as a rule of thumb: The less you have to type, the better. Also consider what will happen if you need to add new functionality to the game, will you have to go back and change tons in your code?
If so, you are most likely not writing good code.
As an attempt to give a concrete answer I'd say you should make an inheritance, create a class Level and make sub classes Tutorial and FreePlay or similar, that inherits from Level.
Then you can add all "general" functionality in the base class and the specific things goes in the sub classes
By structuring these behaviours inside if statements, it makes the code hard to understand and work with. Imagine what this will look like if you decide you want one of the squares to increase the players score AND show a tutorial arrow.
Split the behaviours into separate objects. For the square it could be something like a TutorialCollisionHandler, ScoreCollisionHandlerand HazardCollisionHandler. Then you can create different squares simply by changing which collision handlers are added to them, you don't even need to write any code!
Now depending on which mode the user picks, you can just use a different mix of squares. The same principle can be used with other tutorial or game specific behaviour.
I'm working on a 2D platformer in c#, as most people are, but I have got a decent start to the project I have a class called Player, I then handle all collision for that player as well as the scrolling of the blocks in the background within the gamescreen class. I have just added another player (as a different class in this case a warrior), but all of my collision is based around the players positions and velocity, how would I change the blocks movement and collision to be around the warrior's velocity and positions instead (without duplicating or creating quite a lot of code).
Thanks for any help Sam.
Inheritance is your friend. You should probably have a base Player class, or even something more low level than that. The base class implements the colision detection and movement code. Your Warrior and other player types should inherit that class and override different parts to change the behavior.
My strategy works approximately like this:
I have a Character class. It contains a HitboxSet. The HitboxSet exposes an active Hitbox. All my collision is done based on Hitbox instances. Depending on what kind of character I need, I pass in different sprites, hitboxes, movements, etc.
The result is a high degree of flexibility, while allowing you to keep your concerns thoroughly separated. This strategy is known as Composition, and is widely considered superior to inheritance based strategies in almost all cases.
The main advantage of this strategy over inheritance is the ability to mix and match components. If, one day, you decide that you need a new projectile that's smaller than a previous one, and moves in a sine pattern, you simply use a new sine movement. You can reuse such things infinitely, in any combination.
You can do something like this with inheritance: a child class can override a method and do something differently. The problem is that you either keep adding new child classes with different combinations and end up with a terrifyingly complex tree, or you limit your options.
In short, if something is naturally going to vary, as it almost certainly will in a game, those variations should be distinct classes that can be combined in different ways rather than mutually exclusive overrides.
I'm trying to detect collision between the characterController and a platform (a rigidBody + boxCollider) in an Unity project.
I know that I can use this function at the characterController object:
void OnControllerColliderHit(ControllerColliderHit hit) {
// [...];
}
But I would strongly rather to detect it in the platform object, in order to try to maintain the code clearer. Something like this:
void OnCollisionEnter(Collision c) {
Debug.Log(c.gameObject.tag);
}
But it is not working! I searched in Unity forums and apparently the only way to detect a collision is to set the boxCollider's property isTrigger as True and using .OnTriggerEnter(Collider c) method instead. However, doing it will cause the player to fall through the platform, which obviously can't happen.
Alright, so my question is: is there another way to do it - whithout setting isTrigger as True - and detecting the collision in the platform object?
Thank you!
The way I handled a similar problem with a platform and a character controller, is by adding a child object to the platform with a trigger collider set to a larger size than the platform itself (think of it like an invisible box surrounding your platform). What this does is allow you to know if your player is going to hit the platform, the direction he's coming from etc. Then it's a simple matter of sending a message to the platform, with an necessary information parentPlatformObject.SendMessage(params)
I would like to suggest something very similar to what Steven Mills suggested, but may make things easier in the long run.
Add a child object to the player, that has a trigger collision box the size of the player (or just around it's feet if that's what you care about), but has a specific layer only for itself. In the project physics settings, make said layer only interact with the platform's layer. This means you won't trigger if this box hits anything else except for the platforms (like the rest of the player). Since the non triggers had not changed, the player and the platform will behave as you expect (just as with Steven's solution) but if you add new types of objects that you wish to land on/hit, and want them to work in a similar manner, you will not need double the prefabs/make 2 objects, just 1 with the correct layer assigned.
Scenario: a game with a board, and several tiles on it. Classes: Board, Tile, Player and of course, Game.
Whenever the player presses a tile, his score gets incremented by 1. Board is instantiated inside of Game, and an array of Tile is instantiated inside of Board. My first option to increment that score easily was to make a public static class with a public static field (Score). Of course, it's rather amateurish. And seemed to break the overall flow of the app.
After some thought, I changed everything to use Events; Tile raises an event when clicked; Board handles that event, and raises another event to the main Game class. Player is instantiated inside of Game; when Game handles the event received from Board, it does a PlayerOne(instance of Player).Score += 1;
Should I just go on ahead and use this flow? Do you have any other architecture/design ideas that would work better? Why would your ideas work better?
I didn't use custom made events intensively before and I feel that the whole event raising another even idea might be a bit wrong. From afar though, it looks like a good flow. And it certainly does the job correctly.
What you described looks like (is) the observer design pattern. The game should 'listen' to events from the board, the board should listen to events from the tiles etc.
You should have provided some code.
Should I just go on ahead and use this flow?
Depends on what the events look like.
Do you have any other architecture/design ideas that would work better?
Publish/Subscribe is an alternative. But the .NET events works fine here.
I didn't use custom made events intensively before and I feel that the whole event raising another even idea might be a bit wrong.
It's fine to keep encapsulation. I would do something like:
class Tile
{
public event EventHandler Clicked = delegate{};
}
class Board
{
private void OnTileClick(object source, EventArgs e)
{
var tile = (Tile)source;
//doSome
var args = new CustomEventArgs();
CustomEvent(this, args);
}
public event EventHandler<CustomEventArgs> SomeEvent = delegate{};
}
public class SomeCustomEventArgs : EventArgs
{
}
The only other possiblity that springs to mind is passing / setting in delegates from higher classes that act as callbacks - so the lower classes can check for a valid delegate and call it without any knowledge of who owns it. If you make it a list of possible delegates, it allow for multiple subscribers all benefitting from that callback.
Having said that, I find your event architecture pretty elegant.
Another way to look at it is that the Board depends on Player to function correctly. How many players are there at any one time and do players get added to and from the board during game time?
If not, you might be able to pass the player(s) to the board on creation and then the board could increment the player score. This works as long as there is no other logic that happens at the Game level which could influence the scoring.
The architecture you seem to have implemented works well for this scenario.
using the observer architecture allows the dependencies you have created through the object relationships to be easily managed.
The observer architecture here will allow you you add or remove players, tiles, boards very easily. If there was a requirement for a 'Game' to now manage multiple boards, then simply adding the object in and subscribing to its exposed events allows you to manage that elegantly. This is because a tile does not need to know that a player exists. The same way a player does not need to know that a game exists - they just do their jobs independently.
Other patterns may create unwanted dependencies, leading to the extra code that would be required to pass the information back up the chain (from tile, to player, to game) - that could very easily result in issues further down the line of your project implementation.
I am relatively new to game development so I decided I wanted to create a hobby project from scratch for both experience and entertainment. The specific game is similar to poker known as Three Card Brag. The game is played in the movie Lock, Stock and Two Smoking Barrels.
I have been reading up on some of the topics on SO regarding game development, though mostly this question. This has helped revamp the original way I was creating the objects.
One particular problem I am having is defining game state. My initial approach was to separate everything (e.g. keeping chip stacks inside a Player class) but after reading the responses to the question I mentioned previously, it seems as though all possible states of the game should be maintained within a GameState object. What I came up with is essentially this:
abstract class CardGameState
{
protected List<Player> _Players;
protected Player _CurrentPlayer;
protected Dictionary<Player, int> _Chips;
protected Dictionary<Player, Hand> _CurrentHand;
protected Dictionary<Player, PlayerStatuses> _PlayerStatus; // PlayerStatuses.InHand, PlayerStatuses.Folded, PlayerStatuses.SittingOut, etc.
/* etc. */
where each CardGameState is modified by some action:
public interface IAction
{
string Name { get; }
CardGameState Apply(CardGameState state);
bool IsLegal(CardGameState state);
}
Now I'm feeling very strongly that this is defeating the purpose of object-oriented programming, because the data specifically related to the player (in this case, his chip stack, hand, and current status) is not encapsulated by the Player object.
On the other hand, if a player were to raise the bet, I would be creating a RaiseAction that implements IAction, but the IAction interface only accepts the current game state, which I don't believe would be ideal if the chip stacks were stored within the Player class.
Basically, my question is: can I have the best of both worlds such that I can have an exact representation of the game state while simultaneously keeping all data related specifically to an object within the game state inside its given object?
In online-games using the command-pattern (your IAction) is the standard, and proven, way to do it. It's not Object Oriented in the sense of the player, but the actions are Object Oriented, so from a purely theoretical point of view its a solid design pattern, I guess. And in practice thats how every successful online game I've seen implements it, but note that action games normally use very small discreet actions/packets, until it practically becomes a stream of sorts.
Edit:
A long time after I answering this, I came back here and realized another solution to this problem is to implement GameState's Players, Decks, etc... as derived from an IState class with an Apply(IAction action) member. This way objects apply actions on themselves, instead of having the application apply actions on objects, this would map actions and state to a visitor-pattern instead of a command pattern. Either solution will work, where visitor has the larger overhead and more encapsulation, while command is the easier solution with less encapsulation.
Seems like you might be Object-orientizing it for Object-orient's sake...
Seems like Bob Martin's classic bowling game problem.
EDIT: -Summary-
Its a long read, but basically, through TDD and refactoring, a bowling scoring application went from a huge cluster with lots of Classes and polymorphism to 20 or 30 elegant lines of code. Why? Because they didn't really need to be there in the first place