Merge pull request #3802 from Atlante45/chessgame

Chessgame
This commit is contained in:
Philip Rosedale 2014-11-14 17:55:19 -08:00
commit 8b4b2c51cf
4 changed files with 477 additions and 4 deletions

View file

@ -0,0 +1,8 @@
var entities = Entities.findEntities(MyAvatar.position, 10000);
var URL = "https://s3.amazonaws.com/hifi-public/models/props/chess/";
for(var i in entities) {
if (Entities.getEntityProperties(entities[i]).modelURL.slice(0, URL.length) === URL) {
Entities.deleteEntity(entities[i]);
}
}

View file

@ -0,0 +1,201 @@
(function(){
this.FIRST_TILE = null; // Global position of the first tile (1a)
this.TILE_SIZE = null; // Size of one tile
this.wantDebug = false;
this.active = false;
this.entityID = null;
this.properties = null;
this.boardID = null;
this.boardUserData = null;
this.sound = null;
this.startingTile = null;
this.pieces = new Array();
// All callbacks start by updating the properties
this.updateProperties = function(entityID) {
// Piece ID
if (this.entityID === null || !this.entityID.isKnownID) {
this.entityID = Entities.identifyEntity(entityID);
}
// Piece Properties
this.properties = Entities.getEntityProperties(this.entityID);
// Board ID
if (this.boardID === null) {
// Read user data string and update boardID
var userData = JSON.parse(this.properties.userData);
var boardID = Entities.identifyEntity(userData.boardID);
if (boardID.isKnownID) {
this.boardID = boardID;
} else {
return;
}
}
// Board User Data
this.updateUserData();
}
// Get an entity's user data
this.getEntityUserData = function(entityID) {
var properties = Entities.getEntityProperties(entityID);
if (properties && properties.userData){
return JSON.parse(properties.userData);
} else {
print("No user data found.");
return null;
}
}
// Updates user data related objects
this.updateUserData = function() {
// Get board's user data
if (this.boardID !== null && this.boardID.isKnownID) {
this.boardUserData = this.getEntityUserData(this.boardID);
if (!(this.boardUserData &&
this.boardUserData.firstTile &&
this.boardUserData.tileSize)) {
print("Incomplete boardUserData " + this.boardID.id);
} else {
this.FIRST_TILE = this.boardUserData.firstTile;
this.TILE_SIZE = this.boardUserData.tileSize;
this.active = true;
}
} else {
print("Missing boardID:" + JSON.stringify(this.boardID));
}
}
// Returns whether pos is inside the grid or not
this.isOutsideGrid = function(pos) {
return !(pos.i >= 0 && pos.j >= 0 && pos.i < 8 && pos.j < 8);
}
// Returns the tile coordinate
this.getIndexPosition = function(position) {
var halfTile = this.TILE_SIZE / 2.0;
var corner = Vec3.sum(this.FIRST_TILE, { x: -halfTile, y: 0.0, z: -halfTile });
var relative = Vec3.subtract(position, corner);
return {
i: Math.floor(relative.x / this.TILE_SIZE),
j: Math.floor(relative.z / this.TILE_SIZE)
}
}
// Returns the world position
this.getAbsolutePosition = function(pos, halfHeight) {
var relative = {
x: pos.i * this.TILE_SIZE,
y: halfHeight,
z: pos.j * this.TILE_SIZE
}
return Vec3.sum(this.FIRST_TILE, relative);
}
// Pr, Vr are respectively the Ray's Point of origin and Vector director
// Pp, Np are respectively the Plane's Point of origin and Normal vector
this.rayPlaneIntersection = function(Pr, Vr, Pp, Np) {
var d = -Vec3.dot(Pp, Np);
var t = -(Vec3.dot(Pr, Np) + d) / Vec3.dot(Vr, Np);
return Vec3.sum(Pr, Vec3.multiply(t, Vr));
}
// Download sound if needed
this.maybeDownloadSound = function() {
if (this.sound === null) {
this.sound = SoundCache.getSound("http://public.highfidelity.io/sounds/Footsteps/FootstepW3Left-12db.wav");
}
}
// Play drop sound
this.playSound = function() {
if (this.sound && this.sound.downloaded) {
Audio.playSound(this.sound, { position: this.properties.position });
}
}
// updates the piece position based on mouse input
this.updatePosition = function(mouseEvent) {
var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y)
var upVector = { x: 0, y: 1, z: 0 };
var intersection = this.rayPlaneIntersection(pickRay.origin, pickRay.direction,
this.properties.position, upVector);
// if piece outside grid then send it back to the starting tile
if (this.isOutsideGrid(this.getIndexPosition(intersection))) {
intersection = this.getAbsolutePosition(this.startingTile, this.properties.dimensions.y / 2.0);
}
Entities.editEntity(this.entityID, { position: intersection });
}
// Snap piece to the center of the tile it is on
this.snapToGrid = function() {
var pos = this.getIndexPosition(this.properties.position);
var finalPos = this.getAbsolutePosition((this.isOutsideGrid(pos)) ? this.startingTile : pos,
this.properties.dimensions.y / 2.0);
Entities.editEntity(this.entityID, { position: finalPos });
}
this.moveDeadPiece = function() {
var myPos = this.getIndexPosition(this.properties.position);
var others = Entities.findEntities(this.properties.position, this.properties.dimensions.y);
for (var i = 0; i < others.length; i++) {
var piece = others[i];
if (piece.id != this.entityID.id) {
var properties = Entities.getEntityProperties(piece);
var isWhite = properties.modelURL.search("White") !== -1;
var type = (properties.modelURL.search("King") !== -1) ? 4 :
(properties.modelURL.search("Queen") !== -1) ? 3 :
(properties.modelURL.search("Rook") !== -1) ? 2 :
(properties.modelURL.search("Knight") !== -1) ? 1 :
(properties.modelURL.search("Bishop") !== -1) ? 0 :
(properties.modelURL.search("Pawn") !== -1) ? -1 : -2;
var piecePos = this.getIndexPosition(properties.position);
if (myPos.i === piecePos.i && myPos.j === piecePos.j && type !== -2) {
var position = this.getAbsolutePosition((isWhite) ? { i: type, j: -1 } : { i: 7 - type, j: 8 },
properties.dimensions.y / 2.0);
Entities.editEntity(piece, {
position: position
});
break;
}
}
}
}
this.grab = function(mouseEvent) {
if (this.active) {
this.startingTile = this.getIndexPosition(this.properties.position);
this.updatePosition(mouseEvent);
}
}
this.move = function(mouseEvent) {
if (this.active) {
this.updatePosition(mouseEvent);
}
}
this.release = function(mouseEvent) {
if (this.active) {
this.updatePosition(mouseEvent);
this.snapToGrid();
this.moveDeadPiece();
this.playSound();
}
}
this.preload = function(entityID) {
this.updateProperties(entityID); // All callbacks start by updating the properties
this.maybeDownloadSound();
}
this.clickDownOnEntity = function(entityID, mouseEvent) {
this.preload(entityID); // TODO : remove
this.updateProperties(entityID); // All callbacks start by updating the properties
this.grab(mouseEvent);
};
this.holdingClickOnEntity = function(entityID, mouseEvent) {
this.updateProperties(entityID); // All callbacks start by updating the properties
this.move(mouseEvent);
};
this.clickReleaseOnEntity = function(entityID, mouseEvent) {
this.updateProperties(entityID); // All callbacks start by updating the properties
this.release(mouseEvent);
};
})

