Pen created for #cpc-stars, little 2d shoot em up. Have fun! :)
A Pen by Tom McQuillan on CodePen.
<div id="game_over" class="state-ui-container"> | |
<div class="console"> | |
<div class="ui-text ui-text--heading">GAME OVER!</div> | |
<div id="final_score" class="ui-text"></div> | |
<div class="ui-text">PRESS [ENTER] TO PLAY AGAIN!</div> | |
<div class="ui-text">PRESS [R] TO GO TO TITLE SCREEN</div> | |
</div> | |
</div> | |
<div id="title" class="state-ui-container"> | |
<div class="console"> | |
<div class="ui-text ui-text--heading">SPACE FORCE: X-ALPHA 2 TURBO</div> | |
<div class="ui-text">INSTRUCTIONS:</div> | |
<div class="ui-text">PRESS [ARROW KEYS] TO MOVE!</div> | |
<div class="ui-text">PRESS [SPACE] TO SHOOT!</div> | |
<div class="ui-text">PRESS [ENTER] TO PLAY!</div> | |
<div class="ui-text">PRESS [R] TO COME BACK TO THIS SCREEN</div> | |
</div> | |
</div> | |
<div id="game" class="state-ui-container"> | |
<div class="banner"> | |
<div id="score" class="ui-text">SCORE: 0</div> | |
<div id="lives" class="ui-text">LIVES: 3</div> | |
</div> | |
</div> | |
var TOP_TURN = false; | |
var canvas = document.createElement('canvas'); | |
var context = canvas.getContext('2d'); | |
context.globalAlpha = .1; | |
var fps = 1000 / 60; | |
var then = Date.now(); | |
var startTime = then; | |
/** | |
* Piskel was used to create my sprites. | |
* It is a free online editor for animated sprites & pixel art | |
* you should check it out (it's incredible) | |
* https://www.piskelapp.com/ | |
*/ | |
var speedUpSprite = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABdElEQVRYR82W0RXCIAxF0zXcpG7jnyP55xwuYDdxjXpSm/oIoQlHetA/BJLLy4N0IPxN5zkZlwbjc7CmbhOF9l9H2vZ/A3HyQuAsmbGWk2PgvYPg2g9ATXKJDHtqkst22TOYyaUUoogeA8SNnmSdXMohc3rMIfi/FACViEBM5xkBvKTWfA7AaKWTG1BagQgEqpKXwDu5UskqgQeBPmjqATRjBCL3ADp8rxQFE7YB6FqCSHKlTFsTdr+GP3oAn9+4Cbs/xcbb7nbE5s1IS+8RHNKOuSleYv18vH/7efI5cQrufxnfA5y8FFgLYq2dTjSPEHhPRFy7fA/UJN+qBcA1ybf9K/CAyaUEokRo/CDCkzPM8latalhjnEsARI0lwFpnCyKZUwBLDAcCVcgAIhBYBgIALEUEgtdkJYjKv4EqAE9+Pf9fHgiZTvujpQlrbsQhJUjMtXMTDjNh5AZkKrW8hl080P0ptt52rxs3b0bafB5Ay3b8BvT6cqvw5EPXAAAAAElFTkSuQmCC'; | |
var powerUpSprite = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAABwCAYAAAAXB/A7AAACGklEQVRYR+1ZsXHDMAwk1/AY6egVMkHKdBkpXcpM4BWiLmNkDeVAkcoLhEjAlKy7nFxZJv75AB+QbXmHr+E6Lq7XLsKXz0vzG0dgWKgSQexEYAFn5oTxC3AtBUndcB2XBKoCQJBIYFGxj4JcVMURUv3+XQ0sJ5BqtUENuq3MvK0yY9FMSKJhENvZOfc+ONU8eAuunAcExoWaEIyNTBZwJs4YvwaW0uEKKWaVQFPLJkFLRZOgpUJFUFOhImgdZ7WIx9agtXs2YL8Puq3Mvd06e77h3925t53jZHvVzYPwIcwDAuNCLRWMjSlYwPP0Sxt6DRhTQ5X0uYpgLR0TgaTCRCCpMBNwFWYCrsJEcGwN9vVBt5W5tzXzoGgmJNEQiO0cU7ko58GPNA8ubgywUJ0HEDvNAwN4TjdhvBac00OV9JmaQOxGKwFX8XgFeNRUi8crOLYG+/mg28rc25p2Rvsvvh90tXNMxX2qfi8E91L+XiAwLlTnAcRO88AAnmuWMN4C5rF0bSIo7o33EKCKYxRg0Y9RcGwN9vFBt5W5t1XzgDcTkmgIxHaOwKdBNQ/cdxD+TyQwLFSVQOzEZAFn5oTxd4GB5CQYxrMGm9Sg28rM25p2Rvsvvh/0tXOcbTfdPAjP0vOF2+hgoZoKbZRi0/MFA3iefxPGR9nanYv7+43+Wz8Jzhps4YPcRFY3JgPCwzqDI4tmwgbRTBRQ+wsmv4hBGUclzwAAAABJRU5ErkJggg==' | |
var bulletSprite = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAICAYAAADwdn+XAAAAQ0lEQVQoU2NkSPr/n4FUMI+REaYFzgALfPn//z83AwPjVwYGYmlUA6DG/v9PvKswDCBFM8g+6hsAMpUUV1AhECmMRgChtzPdurGgmgAAAABJRU5ErkJggg=='; | |
var burnSprite = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAABACAYAAAB7jnWuAAAAw0lEQVRoQ+2ZwQ3AIAwDYY7uP1rnoAIJBFXfPkt1F8A4l5CktcBfhc8vPgLu0tpVqlxQ7QfPMCAC+uFTBCJgd6CLUYsYMSdFhIHDAQsG5BCSAHbHvbLgnwy8C1EgVHOQQuTlgDoDRiW0asmI3jAMeDAw3wMkCzIbxoE4EAfiwO4AsSlZSylsSYXviGYICPs/p2P1k3wwoJ6KPPYDFgzsIjAGqL4wEPo5gEFoUYrVt1+VkErBQwD1LMv/kr170AiIA3HgARYMhEG2cflOAAAAAElFTkSuQmCC'; | |
var popCornSprite = 'data:image/png;base64,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'; | |
var shipSprite = 'data:image/png;base64,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'; | |
var explosionSprite = 'data:image/png;base64,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'; | |
canvas.id = 'viewport'; | |
canvas.width = window.innerWidth*.5; | |
canvas.height = window.innerHeight*.5; | |
context.imageSmoothingEnabled = false; | |
document.getElementsByTagName('body')[0].appendChild(canvas); | |
WAVE = 1800; | |
if (TOP_TURN) { | |
canvas.style.transform = 'scaleX(-1)'; | |
UP = 39; | |
DOWN = 37; | |
LEFT = 40; | |
RIGHT = 38; | |
SHOOT = 32; | |
RESET = 82; | |
START = 13; | |
} else { | |
UP = 38; | |
DOWN = 40; | |
LEFT = 37; | |
RIGHT = 39; | |
SHOOT = 32; | |
RESET = 82; | |
START = 13; | |
} | |
function State(name, updater, renderer) | |
{ | |
this.name = name; | |
this.updater = updater; | |
this.renderer = renderer; | |
} | |
function Intersection() { | |
} | |
Intersection.rectanglesIntersect = function(rect1, rect2) { | |
return ( | |
rect1.x < rect2.x + rect2.width && | |
rect1.x + rect1.width > rect2.x && | |
rect1.y < rect2.y + rect2.height && | |
rect1.height + rect1.y > rect2.y | |
); | |
} | |
function Star(x, y) { | |
var r = Math.max(50,Math.floor(Math.random()*256)); | |
var g = Math.max(125, Math.floor(Math.random()*256)); | |
var b = Math.max(240, Math.floor(Math.random()*256)); | |
this.x = Math.floor(x); | |
this.y = Math.floor(y); | |
var size = Math.floor(Math.random() * Star.MAX_SIZE); | |
this.width = size; | |
this.height = size; | |
this.variance = Math.max(Math.random(), .2); | |
this.color = 'rgb('+r+', '+g+', '+b+')'; | |
} | |
Star.SPEED = 5; | |
Star.MAX_SIZE = 2; | |
Star.prototype.update = function() { | |
if (game.overdrive) { | |
var travel = Star.SPEED*this.variance*6; | |
this.width = 50; | |
} else { | |
var travel = Star.SPEED*this.variance; | |
this.width = this.height; | |
} | |
this.x -= travel; | |
if(this.x + this.width < 0) { | |
this.x = canvas.width; | |
} | |
} | |
Game.prototype.updateScore = function() { | |
document.getElementById('score').innerHTML = 'SCORE: ' + this.score; | |
} | |
Game.prototype.updateLives = function() { | |
document.getElementById('lives').innerHTML = 'LIVES: ' + this.lives; | |
} | |
Star.prototype.render = function(context) { | |
if (game.overdrive) { | |
context.globalAlpha = .6; | |
} | |
context.fillStyle = (game.overdrive) ? 'rgba(125, 135, 255, 1)' : this.color; | |
context.fillRect(this.x, this.y, this.width, this.height); | |
context.globalAlpha = 1; | |
} | |
function Explosion(x, y) { | |
this.currentFrame = 0; | |
this.frames = 12; | |
this.buffer = 4; | |
this.currentBuffer = 0; | |
this.alive = false; | |
this.img = document.createElement('img'); | |
this.img.src = explosionSprite; | |
} | |
Explosion.prototype.reset = function() { | |
this.currentFrame = 0; | |
this.frames = 12; | |
this.buffer = 4; | |
this.currentBuffer = 0; | |
this.alive = false; | |
}; | |
Explosion.prototype.update = function() { | |
if (!this.alive) { | |
return; | |
} | |
this.x -= Popcorn.SPEED; | |
if (this.currentBuffer === this.buffer) { | |
this.currentBuffer = 0; | |
this.currentFrame++; | |
if (this.currentFrame === this.frames) { | |
this.reset(); | |
} | |
} | |
this.currentBuffer++; | |
} | |
Explosion.prototype.render = function(context) { | |
if (!this.alive) { | |
return; | |
} | |
context.drawImage( | |
this.img, | |
0, this.currentFrame * 32, 32, 32, | |
this.x-16, this.y-16, 64, 64 | |
); | |
} | |
function TitleState(name) | |
{ | |
State.call(this, name, this.update, this.render); | |
} | |
TitleState.prototype = new State(); | |
TitleState.prototype.init = function() { | |
game.overdrive = true; | |
context.setTransform(1, 0, 0, 1, 0, 0); | |
game.showUI('title'); | |
this.entities = []; | |
this.starField = []; | |
for (var i = 0; i < 1024; i++) { | |
this.starField.push( | |
new Star( | |
Math.random()*canvas.width, | |
Math.random()*canvas.height | |
) | |
); | |
} | |
} | |
TitleState.prototype.update = function() { | |
if (inputManager.start) { | |
game.setState(game.states.game); | |
game.currentState.init(); | |
} | |
this.starField.forEach(function(entity) { | |
entity.update(); | |
}) | |
} | |
TitleState.prototype.render = function(context) { | |
context.clearRect(0, 0, canvas.width, canvas.height); | |
this.starField.forEach(function(entity) { | |
entity.render(context); | |
}) | |
} | |
function GameOverState(name) | |
{ | |
State.call(this, name, this.update, this.render); | |
} | |
GameOverState.prototype = new State(); | |
GameOverState.prototype.init = function() { | |
context.setTransform(1, 0, 0, 1, 0, 0); | |
this.timer = 0; | |
console.log('Game Over'); | |
game.showUI('game_over'); | |
document.querySelector('#final_score').innerHTML = 'FINAL SCORE: ' + game.score; | |
} | |
GameOverState.prototype.update = function() { | |
if (inputManager.start) { | |
game.setState(game.states.game); | |
game.currentState.init(); | |
game.reset(); | |
} | |
this.timer++; | |
} | |
GameOverState.prototype.render = function(context) { | |
for (var i = 0; i < canvas.width; i++) { | |
context.drawImage( | |
canvas, | |
i, 0, 1, canvas.height, | |
i, Math.sin((i*20*Math.PI/180))*2, 1, canvas.height | |
); | |
} | |
for (var i = 0; i < canvas.height; i++) { | |
context.drawImage( | |
canvas, | |
i, 0, canvas.width, 1, | |
i, Math.sin((i*12*Math.PI/180))*2, canvas.width, 1 | |
); | |
} | |
if (this.timer > 60) { | |
context.globalAlpha = .3; | |
} | |
} | |
function GameState(name) | |
{ | |
State.call(this, name, this.update, this.render); | |
} | |
GameState.prototype = new State(); | |
GameState.prototype.init = function() { | |
game.overdrive = true; | |
this.overdriveTimer = 90; | |
context.setTransform(1, 0, 0, 1, 0, 0); | |
game.showUI('game'); | |
this.timer = 0; | |
this.tier1 = 1 * WAVE; | |
this.tier2 = 2 * WAVE; | |
this.tier3 = 3 * WAVE; | |
this.tier4 = 4 * WAVE; | |
this.enemyTimerEasy = 120; | |
this.enemyTimerMedium = 60; | |
this.enemyTimerHard = 30; | |
this.enemyTimerNightmare = 5; | |
this.currentEnemyTimer = this.enemyTimerEasy; | |
this.powerUpTimer = 1600; | |
this.starField = []; | |
for (var i = 0; i < 1024; i++) { | |
this.starField.push( | |
new Star( | |
Math.random()*canvas.width, | |
Math.random()*canvas.height | |
) | |
); | |
} | |
this.player = new Player(20, Math.floor(canvas.height * .5), 100, null); | |
for (var i = 0; i < 256; i++) { | |
this.player.bulletPool.push(new Bullet(this.player.x + 32, this.player.y + 16, 1, 15)); | |
} | |
this.enemyList = []; | |
for (var i = 0; i < 32; i++) { | |
this.enemyList.push(new Popcorn(canvas.width, Math.random() * (canvas.height - 32))); | |
} | |
this.explosions = []; | |
for (var i = 0; i < 32; i++) { | |
this.explosions.push(new Explosion(0, 0)); | |
} | |
this.powerUps = []; | |
for (var i = 0; i < 32; i++) { | |
this.powerUps.push(new PowerUp(0, 0)); | |
} | |
this.entities = [this.player]; | |
this.entities = this.entities.concat( | |
this.enemyList, | |
this.explosions, | |
this.powerUps, | |
this.player.bulletPool | |
); | |
console.log('game initialised'); | |
} | |
GameState.prototype.deployEnemies = function() { | |
if (this.timer && (this.timer % this.currentEnemyTimer === 0) ) { | |
var enemy = this.enemyList.find(function(enemy) { | |
return !enemy.alive; | |
}); | |
enemy.reset(); | |
enemy.x = canvas.width; | |
enemy.alive = true; | |
enemy.y = Math.max(4, (canvas.height * Math.random()) - 24); | |
} | |
} | |
GameState.prototype.deployPowerUps = function() { | |
if (this.timer && (this.timer % this.powerUpTimer === 0) ) { | |
if (Math.random() >= .01) { | |
var powerup = this.powerUps.find(function(powerup) { | |
return !powerup.alive; | |
}); | |
powerup.x = canvas.width; | |
powerup.alive = true; | |
powerup.y = (canvas.height * Math.random()) - 16; | |
} | |
} | |
} | |
GameState.prototype.update = function() { | |
if (this.timer > this.tier2) { | |
this.currentEnemyTimer = this.enemyTimerMedium; | |
} | |
if (this.timer > this.tier3) { | |
this.currentEnemyTimer = this.enemyTimerHard; | |
} | |
if (this.timer > this.tier4) { | |
this.currentEnemyTimer = this.enemyTimerNightmare; | |
} | |
if (this.overdriveTimer < this.timer) { | |
game.overdrive = false; | |
} | |
this.timer++; | |
this.deployEnemies(); | |
this.deployPowerUps(); | |
this.entities.forEach(function(entity) { | |
entity.update(); | |
}); | |
this.player.bulletPool.forEach(function(bullet) { | |
if (!bullet.alive) { | |
return; | |
} | |
game.currentState.enemyList.forEach(function(enemy) { | |
if (!enemy.alive) { | |
return; | |
} | |
if (Intersection.rectanglesIntersect(bullet, enemy)) { | |
enemy.takeDamage(10); | |
bullet.alive = false; | |
if (!enemy.alive) { | |
game.score += enemy.value; | |
game.updateScore(); | |
enemy.hit = true; | |
var explosion = game.currentState.explosions.find(notAlive); | |
explosion.x = enemy.x; | |
explosion.y = enemy.y; | |
explosion.alive = true; | |
} | |
} | |
}); | |
}); | |
var player = game.currentState.player; | |
if (player.alive) { | |
this.enemyList.forEach(function(enemy) { | |
if(!enemy.alive) { | |
return; | |
} | |
var playerHitBox = player.getHitBox(); | |
if(Intersection.rectanglesIntersect(enemy, playerHitBox)) { | |
player.takeDamage(500); | |
enemy.takeDamage(500); | |
game.lives--; | |
game.updateLives(); | |
var explosion = game.currentState.explosions.find(notAlive); | |
explosion.x = enemy.x; | |
explosion.y = enemy.y; | |
explosion.alive = true; | |
var explosion = game.currentState.explosions.find(notAlive); | |
explosion.x = player.x; | |
explosion.y = player.y; | |
explosion.alive = true; | |
if (game.lives === 0) { | |
game.setState(game.states.game_over); | |
game.currentState.init(); | |
} | |
} | |
}); | |
this.powerUps.forEach(function(powerup) { | |
if (!powerup.alive) { | |
return; | |
} | |
if (Intersection.rectanglesIntersect(powerup, player.getHitBox())) { | |
player.powerLevel++; | |
powerup.reset(); | |
game.score += powerup.value; | |
game.updateScore(); | |
} | |
}); | |
} | |
} | |
notAlive = function(item){ | |
return !item.alive; | |
} | |
alive = function(item) { | |
return alive; | |
} | |
GameState.prototype.renderBackground = function(context) { | |
this.starField.forEach(function(star) { | |
star.update(); | |
star.render(context); | |
}); | |
} | |
GameState.prototype.render = function(context) { | |
context.fillStyle = '#000'; | |
context.fillRect(0, 0, canvas.width, canvas.height); | |
context.globalAlpha = 1; | |
this.renderBackground(context); | |
this.entities.forEach( | |
function(entity){ | |
entity.render(context); | |
} | |
); | |
} | |
function Game() | |
{ | |
this.reset(); | |
this.states = {}; | |
this.states['game'] = new GameState('game'); | |
this.states['title'] = new TitleState('title'); | |
this.states['game_over'] = new GameOverState('game_over'); | |
this.entities = []; | |
} | |
Game.prototype.reset = function() { | |
this.score = 0; | |
this.lives = 3; | |
this.updateScore(); | |
this.updateLives(); | |
} | |
Game.prototype.setState = function(state) { | |
this.currentState = state; | |
} | |
Game.prototype.showUI = function(name) { | |
document.querySelectorAll('.state-ui-container').forEach(function(element) { | |
element.style.display = 'none'; | |
}); | |
document.querySelector('#'+name).style.display = 'flex'; | |
} | |
function Ship(x, y, width, height, health) | |
{ | |
this.x = x; | |
this.y = y; | |
this.width = width; | |
this.height = height; | |
this.health = health; | |
this.hit = false; | |
this.alive = true; | |
this.vx = 0; | |
this.vy = 0; | |
} | |
Ship.prototype.render = function(context) { | |
context.fillStyle = '#666'; | |
context.fillRect(this.x, this.y, this.width, this.height); | |
} | |
Ship.prototype.takeDamage = function(damage) { | |
this.health -= damage; | |
if (this.health <= 0) { | |
this.alive = false; | |
} | |
} | |
function Bullet(x, y, dir, speed) { | |
this.vx = 0; | |
this.vy = 0; | |
this.width = 16; | |
this.height = 8; | |
this.x = x; | |
this.y = y; | |
this.dir = dir; | |
this.speed = speed; | |
this.alive = false; | |
this.img = document.createElement('img'); | |
this.img.src = bulletSprite; | |
} | |
Bullet.prototype.update = function() { | |
if (!this.alive) { | |
return; | |
} | |
if (this.dir === 1) this.vx = this.speed + (Math.min(game.currentState.player.powerLevel * 2, 20)); | |
if (this.dir === -1) this.vx = this.speed; | |
this.x += this.vx; | |
if (this.x > canvas.width) { | |
this.alive = false; | |
} | |
} | |
Bullet.prototype.render = function(context) { | |
if (!this.alive) { | |
return | |
} | |
context.drawImage(this.img, 0, 0, 16, 8, this.x, this.y, this.width, this.height); | |
} | |
function PowerUp(x, y) { | |
this.x = x; | |
this.y = y; | |
this.timer = Math.random() * 256; | |
this.currentFrame = 0; | |
this.currentBuffer = 0; | |
this.buffer = 4; | |
this.jump = canvas.height * .5; | |
this.speed = 3; | |
this.frames = 7; | |
this.width = 16; | |
this.height = 16; | |
this.img = document.createElement('img'); | |
this.img.src = powerUpSprite; | |
this.value = 20; | |
} | |
PowerUp.prototype.update = function() { | |
this.vy = Math.cos(this.timer) * this.jump; | |
this.timer += .03; | |
this.y = canvas.height * .5 + this.vy; | |
this.x -= this.speed; | |
if (this.x + this.width <= 0) { | |
this.reset(); | |
} | |
} | |
PowerUp.prototype.reset = function() { | |
this.alive = false; | |
} | |
PowerUp.prototype.render = function(context) { | |
if (!this.alive) { | |
return; | |
} | |
if (this.currentBuffer === this.buffer) { | |
this.currentBuffer = 0; | |
this.currentFrame ++; | |
if (this.currentFrame === this.frames) { | |
this.currentFrame = 0; | |
} | |
} | |
this.currentBuffer++; | |
context.drawImage( | |
this.img, 0, this.currentFrame * 16, 16, 16, | |
this.x, this.y, this.width, this.height | |
) | |
} | |
function Player(x, y, health, weapon) | |
{ | |
Ship.call(this, x, y, 32, 32, health); | |
this.burning = false; | |
this.frame = 0; | |
this.burnFrame = 0; | |
this.weapon = weapon; | |
this.speed = 5; | |
this.powerLevel = 1; | |
this.bulletTimer = 5; | |
this.bulletCoolDown = 5; | |
this.img = document.createElement('img'); | |
this.burnImg = document.createElement('img'); | |
this.img.src = shipSprite; | |
this.burnImg.src = burnSprite; | |
this.bulletPool = []; | |
this.hitBoxSize = [8, 8]; | |
} | |
Player.prototype = new Ship(); | |
Player.prototype.getHitBox = function() { | |
return { | |
x: this.x + (this.width * .5) - (this.hitBoxSize[0] * .5), | |
y: this.y + (this.height * .5) - (this.hitBoxSize[1] * .5), | |
width: this.hitBoxSize[0], | |
height: this.hitBoxSize[1], | |
} | |
} | |
Player.prototype.update = function() { | |
if (!this.alive) { | |
if (inputManager.start) { | |
game.currentState.init(); | |
} | |
return; | |
} | |
this.vx = 0; | |
this.vy = 0; | |
if (inputManager.upPressed) { | |
this.vy -= this.speed; | |
} | |
if (inputManager.downPressed) { | |
this.vy += this.speed; | |
} | |
if (inputManager.rightPressed) { | |
this.vx += this.speed; | |
this.burning = true; | |
} else { | |
this.burning = false; | |
} | |
if (inputManager.leftPressed) { | |
this.vx -= this.speed; | |
this.burning = false; | |
} | |
if (inputManager.shooting || game.autoShoot) { | |
if (this.bulletCoolDown === this.bulletTimer) { | |
this.shoot(); | |
this.bulletTimer = 0; | |
} else { | |
this.bulletTimer++; | |
} | |
} | |
this.x += this.vx; | |
this.y += this.vy; | |
if (this.x < 0) { | |
this.x = 0; | |
} | |
if (this.y < 0) { | |
this.y = 0; | |
} | |
if (this.x+this.width > canvas.width) { | |
this.x = canvas.width - this.width; | |
} | |
if (this.y+this.height > canvas.height) { | |
this.y = canvas.height - this.height; | |
} | |
} | |
Player.prototype.shoot = function() { | |
if (this.powerLevel === 1) { | |
var bullet = this.bulletPool.find(notAlive); | |
if (!bullet) { | |
return; | |
} | |
bullet.x = this.x + this.width - bullet.width; | |
bullet.y = (this.y + (this.height * .5)) - (bullet.height * .5); | |
bullet.alive = true; | |
} | |
if (this.powerLevel === 2) { | |
var bullet = this.bulletPool.find(notAlive); | |
if (!bullet) { | |
return; | |
} | |
bullet.alive = true; | |
var bullet2 = this.bulletPool.find(notAlive); | |
if (!bullet) { | |
return; | |
} | |
bullet2.alive = true; | |
bullet.x = this.x + this.width - bullet.width; | |
bullet.y = (this.y + (this.height * .5)) - (bullet.height * .5) - 6; | |
bullet2.x = this.x + this.width - bullet2.width; | |
bullet2.y = (this.y + (this.height * .5)) - (bullet2.height * .5) + 6; | |
} | |
if (this.powerLevel >= 3) { | |
var bullet = this.bulletPool.find(notAlive); | |
if (!bullet) { | |
return; | |
} | |
bullet.alive = true; | |
var bullet2 = this.bulletPool.find(notAlive); | |
if (!bullet2) { | |
return; | |
} | |
bullet2.alive = true; | |
var bullet3 = this.bulletPool.find(notAlive); | |
if (!bullet3) { | |
return; | |
} | |
bullet3.alive = true; | |
bullet.x = this.x + this.width - bullet.width; | |
bullet.y = (this.y + (this.height * .5)) - (bullet.height * .5) - 12; | |
bullet2.x = this.x + this.width - bullet2.width + 8; | |
bullet2.y = (this.y + (this.height * .5)) - (bullet2.height * .5); | |
bullet3.x = this.x + this.width - bullet3.width; | |
bullet3.y = (this.y + (this.height * .5)) - (bullet3.height * .5) + 12; | |
} | |
if (this.powerLevel >= 5) { | |
var bullet = this.bulletPool.find(notAlive); | |
if (!bullet) { | |
return; | |
} | |
bullet.alive = true; | |
var bullet2 = this.bulletPool.find(notAlive); | |
if (!bullet2) { | |
return; | |
} | |
bullet2.alive = true; | |
bullet.x = this.x + this.width - bullet.width - 8; | |
bullet.y = (this.y + (this.height * .5)) - (bullet.height * .5) - 24; | |
bullet2.x = this.x + this.width - bullet2.width - 8; | |
bullet2.y = (this.y + (this.height * .5)) - (bullet2.height * .5) + 24; | |
} | |
} | |
Player.prototype.render = function(context) { | |
if (!this.alive) { | |
return; | |
} | |
this.buffer = this.buffer ? this.buffer + 1 : 1; | |
if(this.buffer && this.buffer == 4) { | |
this.frame += 1; | |
if (this.frame >= 10) this.frame = 0; | |
this.burnFrame += 1; | |
if (this.burnFrame >= 2) this.burnFrame = 0; | |
this.buffer = 0; | |
} | |
context.drawImage( | |
this.img, 0, this.frame * 32, 32, 32, | |
this.x, this.y, this.width, this.height | |
) | |
if (this.burning) { | |
context.drawImage( | |
this.burnImg, 0, this.burnFrame * 32, 32, 32, | |
this.x, this.y, this.width, this.height | |
) | |
} | |
this.bulletPool.forEach(function(bullet) { | |
if (!bullet.alive) { | |
return false; | |
} | |
bullet.render(context); | |
}) | |
} | |
function Popcorn(x, y) | |
{ | |
Ship.call(this, x, y, 32, 32, Popcorn.HEALTH); | |
this.img = document.createElement('img'); | |
this.img.src = popCornSprite; | |
this.frames = 12; | |
this.buffer = 4; | |
this.speed = Popcorn.SPEED; | |
this.value = 5; | |
this.healthMax = Popcorn.HEALTH; | |
this.reset(); | |
} | |
Popcorn.prototype = new Ship(); | |
Popcorn.SPEED = 5; | |
Popcorn.HEALTH = 80; | |
Popcorn.prototype.reset = function() { | |
this.x = canvas.width; | |
this.y = Math.random() * canvas.height - this.height; | |
this.currentFrame = 0; | |
this.currentBuffer = 0; | |
this.alive = false; | |
this.health = Popcorn.HEALTH; | |
} | |
Popcorn.prototype.update = function() { | |
this.vx = -this.speed; | |
this.x += this.vx; | |
if (this.x + this.width <= 0) { | |
this.reset(); | |
} | |
} | |
Popcorn.prototype.render = function(context) { | |
if (!this.alive) { | |
return; | |
} | |
if (this.currentBuffer === this.buffer) { | |
this.currentBuffer = 0; | |
this.currentFrame ++; | |
if (this.currentFrame === this.frames) { | |
this.currentFrame = 0; | |
} | |
} | |
context.drawImage( | |
this.img, 0, this.currentFrame * 32, 32, 32, | |
this.x, this.y, this.width, this.height | |
) | |
context.fillStyle = '#f00'; | |
context.fillRect(this.x, this.y - 2, this.width, 1); | |
context.fillStyle = '#0f0'; | |
this.perc = this.health/ this.healthMax; | |
context.fillRect(this.x, this.y - 2, this.width * this.perc , 1) | |
if (this.hit) { | |
var tmpOperation = context.globalCompositeOperation | |
context.globalCompositeOperation = 'color-dodge'; | |
context.drawImage( | |
this.img, 0, this.currentFrame * 32, 32, 32, | |
this.x, this.y, this.width, this.height | |
) | |
context.drawImage( | |
this.img, 0, this.currentFrame * 32, 32, 32, | |
this.x, this.y, this.width, this.height | |
) | |
context.globalCompositeOperation = tmpOperation; | |
this.hit = false; | |
} | |
this.currentBuffer++; | |
} | |
Game.prototype.update = function() { | |
this.currentState.update(); | |
} | |
Game.prototype.render = function(context) { | |
this.currentState.render(context); | |
} | |
Game.prototype.loop = function() { | |
window.requestAnimationFrame(function(){this.loop()}.bind(this)); | |
now = Date.now(); | |
dt = now - then; | |
if (dt <= fps) { return } | |
then = now - (dt % fps); | |
this.update(); | |
this.render(context); | |
} | |
Game.prototype.init = function() { | |
this.autoShoot = true; | |
this.setState(this.states.title); | |
this.currentState.init(); | |
window.requestAnimationFrame(function(){ this.loop() }.bind(this)); | |
} | |
var game = new Game(); | |
function InputManager() { | |
this.upPressed = false; | |
this.downPressed = false; | |
this.leftPressed = false; | |
this.rightPressed = false; | |
this.shooting = false; | |
this.start = false; | |
} | |
InputManager.prototype.handleKey = function(e, state) { | |
switch(e.keyCode) { | |
case InputManager.UP: | |
this.upPressed = state; | |
break; | |
case InputManager.DOWN: | |
this.downPressed = state; | |
break; | |
case InputManager.LEFT: | |
this.leftPressed = state; | |
break; | |
case InputManager.RIGHT: | |
this.rightPressed = state; | |
break; | |
case InputManager.SHOOT: | |
this.shooting = state; | |
break; | |
case InputManager.RESET: | |
game.reset(); | |
game.setState(game.states.title); | |
game.currentState.init(); | |
break; | |
case InputManager.START: | |
this.start = state; | |
break; | |
} | |
} | |
InputManager.UP = UP; | |
InputManager.DOWN = DOWN; | |
InputManager.LEFT = LEFT; | |
InputManager.RIGHT = RIGHT; | |
InputManager.SHOOT = SHOOT; | |
InputManager.RESET = RESET; | |
InputManager.START = START; | |
var inputManager = new InputManager(); | |
window.addEventListener( | |
'keydown', | |
function(e) { | |
game.autoShoot = false; | |
this.handleKey(e, true) | |
}.bind(inputManager) | |
); | |
window.addEventListener( | |
'keyup', | |
function(e){ | |
this.handleKey(e, false) | |
}.bind(inputManager) | |
); | |
game.init(); |
Pen created for #cpc-stars, little 2d shoot em up. Have fun! :)
A Pen by Tom McQuillan on CodePen.
* { | |
margin: 0; | |
padding: 0; | |
} | |
body { | |
font-size: 24px; | |
} | |
#viewport { | |
background: #020408; | |
display: block; | |
width: 100%; | |
height: 100%; | |
image-rendering: crisp-edges; | |
image-rendering: pixelated; | |
} | |
.state-ui-container { | |
display: flex; | |
flex-direction: row; | |
position: absolute; | |
justify-content: left; | |
align-items: left; | |
} | |
.ui-text { | |
user-select: none; | |
font-family: arial; | |
font-size: 1em; | |
font-weight: bold; | |
font-variant-numeric: tabular-nums; | |
margin: 10px; | |
color: #e4e4e4; | |
text-shadow: 0 2px 2px rgba(125,0,0,.51), | |
0 0 10px rgba(255,0,255,1), | |
0 0 10px rgba(255,0,255,1); | |
text-align: left; | |
} | |
#score { | |
left: 0; | |
} | |
#lives { | |
right: 0; | |
} | |
.ui-text--heading { | |
font-size: 4em; | |
} | |
.state-ui-container { | |
width: 100%; | |
display: none; | |
height: 100%; | |
justify-content: center; | |
} | |
.console { | |
align-self: center; | |
} | |
.banner { | |
align-self: flex-start; | |
} |