overte/examples/spaceInvadersExample.js
2014-02-05 13:26:46 -08:00

415 lines
15 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// spaceInvadersExample.js
// hifi
//
// Created by Brad Hefta-Gaub on 1/30/14.
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
//
// This is an example script that demonstrates a simple space invaders style of game
//
var iteration = 0;
var gameOver = false;
// horizontal movement of invaders
var invaderStepsPerCycle = 120; // the number of update steps it takes then invaders to move one column to the right
var invaderStepOfCycle = 0; // current iteration in the cycle
var invaderMoveDirection = 1; // 1 for moving to right, -1 for moving to left
// game length...
var itemLifetimes = 60; // 1 minute
// position the game to be basically near the avatar running the game...
var gameSize = { x: 10, y: 20, z: 1 };
var positionFromAvatarZ = 10;
var avatarX = MyAvatar.position.x;
var avatarY = MyAvatar.position.y;
var avatarZ = MyAvatar.position.z;
var gameAtX = avatarX;
var gameAtY = avatarY;
var gameAtZ = avatarZ;
// move the game to be "centered" on our X
if (gameAtX > (gameSize.x/2)) {
gameAtX -= (gameSize.x/2);
}
// move the game to be "offset slightly" on our Y
if (gameAtY > (gameSize.y/4)) {
gameAtY -= (gameSize.y/4);
}
// move the game to be positioned away on our Z
if (gameAtZ > positionFromAvatarZ) {
gameAtZ -= positionFromAvatarZ;
}
var gameAt = { x: gameAtX, y: gameAtY, z: gameAtZ };
var middleX = gameAt.x + (gameSize.x/2);
var middleY = gameAt.y + (gameSize.y/2);
var invaderSize = 0.4;
var shipSize = 0.25;
var missileSize = 0.1;
var myShip;
var myShipProperties;
// create the rows of space invaders
var invaders = new Array();
var numberOfRows = 5;
var invadersPerRow = 8;
var emptyColumns = 2; // number of invader width columns not filled with invaders
var invadersBottomCorner = { x: gameAt.x, y: middleY , z: gameAt.z };
var rowHeight = ((gameAt.y + gameSize.y) - invadersBottomCorner.y) / numberOfRows;
var columnWidth = gameSize.x / (invadersPerRow + emptyColumns);
// vertical movement of invaders
var invaderRowOffset = 0;
var stepsPerRow = 20; // number of steps before invaders really move a whole row down.
var yPerStep = rowHeight/stepsPerRow;
var stepsToGround = (middleY - gameAt.y) / yPerStep;
var maxInvaderRowOffset=stepsToGround;
// missile related items
var missileFired = false;
var myMissile;
// sounds
var hitSound = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Space%20Invaders/hit.raw");
var shootSound = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Space%20Invaders/shoot.raw");
var moveSounds = new Array();
moveSounds[0] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Space%20Invaders/Lo1.raw");
moveSounds[1] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Space%20Invaders/Lo2.raw");
moveSounds[2] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Space%20Invaders/Lo3.raw");
moveSounds[3] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Space%20Invaders/Lo4.raw");
var currentMoveSound = 0;
var numberOfSounds = 4;
var stepsPerSound = invaderStepsPerCycle / numberOfSounds;
// if you set this to false, sounds will come from the location of particles instead of the player's head
var soundInMyHead = true;
// models...
var invaderModels = new Array();
invaderModels[0] = {
modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/newInvader16x16-large-purple.svo",
modelScale: 450,
modelTranslation: { x: -1.3, y: -1.3, z: -1.3 },
};
invaderModels[1] = {
modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/newInvader16x16-large-cyan.svo",
modelScale: 450,
modelTranslation: { x: -1.3, y: -1.3, z: -1.3 },
};
invaderModels[2] = {
modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/newInvader16x16-medium-cyan.svo",
modelScale: 450,
modelTranslation: { x: -1.3, y: -1.3, z: -1.3 },
};
invaderModels[3] = {
modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/newInvader16x16-medium-green.svo",
modelScale: 450,
modelTranslation: { x: -1.3, y: -1.3, z: -1.3 },
};
invaderModels[4] = {
modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/newInvader16x16-small-green.svo",
modelScale: 450,
modelTranslation: { x: -1.3, y: -1.3, z: -1.3 },
};
//modelURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/Feisar_Ship.FBX",
//modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/invader.svo",
// "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/spaceInvader3.fbx"
function initializeMyShip() {
myShipProperties = {
position: { x: middleX , y: gameAt.y, z: gameAt.z },
velocity: { x: 0, y: 0, z: 0 },
gravity: { x: 0, y: 0, z: 0 },
damping: 0,
radius: shipSize,
color: { red: 0, green: 255, blue: 0 },
modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/myCannon16x16.svo",
modelScale: 450,
modelTranslation: { x: -1.3, y: -1.3, z: -1.3 },
lifetime: itemLifetimes
};
myShip = Particles.addParticle(myShipProperties);
}
// calculate the correct invaderPosition for an column row
function getInvaderPosition(row, column) {
var xBasePart = invadersBottomCorner.x + (column * columnWidth);
var xMovePart = 0;
if (invaderMoveDirection > 0) {
xMovePart = (invaderMoveDirection * columnWidth * (invaderStepOfCycle/invaderStepsPerCycle));
} else {
xMovePart = columnWidth + (invaderMoveDirection * columnWidth * (invaderStepOfCycle/invaderStepsPerCycle));
}
var y = invadersBottomCorner.y + (row * rowHeight) - (invaderRowOffset * rowHeight/stepsPerRow);
var invaderPosition = {
x: xBasePart + xMovePart,
y: y,
z: invadersBottomCorner.z };
return invaderPosition;
}
function initializeInvaders() {
for (var row = 0; row < numberOfRows; row++) {
invaders[row] = new Array();
for (var column = 0; column < invadersPerRow; column++) {
invaderPosition = getInvaderPosition(row, column);
invaders[row][column] = Particles.addParticle({
position: invaderPosition,
velocity: { x: 0, y: 0, z: 0 },
gravity: { x: 0, y: 0, z: 0 },
damping: 0,
radius: invaderSize,
color: { red: 255, green: 0, blue: 0 },
modelURL: invaderModels[row].modelURL,
modelScale: invaderModels[row].modelScale,
modelTranslation: invaderModels[row].modelTranslation,
lifetime: itemLifetimes
});
print("invaders[row][column].creatorTokenID=" + invaders[row][column].creatorTokenID);
}
}
}
function moveInvaders() {
for (var row = 0; row < numberOfRows; row++) {
for (var column = 0; column < invadersPerRow; column++) {
props = Particles.getParticleProperties(invaders[row][column]);
if (props.isKnownID) {
invaderPosition = getInvaderPosition(row, column);
Particles.editParticle(invaders[row][column],
{
position: invaderPosition,
velocity: { x: 0, y: 0, z: 0 } // always reset this, incase they got collided with
});
}
}
}
}
function displayGameOver() {
gameOver = true;
print("Game over...");
}
function update() {
if (!gameOver) {
//print("updating space invaders... iteration="+iteration);
iteration++;
if (invaderStepOfCycle % stepsPerSound == 0) {
// play the move sound
var options = new AudioInjectionOptions();
if (soundInMyHead) {
options.position = { x: MyAvatar.position.x + 0.0,
y: MyAvatar.position.y + 0.1,
z: MyAvatar.position.z + 0.0 };
} else {
options.position = getInvaderPosition(invadersPerRow / 2, numberOfRows / 2);
}
options.volume = 1.0;
Audio.playSound(moveSounds[currentMoveSound], options);
// get ready for next move sound
currentMoveSound = (currentMoveSound+1) % numberOfSounds;
}
invaderStepOfCycle++;
if (invaderStepOfCycle > invaderStepsPerCycle) {
// handle left/right movement
invaderStepOfCycle = 0;
if (invaderMoveDirection > 0) {
invaderMoveDirection = -1;
} else {
invaderMoveDirection = 1;
}
// handle downward movement
invaderRowOffset++; // move down one row
//print("invaderRowOffset="+invaderRowOffset);
// check to see if invaders have reached "ground"...
if (invaderRowOffset > maxInvaderRowOffset) {
displayGameOver();
return;
}
}
moveInvaders();
}
}
// register the call back so it fires before each data send
Script.willSendVisualDataCallback.connect(update);
function cleanupGame() {
print("cleaning up game...");
Particles.deleteParticle(myShip);
print("cleanupGame() ... Particles.deleteParticle(myShip)... myShip.id="+myShip.id);
for (var row = 0; row < numberOfRows; row++) {
for (var column = 0; column < invadersPerRow; column++) {
Particles.deleteParticle(invaders[row][column]);
print("cleanupGame() ... Particles.deleteParticle(invaders[row][column])... invaders[row][column].id="
+invaders[row][column].id);
}
}
// clean up our missile
if (missileFired) {
Particles.deleteParticle(myMissile);
}
Controller.releaseKeyEvents({text: " "});
Script.stop();
}
Script.scriptEnding.connect(cleanupGame);
function endGame() {
print("ending game...");
Script.stop();
}
function moveShipTo(position) {
myShip = Particles.identifyParticle(myShip);
Particles.editParticle(myShip, { position: position });
}
function fireMissile() {
// we only allow one missile at a time...
var canFire = false;
// If we've fired a missile, then check to see if it's still alive
if (missileFired) {
var missileProperties = Particles.getParticleProperties(myMissile);
print("missileProperties.isKnownID=" + missileProperties.isKnownID);
if (!missileProperties.isKnownID) {
print("canFire = true");
canFire = true;
}
} else {
canFire = true;
}
if (canFire) {
print("firing missile");
var missilePosition = { x: myShipProperties.position.x,
y: myShipProperties.position.y + (2* shipSize),
z: myShipProperties.position.z };
myMissile = Particles.addParticle(
{
position: missilePosition,
velocity: { x: 0, y: 5, z: 0},
gravity: { x: 0, y: 0, z: 0 },
damping: 0,
radius: missileSize,
color: { red: 0, green: 0, blue: 255 },
lifetime: 5
});
var options = new AudioInjectionOptions();
if (soundInMyHead) {
options.position = { x: MyAvatar.position.x + 0.0,
y: MyAvatar.position.y + 0.1,
z: MyAvatar.position.z + 0.0 };
} else {
options.position = missilePosition;
}
options.volume = 1.0;
Audio.playSound(shootSound, options);
missileFired = true;
}
}
function keyPressEvent(key) {
//print("keyPressEvent key.text="+key.text);
if (key.text == ",") {
myShipProperties.position.x -= 0.1;
if (myShipProperties.position.x < gameAt.x) {
myShipProperties.position.x = gameAt.x;
}
moveShipTo(myShipProperties.position);
} else if (key.text == ".") {
myShipProperties.position.x += 0.1;
if (myShipProperties.position.x > gameAt.x + gameSize.x) {
myShipProperties.position.x = gameAt.x + gameSize.x;
}
moveShipTo(myShipProperties.position);
} else if (key.text == " ") {
fireMissile();
} else if (key.text == "q") {
endGame();
}
}
// remap the keys...
Controller.keyPressEvent.connect(keyPressEvent);
Controller.captureKeyEvents({text: " "});
function deleteIfInvader(possibleInvaderParticle) {
for (var row = 0; row < numberOfRows; row++) {
for (var column = 0; column < invadersPerRow; column++) {
invaders[row][column] = Particles.identifyParticle(invaders[row][column]);
if (invaders[row][column].isKnownID) {
if (invaders[row][column].id == possibleInvaderParticle.id) {
Particles.deleteParticle(possibleInvaderParticle);
Particles.deleteParticle(myMissile);
// play the hit sound
var options = new AudioInjectionOptions();
if (soundInMyHead) {
options.position = { x: MyAvatar.position.x + 0.0,
y: MyAvatar.position.y + 0.1,
z: MyAvatar.position.z + 0.0 };
} else {
options.position = getInvaderPosition(row, column);
}
options.volume = 1.0;
Audio.playSound(hitSound, options);
}
}
}
}
}
function particleCollisionWithParticle(particleA, particleB) {
print("particleCollisionWithParticle() a.id="+particleA.id + " b.id=" + particleB.id);
if (missileFired) {
myMissile = Particles.identifyParticle(myMissile);
if (myMissile.id == particleA.id) {
deleteIfInvader(particleB);
} else if (myMissile.id == particleB.id) {
deleteIfInvader(particleA);
}
}
}
Particles.particleCollisionWithParticle.connect(particleCollisionWithParticle);
// initialize the game...
initializeMyShip();
initializeInvaders();
// shut down the game after 1 minute
var gameTimer = Script.setTimeout(endGame, itemLifetimes * 1000);