262
examples/playChess.js Normal file
View file

@ -0,0 +1,262 @@
//
// playChess.js
// examples
//
// Created by Clement Brisset on 11/08/2014
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
var gamePosition = { x: 1.0, y: 1.0, z: 1.0 };
var gameSize = 1.0;
// Script namespace
var extraDebug = extraDebug || true;
var ChessGame = ChessGame || {
BOARD: {
modelURL: "https://s3.amazonaws.com/hifi-public/models/props/chess/Board.fbx",
dimensions: { x: 773.191, y: 20.010, z: 773.191 },
rotation: Quat.fromPitchYawRollDegrees(0, 90, 0),
numTiles: 10.0
},
KING: 0, QUEEN: 1, BISHOP: 2, KNIGHT: 3, ROOK: 4, PAWN: 5,
board: null,
pieces: new Array()
};
ChessGame.getPieceInfo = function(type, isWhite) {
var info = {
modelURL: "https://s3.amazonaws.com/hifi-public/models/props/chess/",
dimensions: { x: 1.0, y: 1.0, z: 1.0 },
rotation: Quat.fromPitchYawRollDegrees(0, 0, 0)
}
switch(type) {
case ChessGame.KING:
info.modelURL += "King";
info.dimensions = { x: 110.496, y: 306.713, z: 110.496 };
info.rotation = Quat.fromPitchYawRollDegrees(0, 90, 0);
break;
case ChessGame.QUEEN:
info.modelURL += "Queen";
info.dimensions = { x: 110.496, y: 257.459, z: 110.496 };
break;
case ChessGame.BISHOP:
info.modelURL += "Bishop";
info.dimensions = { x: 102.002, y: 213.941, z: 102.002 };
info.rotation = Quat.fromPitchYawRollDegrees(0, 90, 0);
break;
case ChessGame.KNIGHT:
info.modelURL += "Knight";
info.dimensions = { x: 95.602, y: 186.939, z: 95.602 };
info.rotation = Quat.fromPitchYawRollDegrees(0, 180, 0);
break;
case ChessGame.ROOK:
info.modelURL += "Rook";
info.dimensions = { x: 101.024, y: 167.523, z: 101.024 };
break;
case ChessGame.PAWN:
info.modelURL += "Pawn";
info.dimensions = { x: 93.317, y: 138.747, z: 93.317 };
break;
}
info.modelURL += ((isWhite) ? "_White" : "_Black") + ".fbx"
return info;
}
// Board class
ChessGame.Board = (function(position, scale) {
this.dimensions = Vec3.multiply(1.0 / ChessGame.BOARD.dimensions.x, ChessGame.BOARD.dimensions); // 1 by 1
this.dimensions = Vec3.multiply(scale, this.dimensions); // scale by scale
this.position = position
this.tileSize = scale / ChessGame.BOARD.numTiles;
this.userDataObject = {
firstTile: this.tilePosition(1, 1),
tileSize: this.tileSize,
whitesDeadPieces: this.tilePosition(0,0),
blacksDeadPieces: this.tilePosition(9,9)
}
this.entityProperties = {
type: "Model",
modelURL: ChessGame.BOARD.modelURL,
position: this.position,
dimensions: this.dimensions,
userData: this.buildUserDataString()
}
this.entity = null;
});
// Returns the top center point of tile i,j
ChessGame.Board.prototype.tilePosition = function(i, j) {
if (!(this.position || this.dimensions || this.tileSize || ChessGame.BOARD.numTiles)) {
print("ChessGame.Board.prototype.tilePosition(): Called before proper initialisation, bailing.");
return null;
}
return {
x: this.position.x + (i - ChessGame.BOARD.numTiles / 2.0 + 0.5) * this.tileSize,
y: this.position.y + this.dimensions.y / 2.0,
z: this.position.z + (j - ChessGame.BOARD.numTiles / 2.0 + 0.5) * this.tileSize
};
}
// Checks the color of the tile
ChessGame.Board.prototype.isWhite = function(i, j) {
return (i + j) % 2 != 0;
}
// Build the user data string
ChessGame.Board.prototype.buildUserDataString = function() {
return JSON.stringify(this.userDataObject);
}
// Updates the user data stored by the board
ChessGame.Board.prototype.updateUserData = function() {
var userDataString = this.buildUserDataString();
this.entityProperties.userData = userDataString;
Entities.editEntity(this.entity, { userData: userDataString });
}
// Spawns the board using entities
ChessGame.Board.prototype.spawn = function() {
if (extraDebug) {
print("Spawning board...");
}
this.entity = Entities.addEntity(this.entityProperties);
print("Board spawned");
}
// Cleans up the entities of the board
ChessGame.Board.prototype.cleanup = function() {
if (extraDebug) {
print("Cleaning up board...");
}
Entities.deleteEntity(this.entity);
print("Board cleaned up");
}
// Piece class
ChessGame.Piece = (function(position, dimensions, url, rotation) {
this.dimensions = dimensions;
this.position = position;
this.position.y += this.dimensions.y / 2.0;
this.entityProperties = {
type: "Model",
position: this.position,
rotation: rotation,
dimensions: this.dimensions,
modelURL: url,
/**/
script: "https://s3.amazonaws.com/hifi-public/scripts/entityScripts/chessPiece.js",
/*/
script: "file:/Users/clement/hifi/examples/entityScripts/chessPiece.js",
/**/
userData: this.buildUserDataString()
}
this.entity = null;
});
// Build the user data string
ChessGame.Piece.prototype.buildUserDataString = function() {
if (!(ChessGame.board !== null || ChessGame.board.entity.isKnownID)) {
print("ChessGame.Piece.prototype.buildUserDataString(): Called before proper initialization, bailing.");
return null;
}
var userDataObject = {
boardID: ChessGame.board.entity,
};
return JSON.stringify(userDataObject);
}
// Spawns the piece
ChessGame.Piece.prototype.spawn = function() {
this.entity = Entities.addEntity(this.entityProperties);
}
// Cleans up the piece
ChessGame.Piece.prototype.cleanup = function() {
Entities.deleteEntity(this.entity);
}
ChessGame.makePiece = function(piece, i, j, isWhite) {
var info = ChessGame.getPieceInfo(piece, isWhite);
var url = info.modelURL;
var size = Vec3.multiply(0.5 * (1.0 / ChessGame.BOARD.dimensions.x), info.dimensions);
var rotation = (isWhite) ? info.rotation
: Quat.multiply(Quat.fromPitchYawRollDegrees(0, 180, 0),
info.rotation);
var position = ChessGame.board.tilePosition(i, j);
var piece = new ChessGame.Piece(position, size, url, rotation);
piece.spawn();
ChessGame.pieces.push(piece);
return piece;
}
ChessGame.scriptStarting = function() {
print("playChess.js started");
gamePosition = Vec3.sum(MyAvatar.position,
Vec3.multiplyQbyV(MyAvatar.orientation,
{ x: 0, y: 0, z: -1 }));
// Setup board
ChessGame.board = new ChessGame.Board(gamePosition, gameSize);
ChessGame.board.spawn();
}
ChessGame.update = function() {
ChessGame.board.entity = Entities.identifyEntity(ChessGame.board.entity);
if (ChessGame.board.entity.isKnownID && ChessGame.pieces.length == 0) {
// Setup white pieces
var isWhite = true;
var row = 1;
// King
ChessGame.makePiece(ChessGame.KING, row, 5, isWhite);
// Queen
ChessGame.makePiece(ChessGame.QUEEN, row, 4, isWhite);
// Bishop
ChessGame.makePiece(ChessGame.BISHOP, row, 3, isWhite);
ChessGame.makePiece(ChessGame.BISHOP, row, 6, isWhite);
// Knight
ChessGame.makePiece(ChessGame.KNIGHT, row, 2, isWhite);
ChessGame.makePiece(ChessGame.KNIGHT, row, 7, isWhite);
// Rook
ChessGame.makePiece(ChessGame.ROOK, row, 1, isWhite);
ChessGame.makePiece(ChessGame.ROOK, row, 8, isWhite);
for(var j = 1; j <= 8; j++) {
ChessGame.makePiece(ChessGame.PAWN, row + 1, j, isWhite);
}
// Setup black pieces
isWhite = false;
row = 8;
// King
ChessGame.makePiece(ChessGame.KING, row, 5, isWhite);
// Queen
ChessGame.makePiece(ChessGame.QUEEN, row, 4, isWhite);
// Bishop
ChessGame.makePiece(ChessGame.BISHOP, row, 3, isWhite);
ChessGame.makePiece(ChessGame.BISHOP, row, 6, isWhite);
// Knight
ChessGame.makePiece(ChessGame.KNIGHT, row, 2, isWhite);
ChessGame.makePiece(ChessGame.KNIGHT, row, 7, isWhite);
// Rook
ChessGame.makePiece(ChessGame.ROOK, row, 1, isWhite);
ChessGame.makePiece(ChessGame.ROOK, row, 8, isWhite);
for(var j = 1; j <= 8; j++) {
ChessGame.makePiece(ChessGame.PAWN, row - 1, j, isWhite);
}
Script.update.disconnect(ChessGame.update);
}
}
ChessGame.scriptEnding = function() {
// Cleaning up board
ChessGame.board.cleanup();
// Cleaning up pieces
for(var i in ChessGame.pieces) {
ChessGame.pieces[i].cleanup();
}
print("playChess.js finished");
}
Script.scriptEnding.connect(ChessGame.scriptEnding);
Script.update.connect(ChessGame.update);
ChessGame.scriptStarting();

