I'm having trouble wrapping my head around this, and I apologize if this question isn't very clear. But I'll try.
For the sake of this post, I'll simply my problem a bit. I'm writing a game of multiplayer Tic Tac Toe (not really, but it's close enough to count). There are only three actions any given player can make:
The current player is allowed to place a marker.
Either player is allowed to request an Undo. The other player can choose to allow or deny the request.
Either player is allowed to Resign.
I wrote a GameEngine class that keeps track of the game board, checks the validity of marker placement, and win conditions. I would like to write Player classes, such as TerminalPlayer (to play the game from a command line), NetworkPlayer (to accept moves from a server), and ArtificialPlayer (to make it play offline).
My problem is this: given that each Player can send commands at any time (placeMarker, requestUndo, Resign), how do I structure this game?
I can think of solutions that might work (put each player in a thread, and have the GameEngine monitor requests), but everything I come up with is so clunky and awkward. I feel like there should be a good pattern for this, but I can't find it.
Specifically, can you answer:
What is the pattern that solves this problem? Does one exist, or is this more simple than I'm making it?
If a Boost library (or something like it) has solved this problem elegantly, what's the name of that library?
Seems like a simple state machine would let you manage the game.
When some input is recieved to the server, you need to validate, based on the game rules, and decide weather to execute the input or discard it. As mentioned by Esteban, the game state would progress as a state machine, including state on which player is currently expected to take a turn.
Different pieces of input will be allowed at different states of the game,
If the possible states are:
Player 1 Turn
Player 2 Turn
Player 1 Request Pending
Player 2 Request Pending
Game Over
Then you have a list of actions, when they are allowed, and how they change the state.
Player 1 make turn:
Allowed states: Player 1 turn
New State: Player 2 turn
Player 1 Request Undo:
Allowed states: Player 1 turn
New State: Player 1 Request Pending
Player 2 Deny Request:
Allowed states: Player 1 request pending
New State: Player 1 Turn
Player 2 Resign:
Allowed states: ALL
New State: Game Over
If a player makes a move out of turn, simply discard it.
The concept you are looking for is called a game loop. The term is fairly Googleable for how generic it sounds. It is a simple forever loop that checks for input, steps game state and redraws the screen. For the network player I would probably run that in a separate thread and have it post events that the main game loop picks up.
Related
I have a small Clojure game (think Snake but multiplayer; if you hit another snake, you lose) running over WebSockets - logic is in the Clojure backend, rendering is in the browser.
Every "turn" of the game takes 100ms, during which the game steps, which involves 1) calculating the next state of the game, 2) sending the game state to every player over WebSockets 3) checking if the game is over, and if not 4) sleeping for 100ms minus the time it took to do steps 1-3, and 5) looping back to 1.
There is a global atom games, which is a map from a UUID to a game map (has player coordinates, directions, etc.). When a player presses an arrow key, the browser sends a message containing the game's UUID, the player's UUID, and the move. On receiving that message (independent of the game loop), the server directly modifies the games atom to update its to-moves map to say that the player with some UUID wants to turn :right. Step 1) above takes the to-moves list and changes each players' directions accordingly before moving each player forward (every 100ms). This method works.
I learned about core.async (go, channels, parking, etc.) but I'm not sure if it would be applicable in this case. I was originally thinking that instead of a :to-moves map as part of the Game, I have a buffered channel instead. Then when a player submits a move I can do (>!! ch [<player-uuid> :left]), for example. And when I calculate the next game, I can get the moves with (
This is more of a learning project, so if core.async will pretty much be the same as my current method that's fine. But is it applicable in the first place?
Thanks.
Firstly, I'm assuming that when you say "running over websockets" you mean that you're running ClojureScript in the browser and that you want to use core.async in the browser to decouple your websocket communication implementation from the event generation.
In that case, core.async channels is a very neat fit since you can setup your websocket as a consumer on a channel and pass that to all the pieces like the keyboard event listeners to write to.
It also lets you then setup an outgoing channel that you can cleanly hook up to your game state and make the changes received from the server into the atom.
The point of it is to introduce the decoupling so that as long as you implement some kind of thing that gives you an input and output channel, it'll work. You could replace the websocket implementation with a dummy test or replace the events and game state management with simple listeners and emitters so you have a nice seam to isolate bugs with.
I wish to implement a simple multiplayer Hangman game with the rule slightly bended.
Rule:
All the players have to guess the alphabets in the word at the same time. Whoever player guesses a correct alphabet gets a point, and the player who puts the ending alphabet gets bonus points.
This will be about speed. The faster correct guess gets you ahead of others.
I intend to have a Qt/QML based GUI and the programming language will be C++. Platform will be Linux.
I am thinking I'll need:
- One thread for handling user typing.
- Second thread for parallel display of what other players are typing.
- Third thread for parallel display of scores of every player on every player's screen.
Do I need these 3 threads or I am barking the wrong tree?
It sounds like you're planning to have this game communicating over the network, where each player is using their own computers and running a copy of the program.
You should only need one thread for the application, but you might decided that more threads will make it easier on you.
You can easily connect signals from player's typing (either use an event handler, or connect your widget's "editingDone" signal.) to the appropriate logic for updating the scores and showing the other player's answers.
I think you'll run into the most problems with deciding on how to properly network the application to all instances, assuming that that's what you're trying to do. But the Qt network stack can allow you to do asynchronous network communication without having to manually create new threads.
At the moment I am writing a turn based game for the iOS platform. The client is written in Objective-C with CocoaTouch, and the server is written in C++ for the Ubuntu Server OS. The server is connected to a MySQL database, in which it stores user & game data.
Right now I wish to implement a time-per-turn restriction, and this has to be done on the server side. When a user takes a turn, the next user will have a maximum of 24 hours to answer, otherwise I want the game to skip this user's turn and move on to the next player. I have some ideas about how to do this, but I am not sure if they are any good. What I've been thinking of is storing the date&time of the last turn taken as an entity related to the Game table on my SQL database. Then I'm thinking of launching a thread on the server which runs until termination, and looks up current time minus every game's last turn, say every minute or so. If it's been more than 24hrs since the last turn was taken, this thread allows the next player in the queue to take their turn, and skips the lazy player.
Does it sound over-complicated? Is there another, more simple way to do this? I know it's been done in many games before, I just don't know how. Thanks in advance!
I don't think you need any threads or background processes at all in this case.
What I see here is a simple algorithm:
When a user logs in to the game/match - check up the last turn ending time in the database,
If the elapsed time from the last turn ending time is greater than 24h, get the current time, substract the time from the database (obviously you need to convert both times into hours) and divide it by 24,
If the division yelds an odd number, it's the turn of the other player (player A)
If the division yelds an even number, it's the turn of the player B.
Set the database time to databaseTime+division*24
This algorithm can skip multiple turns. When player A finishes his move, and 48h passed, it's players B turn.
You probably just want a background process that has a schedule of "next actions" to take, a sort of priority queue you can work through as the events should be triggered.
A single process can handle a lot of independent games if you design the server properly. The architecture would pick up an event, load any associated data, dispatch accordingly, and then go back to waiting for new events.
C++ does have frameworks for this, but you could prototype it in NodeJS or Python's Twisted really quickly.
Please look at the reactor pattern (boost.asio, ACE). These frameworks are asynchronous, use an event-driven model and require no threads. Below is pseudo code on how you can solve it:
reactor.addTCPListener(acceptSock(), Handler::AcceptSock) // calls AcceptSock when accepting a new TCP connection
rector.addTCPListener(clientSock, Handler::ClientData) // calls ClientData when user is sending the server game stats (its move, status etc)
.
.
.
later on somewhere
.
.
.
for(set<Game>::Iterator it = games.begin(); it != games.end(); ++it) {
(it*)->checkTurn() // this call can be responsible for checking the timestamps from the ClientData function
}
Summary:
With the reactor pattern you will be able to have a non-blocking server that can do cleanup tasks when it is not handling IO. That cleanup can be comparing timestamps to switch/pass turns.
I'm currently trying to write (as a part of "simple multiplayer game as an example of real time client-server application" assignment) multiplayer game server for simple fast-paced game for few players (less than 20 i think). I'm using TCP sockets for packets that require guaranteed delivery (ie.: chat messages, login and logout requests, ping packets, etc) and UDP for everything that does not necessarily need to be delivered since only the last packet that got through is important (ie.: user input, game world and objects updates, etc).
I should mention here, how my game world looks like. Every object server side has its id, role and owner members. Id is basically identifier for clients so, once I send them object updates they know which object to update on their side. Owner is information about object owner, ie.: player which controls the actor. I use it to remove orphaned objects once player loses connection / logs out. Most objects however has this value set to Server. And finally role determines whether object is important to clients. This can be set to ServerSide (for objects that do not need to be replicated to clients as they are only used in server side game state calculation), RelevantToOwner (this objects get replicated only to their owner, ie.: player private inventory does not need to be replicated to everyone), RelevantToList (object gets replicated to all players from list, ie.: i have list of players to whom the object is visible and i replicate only to them) and RelevantToAll (replicate to everyone).
When user sends login packet I check whether I have free slot and if yes, then I replicate world to him (send current world state - every object that does not have role set as ServerSide or RelevantToList - unless of course the client is on the list for that object).
Then after each iteration of server game state update loop I send exactly same thing - whole world state.
When users send logout packet I remove him from logged in clients, free slot, and remove all orphaned objects from game world (objects that had this user as owner).
Here are my questions:
Is this model suitable for real-time multiplayer game or am I doing it horribly wrong?
Is there a way to reduce amount of packets sent after the initial world replication (ie.: updating only objects which state has changed since last iteration. I've given it a thought and so far I've encountered one huge problem with this approach - if UDP packet from previous iteration is lost and state of the object haven't changed in subsequent iterations, the object will not be updated on the player side.)
How can i pack multiple object updates into one packet (I'm currently sending one object / packet which is inefficient and also probably horribly wrong.
Could someone point me to some working example (source would be nice) of simple Client/Server game so I can see how professionals do it? C++ or C would be nice but Java / C# / Python are fine too.
This depends a lot so much on what type of game you're talking about - example: Im doing roughly the same thing in a text based muck game.. My updates are simple, on arrival, send room details. On change, send messages to say people/object came/went. Done.
UDP is how most online games work just because they need to deal ith 100k+ connectios. UDP loss is often why players "warp" in game. If you're doing 20 people and you can guarentee that, then sticking with tcp will help.
do you need to send them the whole world? Is your world not made of zones/rooms. Normally you send the smaller area. It also depends on how much data on the objects within that you should send, for example. If a player has an inventory, no point sending that to all the other players unless they specifically ask for it - items worn (if a visual game then yes you need to or it draws them wrong)
Just because we have much faster connections these days doesnt mean we shouldnt take into consideration some people dont. You should try and send updates only and have the client maintain its own state, and then, when you change zones, and reload the area, you ensure sync.
To pack object changes in a packet, most likely Im guessing its location changes, eg co-ordinates, and availability, eg, person picks up item. Have an upate structure, item_id, update_type, update_values[], then you can send a chunk of updates.
Are you after text based or more mmorg type? text based I can say google tinymuck, or tinymush, tinymud, there are plenty, graphics ones? thats harder, you could lookup some of the old EQ code and WoW emulators maybe..
I have writing a small shooting game in cocos2d. Winning the game is to eliminate all the 10 enemies. After that end screen comes showing 'You Won' and 'Play Again'. If I go for 'Play Again' option the game is starting from where I need. But, the problem is that the game is continuing from previously ended state.
I mean it is not starting from enemy 1 again instead it is just showing the end of 10 enemy.
I think I have to reset all the values before pushing the scene. But should I reset all the values I have used or there is any other way ?
Thank You.
Resetting the state seems a logical choice.
It would probably make for cleaner code if you re-factor so all your game state related information is held in one instance of a GameState object. Then it could have a method reset that puts values back as you want them.