diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/button.js | 18 | ||||
| -rw-r--r-- | src/engine.js | 217 | ||||
| -rw-r--r-- | src/gameobject.js | 20 | ||||
| -rw-r--r-- | src/keyboard.js | 38 | ||||
| -rw-r--r-- | src/objecttypes.js | 107 | ||||
| -rw-r--r-- | src/platformer.js | 9 | ||||
| -rw-r--r-- | src/player.js | 67 | ||||
| -rw-r--r-- | src/settings.js | 15 | ||||
| -rw-r--r-- | src/sound.js | 20 |
9 files changed, 511 insertions, 0 deletions
diff --git a/src/button.js b/src/button.js new file mode 100644 index 0000000..a214db3 --- /dev/null +++ b/src/button.js @@ -0,0 +1,18 @@ +function Button() { + this.graphics = new PIXI.Graphics(); + + this.graphics.beginFill(0xFFFF00); + + // set the line style to have a width of 5 and set the color to red + this.graphics.lineStyle(5, 0xFF0000); + + // draw a rectangle + this.graphics.drawRect(100, 150, 50, 50); + + // make the button interactive.. + this.graphics.setInteractive(true); + + this.graphics.click = function(data) { + console.log('hit rect'); + } +}
\ No newline at end of file diff --git a/src/engine.js b/src/engine.js new file mode 100644 index 0000000..30d7d7a --- /dev/null +++ b/src/engine.js @@ -0,0 +1,217 @@ +var MENU = 1; +var GAME = 2; +var GAMEOVER = 3; + +var appRunning = true; +var Engine = function() { + + Engine.instance = this; + + this.sound = new Sound(); + + this.state = MENU; + + this.stage = new PIXI.Container(); + this.renderer = PIXI.autoDetectRenderer(Settings.stage_WIDTH, Settings.stage_HEIGHT); + + this.mapContainer = new PIXI.Container(), + this.unitsContainer = new PIXI.Container(), + this.menuContainer = new PIXI.Container(); + this.clickableContainer = new PIXI.Container(); + + this.mapContainer.zIndex = 4; + this.unitsContainer.zIndex = 3; + this.menuContainer.zIndex = 2; + this.clickableContainer.zIndex = 1; + + this.stage.addChild(this.mapContainer); + this.stage.addChild(this.menuContainer); + this.stage.addChild(this.unitsContainer); + this.stage.addChild(this.clickableContainer); + + this.stage.updateLayersOrder = function () { + this.children.sort(function(a,b) { + a.zIndex = a.zIndex || 0; + b.zIndex = b.zIndex || 0; + return b.zIndex - a.zIndex + }); + }; + this.makeStageClickable(); + + this.setupGameObjects(); + this.integralSpawnTimer = 0; + this.gameOverTimer = 0; + + return this; +} + +Engine.prototype.makeStageClickable = function() { + this.clickLayer = new PIXI.Graphics(); + this.clickLayer.beginFill(0x000000, 0.0); + this.clickLayer.drawRect(0, 0, Settings.STAGE_WIDTH, Settings.STAGE_HEIGHT); + this.clickLayer.interactive = true; + + this.clickableContainer.addChild(this.clickLayer); + + this.clickLayer.touchstart = this.clickLayer.mousedown = this.buttonPressed.bind(this); +} + +Engine.prototype.activateMenu = function() { + this.state = MENU; + player.score = 0 + console.log("changed to menu!"); + logo1.sprite.visible = true; + logo2.sprite.visible = true; + this.resetPositions(); + player.active = false; + scoreText.visible = false; + gameOverText.visible = false; + scoreBg.visible = false; + + for (var i = 0; i < this.gameObjectList.length; i++) { + if (this.gameObjectList[i].objectType == "integral") + this.removeIntegral(this.gameObjectList[i]) + } +} + +Engine.prototype.activateGame = function() { + this.state = GAME; + console.log("game starting...") + player.active = true; + logo1.sprite.visible = false; + logo2.sprite.visible = false; + scoreText.moveToCorner(); + scoreText.visible = true; + this.sound.play("start") +} + +Engine.prototype.activateGameOver = function() { + this.state = GAMEOVER; + console.log("game over"); + player.active = false; + logo1.sprite.active = true; + scoreText.moveToCenter(); + this.gameOverTimer = 50; + gameOverText.visible = true; + scoreBg.visible = true; + this.sound.play("explosion") +} + +Engine.prototype.removeIntegral = function(integral) { + var i = this.gameObjectList.indexOf(integral); + this.gameObjectList.splice(i, 1); + this.unitsContainer.removeChild(integral.sprite); + delete integral; +} + +Engine.prototype.testForGameover = function() { + if (player.outOfScreen()) { + this.activateGameOver(); + } + + // collision detection + var g = this.gameObjectList; + var p = player.sprite + for (var i = 0; i < g.length; i++) { + if (g[i].objectType == "integral") { + var obj = g[i].sprite; + + var xdist = obj.position.x - p.position.x; + + if (xdist > -0.3 * obj.width && xdist < 0.2 * obj.width) { + var ydist = obj.position.y - p.position.y; + + if (ydist > -obj.height / 2 && ydist < obj.height / 2) { + this.activateGameOver(); + } + } + } + } +} + +Engine.prototype.spawnIntegral = function() { + var i = new Integral(Math.random() * Settings.STAGE_HEIGHT); + this.gameObjectList.push(i); + this.unitsContainer.addChild(i.sprite); +} + +Engine.prototype.updateSpawns = function() { + this.integralSpawnTimer -= 1; + + if (this.integralSpawnTimer < 0) { + this.spawnIntegral(); + this.integralSpawnTimer = 30 + Math.random() * 100; + } +} + +Engine.prototype.update = function() { + updateDeltaTime(); + if (this.state == GAME) + this.updateSpawns(); + + if (this.state == GAME || this.state == MENU) { + this.testForGameover(); + for (var i = 0; i < this.gameObjectList.length; i++) { + var obj = this.gameObjectList[i]; + obj.update(); + + // check if integral object has left the screen + if (obj.objectType == "integral") { + if (obj.sprite.x < -obj.sprite.width) + this.removeIntegral(obj); + } + } + } + + if (this.state == GAMEOVER) { + this.gameOverTimer -= 1; + } + + scoreText.update(); + + this.renderer.render(this.stage); +} + +Engine.prototype.resetPositions = function() { + for (var i = 0; i < this.gameObjectList.length; i++) { + this.gameObjectList[i].initPosition(); + } +} + +Engine.prototype.buttonPressed = function() { + player.boost(); + + if (this.state == MENU) { + this.activateGame(); + player.boost(); + } + else if (this.state == GAME) { + player.boost(); + } + else if (this.state == GAMEOVER) { + if (this.gameOverTimer < 0) + this.activateMenu(); + } +} + +Engine.prototype.setupGameObjects = function() { + // add player to gameobjectlist + this.gameObjectList = []; + + this.unitsContainer.addChild(player.sprite); + this.menuContainer.addChild(logo1.sprite); + this.menuContainer.addChild(logo2.sprite); + this.mapContainer.addChild(bg1.sprite); + this.mapContainer.addChild(bg2.sprite); + this.menuContainer.addChild(scoreBg); + this.menuContainer.addChild(scoreText); + this.menuContainer.addChild(gameOverText); + + this.gameObjectList = this.gameObjectList.concat([player, logo1, logo2, bg1, bg2]); + + k_space.press = this.buttonPressed.bind(this); + + this.stage.updateLayersOrder(); +} + +var engine = new Engine();
\ No newline at end of file diff --git a/src/gameobject.js b/src/gameobject.js new file mode 100644 index 0000000..0b50553 --- /dev/null +++ b/src/gameobject.js @@ -0,0 +1,20 @@ +function GameObject(texture) { + this.texture = PIXI.Texture.fromImage("res/" + texture + ".png"); + this.sprite = new PIXI.Sprite(this.texture); + + this.initPosition(); + this.active = true; + this.objectType = "gameobject"; +} + +GameObject.prototype.initPosition = function() { + this.sprite.anchor.x = 0.5; + this.sprite.anchor.y = 0.5; + + this.sprite.position.x = Settings.STAGE_WIDTH * 0.5; + this.sprite.position.y = Settings.STAGE_HEIGHT * 0.5; +} + +GameObject.prototype.update = function() { + +}
\ No newline at end of file diff --git a/src/keyboard.js b/src/keyboard.js new file mode 100644 index 0000000..8f9b12d --- /dev/null +++ b/src/keyboard.js @@ -0,0 +1,38 @@ +function keyboard(keyCode) { + var key = {}; + key.code = keyCode; + key.isDown = false; + key.isUp = true; + key.press = undefined; + key.release = undefined; + //The `downHandler` + key.downHandler = function(event) { + if (event.keyCode === key.code) { + if (key.isUp && key.press) key.press(); + key.isDown = true; + key.isUp = false; + } + event.preventDefault(); + }; + + //The `upHandler` + key.upHandler = function(event) { + if (event.keyCode === key.code) { + if (key.isDown && key.release) key.release(); + key.isDown = false; + key.isUp = true; + } + event.preventDefault(); + }; + + //Attach event listeners + window.addEventListener( + "keydown", key.downHandler.bind(key), false + ); + window.addEventListener( + "keyup", key.upHandler.bind(key), false + ); + return key; +} + +var k_space = keyboard(32) // space bar diff --git a/src/objecttypes.js b/src/objecttypes.js new file mode 100644 index 0000000..d7b0df4 --- /dev/null +++ b/src/objecttypes.js @@ -0,0 +1,107 @@ +// bg +function Background(x_offset) { + GameObject.call(this, "bg"); + this.x_offset = x_offset; + this.initPosition(); + + this.x_speed = 10 + this.objectType = "background"; +} + +Background.prototype = Object.create(GameObject.prototype); +Background.prototype.constructor = Background; + +Background.prototype.update = function() { + this.sprite.position.x -= this.x_speed + + if (this.sprite.position.x < -Settings.STAGE_WIDTH) { + this.sprite.position.x = Settings.STAGE_WIDTH - this.x_speed; + } +} + +Background.prototype.initPosition = function() { + this.sprite.position.x = this.x_offset; + this.sprite.position.y = 0; + this.sprite.anchor.x = 0; + this.sprite.anchor.y = 0; +} + +var bg1 = new Background(0); +var bg2 = new Background(Settings.STAGE_WIDTH); + +// logo +var logo1 = new GameObject("logo1"); +logo1.update = function() { + this.sprite.rotation = 0.1 * Math.sin(0.001 * Date.now()); +} + +logo1.initPosition = function() { + logo1.sprite.position.y = Settings.STAGE_WIDTH * 0.2 +} +logo1.initPosition(); + +// press space to play text +var logo2 = new GameObject("logo2"); +logo2.initPosition = function() { + this.sprite.position.y = Settings.STAGE_HEIGHT * 0.6; +} +logo2.initPosition(); + +// background box for score display at gameover +var scoreBg = new PIXI.Graphics(); +scoreBg.beginFill(0xAAAAAA, 1.0); +scoreBg.visible = false; + +// score display +var scoreText = new PIXI.Text("W", { font: '35px Arial', fill: 'black', align: 'left' }); +scoreText.visible = false; +scoreText.update = function() { + this.text = "W = " + player.score + " J"; +} + +scoreText.moveToCorner = function() { + this.position.x = Settings.STAGE_WIDTH * 0.7; + this.position.y = Settings.STAGE_HEIGHT * 0.1; +} + +scoreText.moveToCenter = function() { + this.position.x = Settings.STAGE_WIDTH * 0.5 - this.width / 2; + this.position.y = Settings.STAGE_HEIGHT * 0.5 - this.height / 2; +} +scoreText.moveToCorner(); + +// gameover screen title text +var gameOverText = new PIXI.Text("Nettovoiman tekemä työ:", { font: '35px Arial', fill: 'black', align: 'center' }); +gameOverText.visible = false; +gameOverText.position.x = Settings.STAGE_WIDTH * 0.5 - gameOverText.width / 2;; +gameOverText.position.y = Settings.STAGE_HEIGHT * 0.4 - gameOverText.height / 2;; + +// move the gameover bg box now that we now the width of the text +var yDiff = scoreText.position.y - gameOverText.position.y + gameOverText.height; +scoreBg.drawRect(gameOverText.position.x - 10, gameOverText.position.y - 10, gameOverText.width + 20, -yDiff); + +// integral sign +function Integral(y) { + GameObject.call(this, "int"); + + this.initPosition() + this.sprite.position.y = y; + + this.speed = -10; + this.objectType = "integral"; + +} + +Integral.prototype = Object.create(GameObject.prototype); +Integral.prototype.constructor = Integral; + +Integral.prototype.initPosition = function() { + this.sprite.position.x = Settings.STAGE_WIDTH + this.sprite.width; + this.sprite.position.y = Settings.STAGE_HEIGHT + this.sprite.height; + this.sprite.anchor.x = 0; + this.sprite.anchor.y = 0.5; +} + +Integral.prototype.update = function() { + this.sprite.position.x += this.speed; +}
\ No newline at end of file diff --git a/src/platformer.js b/src/platformer.js new file mode 100644 index 0000000..3d19130 --- /dev/null +++ b/src/platformer.js @@ -0,0 +1,9 @@ +document.body.appendChild(Engine.instance.renderer.view); + +requestAnimationFrame(animate); + +function animate() { + requestAnimationFrame(animate); + + Engine.instance.update(); +}
\ No newline at end of file diff --git a/src/player.js b/src/player.js new file mode 100644 index 0000000..64f00f8 --- /dev/null +++ b/src/player.js @@ -0,0 +1,67 @@ +function Player(texture) { + GameObject.call(this, texture); + this.active = false; + this.acceleration = 18; + this.boost_velocity = -70; + this.velocity = 0.0; + this.terminal_velocity = 60; + + this.score = 0; + + this.initPosition(); + + // bind space bar to boost up + //k_space.press = this.boost.bind(this); +} + +Player.prototype = Object.create(GameObject.prototype); +Player.prototype.constructor = Player; + +Player.prototype.initPosition = function() { + GameObject.prototype.initPosition.call(this); + + this.sprite.position.x = Settings.STAGE_WIDTH * 0.1; + this.sprite.position.y = Settings.STAGE_HEIGHT * 0.6; + this.sprite.rotation = 0; +} + +Player.prototype.updatePhysics = function() { + // update velocity + this.velocity += 0.01 * this.acceleration * dt; + if (this.velocity >= this.terminal_velocity) { + this.velocity = this.terminal_velocity; + } + + // update position + this.sprite.position.y += 0.01 * this.velocity * dt; + + // limit going upwards + this.sprite.position.y = Math.max(0, this.sprite.position.y); +} + +Player.prototype.updateControls = function() { + // TODO +} + +Player.prototype.boost = function() { + this.velocity = this.boost_velocity; + engine.sound.play("jump"); +} + +Player.prototype.outOfScreen = function() { + return this.sprite.position.y > Settings.STAGE_HEIGHT; +} + +Player.prototype.update = function() { + GameObject.prototype.update.call(this); + + this.sprite.rotation += 0.1; + + if (this.active) { + this.score += 1; + this.updatePhysics(); + this.updateControls(); + } +} + +var player = new Player("player");
\ No newline at end of file diff --git a/src/settings.js b/src/settings.js new file mode 100644 index 0000000..b515171 --- /dev/null +++ b/src/settings.js @@ -0,0 +1,15 @@ +var Settings = function() {} +Settings.STAGE_WIDTH = 800; +Settings.STAGE_HEIGHT = 600; +Settings.STAGE_BGCOLOR = 0xA0A0A0; + +var lastTime = Date.now(); +var dt = 0.0; + +function updateDeltaTime() { + var last = lastTime; + var current = Date.now(); + + lastTime = current; + dt = current - last; +}
\ No newline at end of file diff --git a/src/sound.js b/src/sound.js new file mode 100644 index 0000000..51f4330 --- /dev/null +++ b/src/sound.js @@ -0,0 +1,20 @@ +var Sound = function() { + // start music + this.bgMusic = new Howl({ + urls: ['res/bg.mp3'], + autoplay: true, + loop: true, + volume: 1, + buffer: true + }); + + this.sounds = {jump: new Howl({ urls: ['res/jump.wav'], buffer: true }), + start: new Howl({ urls: ['res/start.wav'], buffer: true }), + explosion: new Howl({ urls: ['res/explosion.wav'], buffer: true })}; + + this.play = function(effect) { + this.sounds[effect].play() + } + + return this; +}
\ No newline at end of file |
