8.8 Tutorials: SmartFoxTris PRO
The source FLA of this example is found under the Examples/AS2/pro_smartFoxTris folder. |
» Introduction
In this article we'll develop a complete turn-based game using server side
extensions. The example will be based on the well known SmartFoxTris game,
a multiplayer version of tic-tac-toe. We have already seen how to build the
game keeping all the application logic on the client side.
This time we'll use a different approach and move all the game logic on the
server side.
What are the advantages? In general, using a server side extensions is a more
flexibile and secure option. Even if SmartFoxServer provides
powerful tools for developing application logic on the client, this approach
can be limiting when your games start getting more complex. Also keeping sensitive
game data on the server side allows overall better security from hacking attempts,
cheating etc...
» The game
The game we're going to develop is based on the tutorial that you can find in
chapter 5.14 of the documentation: a tic-tac-toe game for two players with
support for spectators.
The server side extension that handles the game is going to be dynamically
attached to each game room created, and it will send the game events to the
Flash interface. This way we can finally split the game logic, by moving it
on the server, from the game view which is handled by the Flash client.
» Server side events
Before we analyze the game code, it's a good idea to take a look at the the
events that the extension will handle:
game start | The game begins when 2 players are available in the room | |
game end | The game ends when all board tiles have been filled. The extension will then calculate if there's a winner or if it's a tie | |
game stop | The game is interrupted because one of the players has left the room in the middle of a match | |
spectator enter | A spectator has entered the room. We'll need to send him the current state of the game | |
spectator switch | A spectator was turned into a player. We'll have to check if two players are available, if so a new game can start |
function createRoom(name:String, pwd:String, spec:Number) { hideWindow("newGameWindow") var gameRoom:Object = new Object() gameRoom.name = name gameRoom.password = pwd gameRoom.maxUsers = 2 gameRoom.maxSpectators = spec gameRoom.isGame = true gameRoom.isTemp = true xt = {} xt.name = "tris" xt.script = "sfsTris.as" gameRoom.extension = xt smartfox.createRoom(gameRoom) }
import it.gotoandplay.smartfoxserver.* stop() _global.gameStarted = false // global flag for tracking the game status var extensionName:String = "tris" // Name of the extension that we'll call var win:MovieClip // A movieclip used for dialogue windows var myOpponent:User // My opponent user object var player1Id:Number // Id of player 1 var player1Name:String // Name of player 1 var player2Name:String // Name of player 2 var player2Id:Number // Id of player 2 gamePaused("")
var whoseTurn // keep track of the current turn var board // a 2D array containing the board game data var numPlayers // count the number of players currently inside var users = [] // an array of users var gameStarted // boolean, true if the game has started var currentRoomId // the Id of the room where the extension is running var p1id // userId of player1 var p2id // userId of player2 var moveCount // count the number of moves var endGameResponse // save the final result of the game function init() { numPlayers = 0 gameStarted = false } function destroy() { // Nothing special to do here }
function handleInternalEvent(evt) { evtName = evt.name // Handle a user joining the room if (evtName == "userJoin") { // get the id of the current room if (currentRoomId == undefined) currentRoomId = evt["room"].getId() // Get the user object u = evt["user"] // add this user to our list of local users in this game room // We use the userId number as the key users[u.getUserId()] = u // Handle player entering game // Let's check if the player is not a spectator (playerIndex != -1) if (u.getPlayerIndex() != -1) { numPlayers++ if (u.getPlayerIndex() == 1) p1id = u.getUserId() else p2id = u.getUserId() // If we have two players and the game was not started yet // it's time to start it now! if(numPlayers == 2 && !gameStarted) startGame() } else { // If a spectator enters the room // we have to update him sending the current board status updateSpectator(u) if (endGameResponse != null) _server.sendResponse(endGameResponse, currentRoomId, null, [u]) } } // Handle a user leaving the room or a user disconnection else if (evtName == "userExit" || evtName == "userLost") { // get the user id var uId = evt["userId"] // get the playerId of the user we have lost var oldPid = evt["oldPlayerIndex"] var u = users[uId] // Let's remove the player from the list delete users[uId] // If the user we have lost was playing // we stop the game and tell everyone if (oldPid > 0) { numPlayers-- gameStarted = false if(numPlayers > 0) { var res = {} res._cmd = "stop" res.n = u.getName() _server.sendResponse(res, currentRoomId, null, users) } } } // Handle a spectator switching to a player else if (evtName == "spectatorSwitched") { if (!gameStarted && evt["playerIndex"] > 0) { numPlayers++ // Update the playerId this["p" + evt["playerIndex"] + "id"] = evt["user"].getUserId() // If we now have 2 players the game should be started if(numPlayers == 2) startGame() } } }
function updateSpectator(user) { var res = {} res._cmd = "specStatus" res.t = whoseTurn res.status = gameStarted res.board = board if (users[p1id] != undefined) { res.p1n = users[p1id].getName() res.p1i = p1id } else res.p1n = " " if (users[p2id] != undefined) { res.p2n = users[p2id].getName() res.p2i = p2id } else res.p2n = " " _server.sendResponse(res, currentRoomId, null, [user]) }
doc index | next » |