Intro to GameDev and the Phaser Framework
DevLeague is a FullStack coding boot camp
focusing on Web Application Development
We love games too!
And we love to apply our skills towards creating awesome things
Play : exploring the limits of a system
Players want to achieve the highest scores and win
GameDevs create the platform to make this happen in fun and interesting ways
When you start do design your game, define these
The 3 "C"s
When you start do design your game, decide these
Perspective
How many players?
Art, Animation, Motivation
What interactions will be provided for gameplay?
More things to consider...
in the browser
http://opengameart.org/content/vertical-shmup-set-2-m484-games
https://phaser.io/tutorials/making-your-first-phaser-game/index
mkdir Phaser-shmup
cd Phaser-shmup
git initmkdir js assets
touch index.html js/game.js.
├── assets
├── index.html
└── js
└── game.jsproject directory should look like this
use emmet if you have it
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Phaser SHMUP</title>
</head>
<body>
<h1>Phaser SHMUP</h1>
</body>
</html>go to https://cdnjs.com/libraries/phaser-ce
to get the latest version of phaser.min.js
<body>
<h1>Phaser SHMUP</h1>
<script src="https://cdnjs.cloudflare.com/ajax/libs/phaser-ce/2.10.0/phaser.min.js"></script>
</body> <body>
<h1>Phaser SHMUP</h1>
<script src="https://cdnjs.cloudflare.com/ajax/libs/phaser-ce/2.10.0/phaser.min.js"></script>
<script src="js/game.js"></script>
</body>(Phaser => {
console.log(Phaser);
})(window.Phaser);if you have live-server
or use python
live-serverpython -m SimpleHTTPServerObject {VERSION: "2.6.2", GAMES: Array[0], AUTO: 0, CANVAS: 1, WEBGL: 2…}you should see this in your Chrome developer console
(Phaser => {
const GAME_WIDTH = 460;
const GAME_HEIGHT = 600;
const GAME_CONTAINER_ID = 'game';
const game = new Phaser.Game(GAME_WIDTH, GAME_HEIGHT, Phaser.AUTO, GAME_CONTAINER_ID, { preload, create, update });
function preload() {
};
function create() {
};
function update() {
};
})(window.Phaser);
https://photonstorm.github.io/phaser-ce/Phaser.Game.html
<h1>Phaser SHMUP</h1>
<div id="game"></div> Phaser v2.6.2 | Pixi.js | WebGL | WebAudio http://phaser.io ♥♥♥
( cd assets;
curl -O http://gomagames.com/assets/shmup-spritesheet-140x56-28x28-tile.png )const GFX = 'gfx';
function preload() {
game.load.spritesheet(GFX, '../assets/shmup-spritesheet-140x56-28x28-tile.png', 28, 28);
};
let player;
function create() {
player = game.add.sprite(100, 100, GFX, 8);
};const INITIAL_MOVESPEED = 4;
function create() {
player = game.add.sprite(100, 100, GFX, 8);
player.moveSpeed = INITIAL_MOVESPEED;
};let cursors;
function create() {
cursors = game.input.keyboard.createCursorKeys();
player = game.add.sprite(100, 100, GFX, 8);
player.moveSpeed = INITIAL_MOVESPEED;
};a new function, above the update function
function handlePlayerMovement() {
switch( true ){
case cursors.left.isDown:
player.x -= player.moveSpeed;
break;
case cursors.right.isDown:
player.x += player.moveSpeed;
break;
}
switch( true ){
case cursors.down.isDown:
player.y += player.moveSpeed;
break;
case cursors.up.isDown:
player.y -= player.moveSpeed;
break;
}
};
function update() {
handlePlayerMovement();
};function handlePlayerMovement() {
let movingH = Math.sqrt(2);
let movingV = Math.sqrt(2);
if( cursors.up.isDown || cursors.down.isDown){
movingH = 1; // slow down diagonal movement
}
if( cursors.left.isDown || cursors.right.isDown){
movingV = 1; // slow down diagonal movement
}
switch( true ){
case cursors.left.isDown:
player.x -= player.moveSpeed * movingH;
break;
case cursors.right.isDown:
player.x += player.moveSpeed * movingH;
break;
}
switch( true ){
case cursors.down.isDown:
player.y += player.moveSpeed * movingV;
break;
case cursors.up.isDown:
player.y -= player.moveSpeed * movingV;
break;
}
};
let playerBullets;
function create() {
cursors = game.input.keyboard.createCursorKeys();
player = game.add.sprite(100, 100, GFX, 8);
player.moveSpeed = INITIAL_MOVESPEED;
playerBullets = game.add.group();
};
function create() {
cursors = game.input.keyboard.createCursorKeys();
cursors.fire = game.input.keyboard.addKey(Phaser.KeyCode.SPACEBAR);
cursors.fire.onUp.add( handlePlayerFire );
player = game.add.sprite(100, 100, GFX, 8);
player.moveSpeed = INITIAL_MOVESPEED;
playerBullets = game.add.group();
};
function handlePlayerFire() {
console.log("fire");
};function handlePlayerFire() {
playerBullets.add( game.add.sprite(player.x, player.y, GFX, 7) );
};function update() {
handlePlayerMovement();
handleBulletAnimations();
};
const PLAYER_BULLET_SPEED = 6;
function handleBulletAnimations() {
playerBullets.children.forEach( bullet => bullet.y -= PLAYER_BULLET_SPEED );
};in a new function above update
function cleanup() {
playerBullets.children
.filter( bullet => bullet.y < 0 )
.forEach( bullet => bullet.destroy() );
};
function update() {
handlePlayerMovement();
handleBulletAnimations();
cleanup();
};let enemies;
function create() {
cursors = game.input.keyboard.createCursorKeys();
cursors.fire = game.input.keyboard.addKey(Phaser.KeyCode.SPACEBAR);
cursors.fire.onUp.add( handlePlayerFire );
player = game.add.sprite(100, 100, GFX, 8);
player.moveSpeed = INITIAL_MOVESPEED;
playerBullets = game.add.group();
enemies = game.add.group();
};
const ENEMY_SPAWN_FREQ = 100; // higher is less frequent
const randomGenerator = new Phaser.RandomDataGenerator();
function randomlySpawnEnemy() {
if(randomGenerator.between(0, ENEMY_SPAWN_FREQ) === 0) {
let randomX = randomGenerator.between(0, GAME_WIDTH);
enemies.add( game.add.sprite(randomX, -24, GFX, 0));
}
} const update = _ => {
handlePlayerMovement();
handleBulletAnimations();
randomlySpawnEnemy();
cleanup();
};
const ENEMY_SPEED = 4.5;
function handleEnemyActions() {
enemies.children.forEach( enemy => enemy.y += ENEMY_SPEED );
}; function update() {
handlePlayerMovement();
handleBulletAnimations();
handleEnemyActions();
randomlySpawnEnemy();
cleanup();
};
function removeBullet(bullet) {
bullet.destroy();
}
function destroyEnemy(enemy) {
enemy.kill();
}
function handleCollisions() {
// check if any bullets touch any enemies
let enemiesHit = enemies.children
.filter( enemy => enemy.alive )
.filter( enemy =>
playerBullets.children.some(
bullet => enemy.overlap(bullet)
)
);
if( enemiesHit.length ){
// clean up bullets that land
playerBullets.children
.filter( bullet => bullet.overlap(enemies) )
.forEach( removeBullet );
enemiesHit.forEach( destroyEnemy );
}
}; function update() {
handlePlayerMovement();
handleBulletAnimations();
handleEnemyActions();
handleCollisions();
randomlySpawnEnemy();
cleanup();
}; functions handleCollisions() {
// check if any bullets touch any enemies
let enemiesHit = enemies.children
.filter( enemy => enemy.alive )
.filter( enemy => enemy.overlap(playerBullets) );
if( enemiesHit.length){
// clean up bullets that land
playerBullets.children
.filter( bullet => bullet.overlap(enemies) )
.forEach( removeBullet );
enemiesHit.forEach( destroyEnemy );
}
// check if enemies hit the player
enemiesHit = enemies.children
.filter( enemy => enemy.overlap(player) );
if( enemiesHit.length){
handlePlayerHit();
enemiesHit.forEach( destroyEnemy );
}
};
function handlePlayerHit() {
gameOver();
}; function gameOver() {
game.state.destroy();
game.add.text(90, 200, 'YOUR HEAD ASPLODE', { fill: '#FFFFFF' });
};function gameOver() {
game.state.destroy();
game.add.text(90, 200, 'YOUR HEAD ASPLODE', { fill: '#FFFFFF' });
let playAgain = game.add.text(120, 300, 'Play Again', { fill: '#FFFFFF' });
playAgain.inputEnabled = true;
playAgain.events.onInputUp.add(() => window.location.reload());
};
let enemyBullets;
function create() {
cursors = game.input.keyboard.createCursorKeys();
cursors.fire = game.input.keyboard.addKey(Phaser.KeyCode.SPACEBAR);
cursors.fire.onUp.add( handlePlayerFire );
player = game.add.sprite(100, 100, GFX, 8);
player.moveSpeed = INITIAL_MOVESPEED;
playerBullets = game.add.group();
enemies = game.add.group();
enemyBullets = game.add.group();
};function create() {
game.physics.startSystem(Phaser.Physics.ARCADE);
cursors = game.input.keyboard.createCursorKeys();
cursors.fire = game.input.keyboard.addKey(Phaser.KeyCode.SPACEBAR);
cursors.fire.onUp.add( handlePlayerFire );
player = game.add.sprite(100, 100, GFX, 8);
player.moveSpeed = INITIAL_MOVESPEED;
playerBullets = game.add.group();
enemies = game.add.group();
enemyBullets = game.add.group();
enemyBullets.enableBody = true;
};
const ENEMY_FIRE_FREQ = 30; // higher is less frequent
function randomEnemyFire(enemy) {
if( randomGenerator.between(0, ENEMY_FIRE_FREQ) === 0 ){
let enemyBullet = game.add.sprite(enemy.x, enemy.y, GFX, 9);
enemyBullet.checkWorldBounds = true;
enemyBullet.outOfBoundsKill = true;
enemyBullets.add( enemyBullet );
}
};
function handleEnemyActions() {
enemies.children.forEach( enemy => enemy.y += ENEMY_SPEED );
enemies.children.forEach( enemy => randomEnemyFire(enemy) );
};const ENEMY_BULLET_ACCEL = 100;
function handleBulletAnimations() {
playerBullets.children.forEach( bullet => bullet.y -= PLAYER_BULLET_SPEED );
enemyBullets.children.forEach( bullet => {
game.physics.arcade.accelerateToObject(bullet, player, ENEMY_BULLET_ACCEL);
});
};
function handleCollisions() {
// check if any bullets touch any enemies
// ...
// check if enemies hit the player
// ...
// check if enemy bullets hit the player
let enemyBulletsLanded = enemyBullets.children
.filter( bullet => bullet.overlap(player) );
if( enemyBulletsLanded.length){
handlePlayerHit(); // count as one hit
enemyBulletsLanded.forEach( removeBullet );
}
};
function cleanup() {
playerBullets.children
.filter( bullet => bullet.y < 0 )
.forEach( bullet => bullet.destroy() );
enemies.children
.filter( enemy => enemy.y > GAME_HEIGHT || !enemy.alive )
.forEach( enemy => enemy.destroy() );
enemyBullets.children
.filter( bullet => !bullet.alive )
.forEach( bullet => bullet.destroy() );
};function randomEnemyFire(enemy) {
if(randomGenerator.between(0, ENEMY_FIRE_FREQ) === 0){
let enemyBullet = game.add.sprite(enemy.x, enemy.y, GFX, 9);
enemyBullet.checkWorldBounds = true;
enemyBullet.outOfBoundsKill = true;
enemyBullets.add( enemyBullet );
}
};remember this?
Note how the MVP iterations vs. stretch goals are defined