From 6ae27fe1f9ad965e6c7a133a337736e3bf67ff69 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 2 Mar 2016 15:53:13 -0800 Subject: [PATCH] More flappy bird work --- examples/flappyBird.js | 271 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 258 insertions(+), 13 deletions(-) diff --git a/examples/flappyBird.js b/examples/flappyBird.js index 95e018089e..63366a6c75 100644 --- a/examples/flappyBird.js +++ b/examples/flappyBird.js @@ -9,59 +9,304 @@ // // Constants +var OBJECTS_LIFETIME = 1; +var G = 4.0; - +Number.prototype.clamp = function(min, max) { + return Math.min(Math.max(this, min), max); +}; // Class definitions function Game() { // public methods this.start = function() { if (!isRunning) { + isRunning = true; setup(); Script.update.connect(idle); } - }; + } this.stop = function() { if (isRunning) { Script.update.disconnect(idle); cleanup(); + isRunning = false; } - }; + } + this.keyPressed = function(event) { + if (event.text === "SPACE" && (gameTime - lastLost) > coolDown) { + isJumping = true; + startedPlaying = true; + } + } + + // Constants + var spaceDimensions = { x: 1.5, y: 0.8, z: 0.01 }; + var spaceDistance = 1.5; + var spaceYOffset = 0.6; + + var jumpVelocity = 1.0; // Private game state var that = this; + var entityManager = new EntityManager(); var isRunning = false; + var startedPlaying = false; + + var coolDown = 1; + var lastLost = -coolDown; + + var gameTime = 0; + + var isJumping = false; + + var space = null + var board = null; + + var bird = null; + var birdXPos = spaceDimensions.x / 2.0; + var birdDimensions = 0.05; + + // ALong Y axis + var birdPos = spaceDimensions.y / 2.0; + var birdVel = 0.0; + var birdAcc = -G; + + var pipes = new Array(); + var lastPipe = 0; + var pipesInterval = 0.5; + var pipesVelocity = 1.0; + var pipeWidth = 0.05; + var pipeLength = 0.4; // Game loop setup function idle(deltaTime) { inputs(); update(deltaTime); draw(); - }; + } - // Private methods function setup() { print("setup"); - }; + + space = { + position: getSpacePosition(), + orientation: getSpaceOrientation(), + dimensions: getSpaceDimensions() + } + + board = entityManager.add({ + type: "Box", + position: space.position, + rotation: space.orientation, + dimensions: space.dimensions, + color: { red: 100, green: 200, blue: 200 } + }); + + bird = entityManager.add({ + type: "Sphere", + position: to3DPosition({ x: birdXPos, y: birdPos }), + dimensions: { x: birdDimensions, y: birdDimensions, z: birdDimensions }, + color: { red: 0, green: 0, blue: 255 } + }); + } function inputs() { - print("inputs"); - }; + //print("inputs"); + } function update(deltaTime) { - print("update: " + deltaTime); - }; + //print("update: " + deltaTime); + + // Keep entities alive + gameTime += deltaTime; + entityManager.update(deltaTime); + + if (!startedPlaying && (gameTime - lastLost) < coolDown) { + return; + } + + // Update Bird + if (!startedPlaying && birdPos < spaceDimensions.y / 2.0) { + isJumping = true; + } + // Apply jumps + if (isJumping) { + birdVel = jumpVelocity; + isJumping = false; + } + // Apply gravity + birdPos += deltaTime * (birdVel + deltaTime * birdAcc / 2.0); + birdVel += deltaTime * birdAcc; + + + // Move pipes forward + pipes.forEach(function(element) { + element.position -= deltaTime * pipesVelocity; + }); + // Delete pipes over the end + var count = 0; + while(count < pipes.length && pipes[count].position <= 0.0) { + entityManager.remove(pipes[count].id); + count++; + } + if (count > 0) { + pipes = pipes.splice(count); + } + // Move pipes forward + if (startedPlaying && gameTime - lastPipe > pipesInterval) { + print("New pipe"); + var newPipe = entityManager.add({ + type: "Box", + position: to3DPosition({ x: space.dimensions.x, y: 0.2 }), + dimensions: { x: pipeWidth, y: pipeLength, z: pipeWidth }, + color: { red: 0, green: 255, blue: 0 } + }); + pipes.push({ id: newPipe, position: space.dimensions.x }); + lastPipe = gameTime; + } + + + // Check lost + var hasLost = birdPos < 0.0 || birdPos > space.dimensions.y; + if (!hasLost) { + pipes.forEach(function(element) { + var deltaX = Math.abs(element.position - birdXPos); + if (deltaX < (birdDimensions + pipeWidth) / 2.0) { + var deltaY = birdPos - pipeLength; + if (deltaY < 0 || deltaY < birdDimensions / 2.0) { + hasLost = true; + } + } + }); + } + + // Cleanup + if (hasLost) { + birdPos = spaceDimensions.y / 2.0; + birdVel = 0.0; + startedPlaying = false; + lastLost = gameTime; + + + // Clearing pipes + print("Clearing pipes: " + pipes.length); + pipes.forEach(function(element) { + entityManager.remove(element.id); + }); + pipes = new Array(); + } + } function draw() { - print("draw"); - }; + //print("draw"); + Entities.editEntity(bird, { position: to3DPosition({ x: birdXPos, y: birdPos }) }); + + pipes.forEach(function(element) { + Entities.editEntity(element.id, { position: to3DPosition({ x: element.position, y: 0.2 }) }); + }); + } function cleanup() { print("cleanup"); - }; + entityManager.removeAll(); + } + + // Private methods + function getSpacePosition() { + var forward = Vec3.multiplyQbyV(MyAvatar.orientation, Vec3.FRONT); + var spacePosition = Vec3.sum(MyAvatar.position, Vec3.multiply(spaceDistance, forward)); + return Vec3.sum(spacePosition, Vec3.multiply(spaceYOffset, Vec3.UP)); + } + function getSpaceOrientation() { + return MyAvatar.orientation; + } + function getSpaceDimensions() { + return spaceDimensions; + } + + + + function project(point, plane) { + var v = Vec3.subtract(point, plane.origin); + var dist = Vec3.dot(v, plane.normal); + return Vec3.subtract(point, Vec3.multiply(dist, v)); + } + function to3DPosition(position) { + var position2D = { + x: position.x - space.dimensions.x / 2.0, + y: position.y - space.dimensions.y / 2.0, + z: 0.0 + } + return Vec3.sum(space.position, Vec3.multiplyQbyV(space.orientation, position2D)); + } + function to2DPosition(position) { + var position3D = project(position, { + origin: Vec3.subtract(space.position, { + x: space.dimensions.x / 2.0, + y: space.dimensions.y / 2.0, + z: 0.0 + }), + normal: Vec3.multiplyQbyV(space.orientation, Vec3.FRONT) + }); + + var position2D = { + x: position3D.x.clamp(0.0, space.dimensions.x), + y: position3D.y.clamp(0.0, space.dimensions.y) + } + return position2D; + } + +} + +function EntityManager() { + var entities = new Array(); + var lifetime = OBJECTS_LIFETIME; + + this.setLifetime = function(newLifetime) { + lifetime = newLifetime; + this.update(); + } + this.add = function(properties) { + // Add to scene + properties.lifetime = lifetime; + var entityID = Entities.addEntity(properties); + // Add to array + entities.push({ id: entityID, properties: properties }); + + return entityID; + } + this.update = function(deltaTime) { + entities.forEach(function(element) { + // Get entity's age + var properties = Entities.getEntityProperties(element.id, ["age"]); + // Update entity's lifetime + Entities.editEntity(element.id, { lifetime: properties.age + lifetime }); + }); + } + this.remove = function(entityID) { + // Remove from scene + Entities.deleteEntity(entityID); + + // Remove from array + entities = entities.filter(function(element) { + return element.id !== entityID; + }); + } + this.removeAll = function() { + // Remove all from scene + entities.forEach(function(element) { + Entities.deleteEntity(element.id); + }); + // Remove all from array + entities = new Array(); + } } // Script logic function scriptStarting() { var game = new Game(); + Controller.keyPressEvent.connect(function(event) { + game.keyPressed(event); + }); Script.scriptEnding.connect(function() { game.stop(); });