var c = require("./ttConstants.js");
var GridBoard = require("./grid_board.js");
var ArrayBoard = require('./array_board.js');
var PIXI = require("../../lib/pixi/pixi.js");
var Component = require("./component");
var inherits = require('util').inherits;
/**
* The View class
* @constructor
* @param {Game} game - the game state
* @param {TurnMap} turnMap - the state machine
* @extends {Component}
*/
function View(game, turnMap) {
Component.call(this);
this.game = game;
this.turnMap = turnMap;
this.turnMap.updateState("start");
this.tokenViews = [];
this.tileViews = [];
this.boardView = new PIXI.Graphics();
this.stage = new PIXI.Container();
this.renderer = PIXI.autoDetectRenderer(c.canvasWidth, c.canvasHeight,
{ transparent: true });
document.body.appendChild(this.renderer.view);
if (game.board instanceof GridBoard) {
for (var i = 0; i < this.game.board.height; i++) {
this.tileViews[i] = [];
}
}
};
inherits(View, Component);
/**
* Draw the board for the given board type
* @returns {void}
*/
View.prototype.drawBoard = function() {
if (this.game.board instanceof GridBoard)
this.drawGridBoard();
else if (this.game.board instanceof ArrayBoard) {
this.drawArrayBoard();
}
/* todo:
else if (this.game.board instanceof GraphBoard)
this.drawGraphBoard();
else
do nothing and defer drawing to user?
*/
};
/**
* Draw the grid board type
* @returns {void}
*/
View.prototype.drawGridBoard = function() {
this.boardView.x = c.boardStartX;
this.boardView.y = c.boardStartY;
this.boardView.beginFill(c.blueColor, 1);
this.boardView.drawRect(0, 0, c.boardWidth, c.boardHeight);
this.stage.addChild(this.boardView);
this.drawTiles();
this.drawTokens();
this.drawMessage();
this.animate();
};
/**
* Draw the array board type
* @returns {void}
*/
View.prototype.drawArrayBoard = function() {
this.boardView.x = c.boardStartX;
this.boardView.y = c.boardStartY;
this.boardView.beginFill(c.blueColor, 1);
this.boardView.drawRect(0, 0, c.boardWidth, c.boardHeight);
this.stage.addChild(this.boardView);
this.drawArrayTiles();
this.drawTokens();
this.drawMessage();
this.animate();
};
/**
* draw the tiles for an Array Board
* @returns {void}
*/
View.prototype.drawArrayTiles = function() {
var tileWidth = c.boardWidth / this.game.board.width;
var tileHeight = c.boardHeight / this.game.board.height;
var tileNum = 0;
for (var x = 0; x < this.game.board.width; x++) {
tileNum = this.createTileView(tileNum, x * tileWidth, 0, tileWidth, tileHeight);
}
for (var y = 1; y < this.game.board.height; y++) {
tileNum = this.createTileView(tileNum, c.boardWidth - tileWidth, y * tileHeight, tileWidth, tileHeight);
}
for (var x = this.game.board.width - 2; x >= 0; x--) {
tileNum = this.createTileView(tileNum, x * tileWidth, c.boardHeight - tileHeight, tileWidth, tileHeight);
}
for (var y = this.game.board.height - 2; y > 0; y--) {
tileNum = this.createTileView(tileNum, 0, y * tileHeight, tileWidth, tileHeight);
}
};
/**
* Create a view for a tile, place it at the right location
* @param {int} tileNum - index of the tile on the board
* @param {int} x - x location of the tile
* @param {int} y - y location of the tile
* @param {int} width - width of the tile
* @param {int} height - height of the tile
* @returns {PIXI.Graphics} tileView
*/
View.prototype.createTileView = function(tileNum, x, y, width, height) {
var tile = this.game.board.getTile(tileNum);
var tileView = this.drawTile(tile, {width: width, height: height});
tileView.x = x;
tileView.y = y;
this.tileViews[tileNum] = tileView;
this.boardView.addChild(tileView);
return tileNum + 1;
};
// todo
View.prototype.drawGraphBoard = function() {
};
/**
* Draw a single tile
* Override this method in your subclass to customize the board
* @param {Tile} tile - the tile model object
* @param {Dictionary} size - The width and height for the tile
* @returns {PIXI.Graphics} tileView
*/
View.prototype.drawTile = function(tile, size) {
console.log("Using default drawTile()");
var tileView = new PIXI.Graphics();
tileView.lineStyle(1, 0, 1);
tileView.beginFill(tile.color, 1);
tileView.drawRect(0, 0, size.width, size.height);
return tileView;
};
/**
* Draw tile for the grid board
* @returns {void}
*/
View.prototype.drawTiles = function() {
var tileWidth = c.boardWidth / this.game.board.tiles[0].length;
var tileHeight = c.boardHeight / this.game.board.tiles.length;
var y_pos = c.boardHeight;
var x_pos = 0;
for (var y = 0; y < this.game.board.tiles.length; y++) {
x_pos = 0;
y_pos -= tileHeight;
for (var x = 0; x < this.game.board.tiles[0].length; x++) {
var tile = this.game.board.getTile(x, y);
var tileView = this.drawTile(tile, {width: tileWidth, height:tileHeight});
tileView.x = x_pos;
tileView.y = y_pos;
if (this.game.moveType == c.moveTypeManual || this.game.moveType == c.moveTypePlaceToken) {
tileView.interactive = true;
var context = this;
tileView.click = function(mouseData) {
var selectedTile;
for (var i = 0; i < context.tileViews.length; i++) {
for (var j = 0; j < context.tileViews[0].length; j++) {
if (context.tileViews[i][j] == this) {
selectedTile = context.game.board.getTile(i, j);
}
}
}
context.game.tileClicked(selectedTile);
};
}
this.tileViews[x][y] = tileView;
this.boardView.addChild(tileView);
x_pos += tileWidth;
}
}
};
// draws token, puts it on appropriate tile,
// adds it to tokenViews
/**
* Draw a tokens
* Override this method in subclass to customize token drawing
* @param {Token} token - token model data
* @param {Dictionary} size - width and height of token
*/
View.prototype.drawToken = function(token, size) {
console.log("Using default drawToken()");
var tokenView = new PIXI.Graphics();
tokenView.lineStyle(1, 0, 1);
tokenView.beginFill(token.color, 1);
tokenView.drawRect(size.width/2, size.height/2, size.width/2 - 20);
return tokenView;
};
/**
* Get the tile view that a token is on
* @param {Token} token - A game token
* @returns {PIXI.Graphics} tileView
*/
View.prototype.getTileViewForToken = function(token) {
var position = this.game.board.getTilePosition(token.tile);
var tileView = null;
if (this.game.board instanceof ArrayBoard) {
tileView = this.tileViews[position];
} else if (this.game.board instanceof GridBoard) {
tileView = this.tileViews[position.x][position.y];
}
return tileView;
};
/**
* Draw all the tokens on the board
* @returns {void}
*/
View.prototype.drawTokens = function() {
for (var playerIdx in this.game.players) {
var player = this.game.players[playerIdx];
for (var tokenIdx in player.tokens) {
var token = player.tokens[tokenIdx];
var tileView = this.getTileViewForToken(token);
// overridden by user, probably
var tokenView = this.drawToken(token, tileView);
if (this.game.moveType == c.moveTypeManual || this.game.moveType == c.moveTypePlaceToken) {
tokenView.interactive = true;
var context = this;
tokenView.click = function(mouseData) {
var selectedToken;
for (var i = 0; i < context.tokenViews.length; i++) {
if (context.tokenViews[i].view == this) {
selectedToken = context.tokenViews[i].token;
}
}
context.game.tokenClicked(selectedToken);
};
}
tileView.addChild(tokenView);
this.tokenViews.push({view: tokenView, token: token});
}
}
};
/**
* Update the token view if the token moved
* @param {Dictionary} tokenView
* @returns {void}
*/
View.prototype.updateTokenView = function(tokenView) {
// if it's dead, destroy and return
if (tokenView.token.isDead) {
this.destroyTokenView(tokenView);
return;
}
// update if we've moved
var tileView = this.getTileViewForToken(tokenView.token);
// make ourself a child of new tile
tokenView.view.removeChild(tileView.view);
tileView.addChild(tokenView.view);
};
/**
* Update all of the tokens on the board
*/
View.prototype.updateTokens = function() {
if (this.game.moveType == c.moveTypePlaceToken) {
this.drawTokens();
}
var tokenView;
for (var tokenViewIdx in this.tokenViews) {
tokenView = this.tokenViews[tokenViewIdx];
this.updateTokenView(tokenView);
}
};
/**
* Remove a token view from the view
* @param {Token} token - the token to be destroyed
*/
View.prototype.destroyTokenViewForToken = function(token) {
var tokenView;
for (var tokenViewIdx in this.tokenViews) {
tokenView = this.tokenViews[tokenViewIdx];
if (tokenView.token == token) {
tokenView.view.parent.removeChild(tokenView.view);
tokenView.view.destroy();
this.tokenViews.splice(tokenViewIdx, 1);
return;
}
}
};
/**
* Remove the token view from the view
* @param {Dictionary} tokenView
*/
View.prototype.destroyTokenView = function(tokenView) {
tokenView.view.parent.removeChild(tokenView.view);
tokenView.view.destroy();
var tv;
for (var tokenViewIdx in this.tokenViews) {
tv = this.tokenViews[tokenViewIdx];
if (tv == tokenView) {
this.tokenViews.splice(tokenViewIdx, 1);
return;
}
}
};
View.prototype.drawMessage = function() {
};
View.prototype.animate = function() {
this.updateTokens();
requestAnimationFrame(this.animate.bind(this));
this.renderer.render(this.stage);
};
module.exports = View;