420 lines · 13.9 KB · JavaScript
RawDownload
////  spaceInvadersExample.js//  examples////  Created by Brad Hefta-Gaub on 1/30/14.//  Copyright 2014 High Fidelity, Inc.////  This is an example script that demonstrates a simple space invaders style of game////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html//  var OVERTE_PUBLIC_CDN = networkingConstants.PUBLIC_BUCKET_CDN_URL; var iteration = 0; var gameOver = false; // horizontal movement of invadersvar invaderStepsPerCycle = 120; // the number of update steps it takes then invaders to move one column to the rightvar invaderStepOfCycle = 0; // current iteration in the cyclevar invaderMoveDirection = 1; // 1 for moving to right, -1 for moving to leftvar LEFT = ",";var RIGHT = ".";var FIRE = "SPACE";var QUIT = "q"; print("Use:");print(LEFT + " to move left");print(RIGHT + " to move right");print(FIRE + " to fire");print(QUIT + " to quit"); // 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 Xif (gameAtX > (gameSize.x/2)) {    gameAtX -= (gameSize.x/2);} // move the game to be "offset slightly" on our Yif (gameAtY > (gameSize.y/4)) {    gameAtY -= (gameSize.y/4);}  // move the game to be positioned away on our Zif (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 = 1.0;var myShip;var myShipProperties; // create the rows of space invadersvar invaders = new Array();var numberOfRows = 3 // FIXME 5;var invadersPerRow = 3 // FIXME 8;var emptyColumns = 2; // number of invader width columns not filled with invadersvar 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 invadersvar 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 itemsvar myMissile; // soundsvar hitSound = SoundCache.getSound(OVERTE_PUBLIC_CDN + "sounds/Space%20Invaders/hit.raw");var shootSound = SoundCache.getSound(OVERTE_PUBLIC_CDN + "sounds/Space%20Invaders/shoot.raw");var moveSounds = new Array();moveSounds[0] = SoundCache.getSound(OVERTE_PUBLIC_CDN + "sounds/Space%20Invaders/Lo1.raw");moveSounds[1] = SoundCache.getSound(OVERTE_PUBLIC_CDN + "sounds/Space%20Invaders/Lo2.raw");moveSounds[2] = SoundCache.getSound(OVERTE_PUBLIC_CDN + "sounds/Space%20Invaders/Lo3.raw");moveSounds[3] = SoundCache.getSound(OVERTE_PUBLIC_CDN + "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 entities instead of the player's headvar soundInMyHead = true;  // models...var invaderModels = new Array();invaderModels[0] = {        modelURL: OVERTE_PUBLIC_CDN + "meshes/space_invader.fbx",        modelScale: 450,        modelTranslation: { x: -1.3, y: -1.3, z: -1.3 },    };invaderModels[1] = {        modelURL: OVERTE_PUBLIC_CDN + "meshes/space_invader.fbx",        modelScale: 450,        modelTranslation: { x: -1.3, y: -1.3, z: -1.3 },    };invaderModels[2] = {        modelURL: OVERTE_PUBLIC_CDN + "meshes/space_invader.fbx",        modelScale: 450,        modelTranslation: { x: -1.3, y: -1.3, z: -1.3 },    };invaderModels[3] = {        modelURL: OVERTE_PUBLIC_CDN + "meshes/space_invader.fbx",        modelScale: 450,        modelTranslation: { x: -1.3, y: -1.3, z: -1.3 },    };invaderModels[4] = {        modelURL: OVERTE_PUBLIC_CDN + "meshes/space_invader.fbx",        modelScale: 450,        modelTranslation: { x: -1.3, y: -1.3, z: -1.3 },    };         //modelURL: OVERTE_PUBLIC_CDN + "meshes/Feisar_Ship.FBX",//modelURL: OVERTE_PUBLIC_CDN + "meshes/invader.svo",// OVERTE_PUBLIC_CDN + "meshes/spaceInvader3.fbx" function initializeMyShip() {    myShipProperties = {            type: "Model",            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,            dimensions: { x: shipSize * 2, y: shipSize * 2, z: shipSize * 2 },            color: { red: 0, green: 255, blue: 0 },            modelURL: OVERTE_PUBLIC_CDN + "meshes/space_invader.fbx",            lifetime: itemLifetimes        };    myShip = Entities.addEntity(myShipProperties);} // calculate the correct invaderPosition for an column rowfunction 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] = Entities.addEntity({                        type: "Model",                        shapeType: "box",                        position: invaderPosition,                        velocity: { x: 0, y: 0, z: 0 },                        gravity: { x: 0, y: 0, z: 0 },                        damping: 0,                        dimensions: { x: invaderSize * 2, y: invaderSize * 2, z: invaderSize * 2 },                        color: { red: 255, green: 0, blue: 0 },                        modelURL: invaderModels[row].modelURL,                        dynamic: true,                        lifetime: itemLifetimes                    });        }    }} function moveInvaders() {    for (var row = 0; row < numberOfRows; row++) {        for (var column = 0; column < invadersPerRow; column++) {            props = Entities.getEntityProperties(invaders[row][column]);            if (props.id) {                invaderPosition = getInvaderPosition(row, column);                Entities.editEntity(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(deltaTime) {    if (!gameOver) {        //print("updating space invaders... iteration="+iteration);        iteration++;         if (invaderStepOfCycle % stepsPerSound == 0) {            // play the move sound            var options = {};                        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);            }                        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 sendScript.update.connect(update); function cleanupGame() {    print("cleaning up game...");    Entities.deleteEntity(myShip);    print("cleanupGame() ... Entities.deleteEntity(myShip)... myShip="+myShip);    for (var row = 0; row < numberOfRows; row++) {        for (var column = 0; column < invadersPerRow; column++) {            Entities.deleteEntity(invaders[row][column]);            print("cleanupGame() ... Entities.deleteEntity(invaders[row][column])... invaders[row][column]="                    +invaders[row][column]);        }    }        // clean up our missile    if (myMissile) {        Entities.deleteEntity(myMissile);    }        Controller.releaseKeyEvents({text: " "});        Script.stop();}Script.scriptEnding.connect(cleanupGame); function endGame() {    print("ending game...");    Script.stop();} function moveShipTo(position) {    Entities.editEntity(myShip, { position: position });} function entityCollisionWithEntity(entityA, entityB, collision) {    print("entityCollisionWithEntity() a="+entityA + " b=" + entityB);    Vec3.print('entityCollisionWithEntity() penetration=', collision.penetration);    Vec3.print('entityCollisionWithEntity() contactPoint=', collision.contactPoint);     deleteIfInvader(entityB);} 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 (myMissile) {        var missileProperties = Entities.getEntityProperties(myMissile);            if (!missileProperties || (missileProperties.type === 'Unknown')) {            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 = Entities.addEntity(                        {                             type: "Sphere",                            position: missilePosition,                            velocity: { x: 0, y: 5, z: 0},                            gravity: { x: 0, y: 0, z: 0 },                            damping: 0,                            dynamic: true,                            dimensions: { x: missileSize, y: missileSize, z: missileSize },                            color: { red: 0, green: 0, blue: 255 },                            lifetime: 5                        });    Script.addEventHandler(myMissile, "collisionWithEntity", entityCollisionWithEntity);        var options = {}        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;        }         Audio.playSound(shootSound, options);     }} function keyPressEvent(key) {    //print("keyPressEvent key.text="+key.text);     if (key.text == LEFT) {        myShipProperties.position.x -= 0.1;        if (myShipProperties.position.x < gameAt.x) {            myShipProperties.position.x = gameAt.x;        }        moveShipTo(myShipProperties.position);    } else if (key.text == RIGHT) {        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 == FIRE) {        fireMissile();    } else if (key.text == QUIT) {        endGame();    }} // remap the keys...Controller.keyPressEvent.connect(keyPressEvent);Controller.captureKeyEvents({text: " "}); function deleteIfInvader(possibleInvaderEntity) {    for (var row = 0; row < numberOfRows; row++) {        for (var column = 0; column < invadersPerRow; column++) {            if (invaders[row][column] == possibleInvaderEntity) {                Entities.deleteEntity(possibleInvaderEntity);                Entities.deleteEntity(myMissile);                 // play the hit sound                var options = {};                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);                }                                Audio.playSound(hitSound, options);            }        }    }}  // initialize the game...initializeMyShip();initializeInvaders(); // shut down the game after 1 minutevar gameTimer = Script.setTimeout(endGame, itemLifetimes * 1000);