Game "Moon War"

Appearance

Main hero

class Hero {
constructor(position, lifesCount) {
this.pos = position;
this.lifesCount = lifesCount;
this.sprite = new Sprite('../img/hero.png', [0, 0], [58, 58.4], 2, [0, 1, 2, 1]);
this.down = new Sprite('../img/hero.png', [0, 0], [58, 58.4], 3, [0, 1, 2, 1]);
this.up = new Sprite('../img/hero.png', [0, 173], [58, 58.4], 3, [0, 1, 2, 1]);
this.left = new Sprite('../img/hero.png', [0, 58], [58, 58.4], 3, [0, 1, 2, 1]);
this.right = new Sprite('../img/hero.png', [0, 116.6], [58, 58.4], 3, [0, 1, 2, 1]);
}
}
export default Hero;Enemies

class Enemy {
constructor(pos) {
this.pos = pos;
}
}
class EnemyEasy extends Enemy {
constructor(pos) {
super(pos);
this.lifesCount = 1;
this.sprite = new Sprite('../img/ufo.png',[115, 89], [52, 38.5], 7,[0, 1, 2, 3, 4, 5, 6, 7]);
}
}
class EnemyBoss extends Enemy {
constructor(pos) {
super(pos);
this.lifesCount = 6;
this.sprite = new Sprite('../img/enemy-boss.png',[0, 0],[128, 128],6,[0, 1, 2, 3, 4, 3, 2, 1]);
}
}
export { EnemyEasy, EnemyBoss };
Towers

class Tower {
constructor(pos) {
this.pos = pos;
}
}
class FiringTower extends Tower {
constructor(pos) {
super(pos);
this.lastFire = Date.now();
this.sprite = new Sprite('../img/tower.png', [31, 0], [48, 118]);
}
}
class TrapTower extends Tower {
constructor(pos) {
super(pos);
this.sprite = new Sprite('../img/trap-tower.png',[0, 0],[65, 98],6,[0, 1, 2, 3, 2, 1],);
}
}
export { FiringTower, TrapTower };

class Bullet {
constructor(pos, angle) {
this.pos = pos;
this.angle = angle;
this.sprite = new Sprite('../img/bullet.png', [0, 0], [24, 24]);
}
}
export default Bullet;Bullet

Explosions

class Explosion {
constructor(pos) {
this.pos = pos;
}
}
class EasyExplosion extends Explosion {
constructor(pos) {
super(pos);
this.sprite = new Sprite(
"../img/ufo.png",
[30, 196],
[73, 59],
15,
[0, 1, 2, 3, 4, 5, 6, 7],
null,
true
);
}
}
class BigExplosion extends Explosion {
constructor(pos) {
super(pos);
this.sprite = new Sprite(
"../img/enemy-boss-explosion.png",
[0, 0],
[96, 96],
15,
[0, 1, 2, 3, 4, 5],
null,
true
);
}
}
export { EasyExplosion, BigExplosion };

Bonuses

class Bonus {
constructor(pos, pathToImage) {
this.pos = pos;
this.sprite = new Sprite(
pathToImage,
[0, 0],
[32, 31],
6,
[0, 1, 2, 3, 4, 5, 6, 7],
);
}
}
export default Bonus;
Increase bullet speed

increase lives count

kill all enemies
Game
state
const gameState = {
player: new Hero([0, 0], 3),
playerSpeed: 170,
bulletSpeed: 100,
enemySpeed: 100,
towers: [],
trapTowers: [],
bullets: [],
enemies: [],
explosions: [],
bonusesIncreaseScore: [],
bonusesIncreaseBulletSpeed: [],
bonusesKillEnemies: [],
lastTower: 0,
lastTrapTower: 0,
gameTime: 0,
lastTime: new Date(),
isGameOver: false,
isPause: false,
isMuted: false,
score: 0,
scoreEl: document.getElementById("score"),
lifesCountEl: document.getElementById("lifesCount"),
canvasContext: undefined,
canvas: undefined,
terrainPattern: undefined
};
Load resourses
First
init
function
Game loop

Game
loop
function
Update
function
Update bullets
// Update all the bullets
for (let i = 0; i < gameState.bullets.length; i += 1) {
const bullet = gameState.bullets[i];
const pathBulletLenght = dt * gameState.bulletSpeed;
const sin = Math.sin(bullet.angle);
const cos = Math.cos(bullet.angle);
bullet.pos[0] += sin * pathBulletLenght;
bullet.pos[1] += cos * pathBulletLenght;
// Remove the bullet if it goes offscreen
if (
bullet.pos[1] < 0 ||
bullet.pos[1] > gameState.canvas.height ||
bullet.pos[0] > gameState.canvas.width
) {
gameState.bullets.splice(i, 1);
i -= 1;
}
}Check collizions function
boxCollides function
function collides(x, y, r, b, x2, y2, r2, b2) {
return !(r <= x2 || x > r2 || b <= y2 || y > b2);
}
function boxCollides(pos, size, pos2, size2) {
return collides(
pos[0],
pos[1],
pos[0] + size[0],
pos[1] + size[1],
pos2[0],
pos2[1],
pos2[0] + size2[0],
pos2[1] + size2[1],
);
}Render
function
Render function
function renderEntity(entity) {
gameState.canvasContext.save();
gameState.canvasContext.translate(entity.pos[0], entity.pos[1]);
entity.sprite.render(gameState.canvasContext);
gameState.canvasContext.restore();
}
function renderEntities(collection) {
for (let i = 0; i < collection.length; i += 1) {
renderEntity(collection[i]);
}
}Project structure






Webpack config
const path = require('path');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'sass-loader'],
}),
},
{
test: /\.(png|jp(e*)g|svg)$/,
use: [{
loader: 'url-loader',
options: {
limit: 8000,
name: 'images/[hash]-[name].[ext]',
},
}],
},
],
},
plugins: [
new UglifyJsPlugin(),
new ExtractTextPlugin('style.css'),
],
};
Useful link:
Q&A
Game "Moon War"
By Denis Bogush
Game "Moon War"
- 196