C# Delegates and Events Design/Architecture - c#

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.

Related

How to deal with two game modes in the same script?

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.

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.

Should I use an event to notify a class or just use return?

I'm cutting my teeth on events and delegates today and to do so, I have been toying with the idea of experience bars, those progress bars from games. But I have a question about the better way to solve my problem - it could be as simple as bad design. Let me provide you some details.
I have modelled my idea with an ExperienceBar class.
It contains properties:
int StartValue
int CurrentValue
int EndValue
and a method
void UpdateBar(int)
UpdateBar adds the parameter to CurrentValue and then tests to see if it has reached EndValue. If it exceeds the amount, the EndValue increases and the amount continues on. Note that initially in my thinking, it is not concerned with the effects of reaching the maximum amount possible, just that the end value increases and the StartValue is reset to zero.
Another class called Player has a property of class ExperienceBar.
In my little demo, when Player.ExperienceBar.UpdateBar(int) reaches the EndValue it fires an event which is handled by the Player class. It updates the Player.Level property by one.
I've just realised that I could achieve the same thing by just changing UpdateBar(int) to return type "true". This method could be tested by the Player class and when true, Player.Level increases by one.
So my question - which is the best practice way to handle this rather specific circumstance? As a general rule of thumb for these kind of situations, is it better to handle events, or is it better just to keep it simple with the testing of return statements?
PS: I hope I've made this clear as possible, but I can try to clarify if anyone is having trouble. I believe there may be some redundancies already with my idea, but try not to deviate from the question please. I'm kind of aware of them! Thank you :)
Well... To me, events is the good way to do it.
However, if I was to design the application it would be down to one question: Will the ExperienceBars's event when it reaches EndValue ever be used by anyone else than the class calling UpdateBar.
If you are designing a component to be used in many places (which seems to be the goal), the answer to me seems to be an almost certain yes, therefore my answer is use events!
/Victor
In my opinion, there's no best way to do this. There are various ways to implement the class that, depending on how it is going to be used, are a better or worse fit.
Use events when you want to implement the observer pattern for many "clients" or "observers" who need to know the state of an object and need to be alerted when that state changes. this works for the degenerate case where there is only one client, but the caller of the the method that changes the object's state is not the one that needs to know about the change.
Use return values when the state only needs to be known by the caller, there are no other observers of the class. This is simple, and limits the scope of the knowledge of the state of the class to the item that immediately needs to know it.
And finally, do not over-design this. If it only needs to notify the caller, do not implement events. If at some later date the class needs to be "observed" then implement events at that point.
It all depends on the coupling of your components and the flow of your program. The downside to events is that you will increase the complexity of your program, because it is harder to trace exactly what the flow of execution will be when any piece of code can subscribe to your event. The upside is it allows for a more flexible and scalable design, since any piece of code can subscribe to your event.
So here is the thing, if Player is going to be in charge of handling all things related to leveling up, then having a tight coupling between Player and ExperienceBar is ok. Let's say you want to expose an AddIn framework, in that case you probably want to expose leveling up to external plugins, in which case an event makes a lot more sense.
Personally, I would have XP be a part of Player, and have Player expose a LevelUp event, but I don't know if that would be a good idea for you and your framework/domain modeling without seeing your existing code.
I would use events rather than a return value. Why? Two reasons:
What does returning true mean when returning from UpdateBar? That it was updated? That xyz happened? Someone else looking at this (or you, two months down the road) will wonder as well.
What if more than one thing should occur when the limit is reached? Then you have to tie all of the code related to those things (levelling, getting a new item, whatever) into the method that you used to update the bar in the first place.
I would have an event associated with reaching a certain level and then "listeners" for that event that can respond accordingly.
I don't think it makes sense to have Experience bar fire an event - in that case a return value would be fine. It could then call the Player's LevelUp function, which could fire an OnLevelUp event from the Player class, if needed.

Game architecture and design strategy for a multiplayer card game

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

Passing input to a state machine (c#)

I'll try to explain my scenario as best i can;
At each application tick I query the current state of the keyboard and mouse and wrap them in individual classes and data structures. For the keyboard it's an array of my Keys enum (one item for each of the keys that are currently pressed) and for the mouse it's a class containing coordinate delta's and bools for each buttons pressed.
I also have a rudimentary state machine managed via a state manager class which maintains the stack and marshalls the states.
All I want to know is, how best to pass the input (snapshots) to the individual states my app can be in at any one time?
I would like to process as much of the input as possible away from the individual states, so as to reduce repeating logic within the states.
Or would it be better to keep the input snapshots as pure as possible and pass them to the states so they can keep they're input-specific-logic hidden?
Note
This structure is similiar to how I imagine a game would work, and although this application is not a game it does need to be processed as quickly as possible.
Why are you querying the state of the keyboard and mouse with each tick? A much better and traditional solution would be to capture events fired from the keyboard and mouse. That way you only need to update the state when you HAVE to.
If you simply query your keyboard and mouse every tick, I can guarantee you'll run into problems. When you query every tick, you'll find that you miss inputs that occur quickly (within the time domain of a single tick). Imagine a situation where the user presses and releases a key/button between two ticks (it will happen more than you think) - you'll completely miss the input.
Particularly in C#, which is completely geared for input events like this, you should be using events.
In XNA, they do this by making the keyboard class static.
KeyboardState state = Keyboard.GetState();
you can then access the current key state with the above line of code.
You should fire events and capture the arguments. That would be the easiest, and most efficient way to handle this.
class YourClass
{
//data members ...
public void OnKeyboardPress(object sender, EventArgs args)
{
//handle your logic capturing the state here
}
}
//elsewhere
someControl.KeyPress += new KeyPressDelegate(yourClassInstance.OnKeyboardPress);

Categories

Resources