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 » |