Game architecture and design strategy for a multiplayer card game - c#

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

Related

How to combine objects into one list, when they are inherited from one interface?

I'm learning C# and trying to do simple object oriented exercise.
I have three weapon classes, "Bow,dagger,Spear", so I made one interface and inherited from this interface IWeapon.
Now user must choose one of the weapon, so I want to make Collection of weapons and I'm trying to make list of IWeapons, is it correct way? Isn't it bad practice to make list type of IWeapon ? Because of, I know that Interfaces are like a contracts, and I think it's a bad idea to make List with Interface type. One way is to change interface to an abstract class, but I want to use Interface.
private static List<IWeapon> weapons = new List<IWeapon>();
Is it correct way or not ?
The only problem with your solution is that static members should be thread-safe. It's like a convention among C# developers. So either change it to a non-static and, preferrably, readonly:
private readonly List<IWeapon> weapons = new List<IWeapon>();
Or use a thread-safe collection:
private static ConcurrentBag<IWeapon> weapons = new ConcurrentBag<IWeapon>();
I have two thoughts on this:
I can easily imagine a situation where one would want to use a collection of a particular interface. For example, if you were writing a download queue. You would have weapons and shields and players and villages which all implement an IDownloadableThing interface. Your queue code would have a collection of IDownloadableThings because it doesn't care what its actually downloading, it just cares that that thing know what its URL or file path or whatever is.
I'm a little wary of developer edicts. There are good ideas and traps you should be aware of in any language, but context can change everything. When you are trying to figure out if 'Weapon' should be an abstract class, ask yourself a couple things. Should a class implementing Weapon also be allowed to be a Shield? If locking down multiple inheritance is important, then abstract classes are the way to do that. Will there be a lot or any common behavior that classes implementing 'Weapon' will want to share? For example, is there a CalculateDamage() method that's basically identical between all 'Weapon' implementations. Once you have answers to what a class of interface's purpose is, then it'll be easier to choose to violate a development guideline because the situation requires it or re-think your approach.
There's nothing wrong with using interfaces as values for lists.
However, this may not be appropriate to your specific case. You said you'd like the player to pick from a list of weapons. Now consider the follwing scenarios:
You have a single player in your game, and he chose a single weapon. You have created a whole list worth of weapon instances that no one will ever need or use. This just wastes memory.
You have multiple players in the game, and they both choose the same weapon. This could be even worse. If you assign the weapons like this: player.Weapon = weapons[1], then both players will have the same instance of the weapon. If one user assings buffs to his weapons, or maybe if the weapon degrades or breaks, both the players weapons will be affected, since it is, in fact, the same weapon. Think of it like this, both you and I would like a chocolate cake. The store can either give us both the same piece of cake, in this case, if you eat it, I will have none. Or they can bake us both new cakes, so each of us can have his own.
The appropriate solution in this case is to save the types of weapons and present these to the player. Then create a new weapon instance according to the player's choice.
There are several different ways to do this, the simplest of which is to create an enum with the weapon types and present these to the player.
So instead of the list, you can have:
public enum WeaponType
{
Bow,
Dagger,
Spear
}
And now you need to create the instance of the weapon the player chose:
public IWeapon CreateWeapon(WeaponType weaponType)
{
switch(weaponType)
{
case WeaponType.Bow:
// Create Bow...
case WeaponType.Dagger:
// Create Dagger...
case WeaponType.Spear:
// Create Spear...
}
}
This is the basis to the Factory design pattern. I would highly recommend you to take a look at it. Here's a good place to start: http://www.dofactory.com/net/factory-method-design-pattern

2D Platformer multiple classes without code duplication

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.

C# Delegates and Events Design/Architecture

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.

2D collision resolution system

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.

How to properly create Game Objects

I am making sims like game and right now I am trying to figure out how I will structure my objects.
Right now I am thinking to create a class called GameObject, the psuedo is below
public class GameObject {
name:String
width:int
height:int
}
This way I could create objects like bushes, trees, and buildings. But then I began to think. what if I wanted to create multiple buildings and trees of the same type ?? I would have to keep making instances of GameObject and giving it a new name and height and width. The properties would have to be the same values in order for me to duplicate one object. That seems a little tedious. Then I figure , maybe that isnt the right way to go. So I was thinking, I would have to extend GameObject like below
public class Tree extends GameObject{
birdHouse:Boolean
}
public class Building extends GameObject{
packingGarage:Boolean
stories:Number
}
public class House extends GameObject{
garage:Boolean
stories:Number
}
Now this way, I can just create multiple instances of house, or tree, without creating properties that specify that it is indeed a house or tree. This seems more logical, but at the same time it seems it allocates more memory because I am creating more classes.
I just need to know what the best practices for dealing with objects like this. If anyone can help me out with this. also if you know any resources for best practices of reducing loading on games or any application at that. I also want to use Interfaces. the second concept seems more reasonable and I was thinking about having the parent implement a interface like below
public class GameObject implement IGameObject {
name:String
width:int
height:int
}
Now this way I can create a class that has a method that loosely accept accepts any type that inherits GameObject.
Selector.loadObject(gObject:IGameObject);
Depending on what type it is (i.e tree, building, house) I can use a case statement to figure out which type it is and evaluate it accordingly.
I also created a Tile Class that will pass through the loadObject method. It also will be a child of the GameOject class. if the case statement finds that it is type Tile, it will highlight whatever Tile depending on what tile my mouse is over.
My second question is if a class inherits a class that implements a interface, is that class child class considered to be a IGameObject as well. or does it have to implement that interface directly.
does all this sound like I am going in the right directions lol, as far as organization is concerned.
Thanks for all of your help, thanks guys!
One thing you could think about is using Composition of objects over inheritance. This sort of goes along with the Flyweight answer. Rather than having all your GameObjects inherit properties from GameObject; instead, have each game object just have a reference or pointer to an object or interface that has the properties it needs. For example, all your game objects probably have some sort of "size" property - rather than inheriting this from a base class, just have each game object reference or point to a "Size" class, so that the size object can potentially be shared among similar objects.
You should look into the Flyweight pattern
From wikipedia:
Flyweight is a software design
pattern. A flyweight is an object that
minimizes memory use by sharing as
much data as possible with other
similar objects; it is a way to use
objects in large numbers when a simple
repeated representation would use an
unacceptable amount of memory.
As for your second question, the answer is yes. All Subclasses of a Class can be said to implement all interfaces that the parent class implements.
This seems more logical, but at the
same time it seems it allocates more
memory because I am creating more
classes.
Creating new classes doesn't use a significant amount of memory. It's creating instances that uses memory - but again, the amount will be negligible compared to the memory used by loading in your graphics etc. Don't worry about memory. Your only concern at this stage should be good code organisation.
You should have separate classes when they have different behaviour. If they have the same behaviour but different properties, then you use the same class and set the properties accordingly.
In this case, you don't appear to have significantly different behaviour, but if separating it into Tree, Building, and House makes life easier for you when managing which items can be included in others etc, do it.

Categories

Resources