View file

@ -163,10 +163,12 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItem* entity) {
QString scriptContents = loadScriptContents(entity->getScript());
if (QScriptEngine::checkSyntax(scriptContents).state() != QScriptSyntaxCheckResult::Valid) {
QScriptSyntaxCheckResult syntaxCheck = QScriptEngine::checkSyntax(scriptContents);
if (syntaxCheck.state() != QScriptSyntaxCheckResult::Valid) {
qDebug() << "EntityTreeRenderer::loadEntityScript() entity:" << entityID;
qDebug() << " INVALID SYNTAX";
qDebug() << " SCRIPT:" << scriptContents;
qDebug() << " " << syntaxCheck.errorMessage() << ":"
<< syntaxCheck.errorLineNumber() << syntaxCheck.errorColumnNumber();
qDebug() << " SCRIPT:" << entity->getScript();
return QScriptValue(); // invalid script
}
@ -175,7 +177,7 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItem* entity) {
if (!entityScriptConstructor.isFunction()) {
qDebug() << "EntityTreeRenderer::loadEntityScript() entity:" << entityID;
qDebug() << " NOT CONSTRUCTOR";
qDebug() << " SCRIPT:" << scriptContents;
qDebug() << " SCRIPT:" << entity->getScript();
return QScriptValue(); // invalid script
}