diff --git a/src/boilerplates/webpack-boilerplate/src/config.ts b/src/boilerplates/webpack-boilerplate/src/config.ts
index 88efdf2a..5878e590 100644
--- a/src/boilerplates/webpack-boilerplate/src/config.ts
+++ b/src/boilerplates/webpack-boilerplate/src/config.ts
@@ -12,7 +12,8 @@ export const GameConfig: Phaser.Types.Core.GameConfig = {
physics: {
default: 'arcade',
arcade: {
- gravity: { y: 200 }
+ gravity: { y: 200 },
+ debug: true,
}
},
scene: [MainScene]
diff --git a/src/boilerplates/webpack-boilerplate/src/objects/redhat.ts b/src/boilerplates/webpack-boilerplate/src/objects/redhat.ts
index 0f0c26c2..d3af7fd2 100644
--- a/src/boilerplates/webpack-boilerplate/src/objects/redhat.ts
+++ b/src/boilerplates/webpack-boilerplate/src/objects/redhat.ts
@@ -17,8 +17,9 @@ export class Redhat extends Phaser.GameObjects.Image {
private initPhysics() {
this.scene.physics.world.enable(this);
- this.body.setVelocity(100, 200);
+ this.body.setVelocity(300, 400);
this.body.setBounce(1, 1);
+ this.body.setSize(200,200)
this.body.setCollideWorldBounds(true);
}
}
diff --git a/src/games/asteroid/src/config.ts b/src/games/asteroid/src/config.ts
index 44815feb..664781fa 100644
--- a/src/games/asteroid/src/config.ts
+++ b/src/games/asteroid/src/config.ts
@@ -20,7 +20,7 @@ export const GameConfig: Phaser.Types.Core.GameConfig = {
physics: {
default: 'arcade',
arcade: {
- debug: false
+ debug: true
}
},
backgroundColor: '#000000',
diff --git a/src/games/breakout/assets/images/flares.json b/src/games/breakout/assets/images/flares.json
new file mode 100644
index 00000000..9b9c2d8a
--- /dev/null
+++ b/src/games/breakout/assets/images/flares.json
@@ -0,0 +1,57 @@
+{"frames": {
+
+ "blue":
+ {
+ "frame": {"x":2,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "green":
+ {
+ "frame": {"x":132,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "red":
+ {
+ "frame": {"x":262,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "white":
+ {
+ "frame": {"x":392,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "yellow":
+ {
+ "frame": {"x":522,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ }},
+ "meta": {
+ "app": "http://www.codeandweb.com/texturepacker",
+ "version": "1.0",
+ "image": "flares.png",
+ "format": "RGBA8888",
+ "size": {"w":652,"h":132},
+ "scale": "1",
+ "smartupdate": "$TexturePacker:SmartUpdate:f2781d89823d5a67fc31381af364b421:da82646b19b2f0c08684086824b1e581:71625947cf221c10549b852c13ffedc7$"
+ }
+ }
\ No newline at end of file
diff --git a/src/games/breakout/assets/images/flares.png b/src/games/breakout/assets/images/flares.png
new file mode 100644
index 00000000..df04af53
Binary files /dev/null and b/src/games/breakout/assets/images/flares.png differ
diff --git a/src/games/breakout/assets/pack.json b/src/games/breakout/assets/pack.json
index 028b1494..0faa220b 100644
--- a/src/games/breakout/assets/pack.json
+++ b/src/games/breakout/assets/pack.json
@@ -6,6 +6,12 @@
"key": "font",
"textureURL": "./assets/font/font.png",
"fontDataURL": "./assets/font/font.fnt"
+ },
+ {
+ "type": "atlas",
+ "key": "flares",
+ "textureURL": "./assets/images/flares.png",
+ "atlasURL": "./assets/images/flares.json"
}
]
}
diff --git a/src/games/breakout/src/config.ts b/src/games/breakout/src/config.ts
index 474540f4..fbc0ae84 100644
--- a/src/games/breakout/src/config.ts
+++ b/src/games/breakout/src/config.ts
@@ -1,5 +1,5 @@
-import { BootScene } from './scenes/boot-scene';
-import { GameScene } from './scenes/game-scene';
+import { BootScene } from './scenes/bootScene';
+import { GameScene } from './scenes/gameScene';
export const GameConfig: Phaser.Types.Core.GameConfig = {
title: 'Breakout',
@@ -14,7 +14,8 @@ export const GameConfig: Phaser.Types.Core.GameConfig = {
physics: {
default: 'arcade',
arcade: {
- gravity: { x: 0, y: 0 }
+ gravity: { x: 0, y: 0 },
+ // debug: true,
}
},
scale: {
diff --git a/src/games/breakout/src/interfaces/interfaces.ts b/src/games/breakout/src/interfaces/interfaces.ts
index 9333f361..4adc8602 100644
--- a/src/games/breakout/src/interfaces/interfaces.ts
+++ b/src/games/breakout/src/interfaces/interfaces.ts
@@ -1,4 +1,4 @@
-export interface IRectangleConstructor {
+interface IRectangleConstructor {
scene: Phaser.Scene;
x: number;
y: number;
diff --git a/src/games/breakout/src/objects/ball.ts b/src/games/breakout/src/objects/ball.ts
index 7442068b..29cc199b 100644
--- a/src/games/breakout/src/objects/ball.ts
+++ b/src/games/breakout/src/objects/ball.ts
@@ -1,8 +1,8 @@
-import { IRectangleConstructor } from '../interfaces/interfaces';
+
export class Ball extends Phaser.GameObjects.Rectangle {
body: Phaser.Physics.Arcade.Body;
-
+ emitter!: Phaser.GameObjects.Particles.ParticleEmitter;
constructor(aParams: IRectangleConstructor) {
super(
aParams.scene,
@@ -16,6 +16,7 @@ export class Ball extends Phaser.GameObjects.Rectangle {
this.initRectangle();
this.initPhysics();
+ this.initPractices();
this.scene.add.existing(this);
}
@@ -32,8 +33,21 @@ export class Ball extends Phaser.GameObjects.Rectangle {
this.body.setCollideWorldBounds();
}
+ private initPractices(): void {
+ const particles = this.scene.add.particles('flares');
+ this.emitter = particles.createEmitter({
+ frame: 'red',
+ speed: 100,
+ scale: { start: 0.1, end: 0 },
+ angle: {min: 60, max:100},
+ blendMode: 'ADD'
+ }).stop();
+ this.emitter.startFollow(this, 5,5);
+ }
+
public applyInitVelocity(): void {
this.body.setVelocity(Phaser.Math.RND.between(-200, 200), 200);
this.body.speed = 800;
+ this.emitter.start()
}
}
diff --git a/src/games/breakout/src/objects/brick.ts b/src/games/breakout/src/objects/brick.ts
index 12686e27..3c132478 100644
--- a/src/games/breakout/src/objects/brick.ts
+++ b/src/games/breakout/src/objects/brick.ts
@@ -1,8 +1,8 @@
-import { IRectangleConstructor } from '../interfaces/interfaces';
+import { settings } from '../settings';
export class Brick extends Phaser.GameObjects.Rectangle {
body: Phaser.Physics.Arcade.Body;
-
+ isdestroyed!: boolean;
constructor(aParams: IRectangleConstructor) {
super(
aParams.scene,
@@ -13,18 +13,55 @@ export class Brick extends Phaser.GameObjects.Rectangle {
aParams.fillColor,
aParams.fillAlpha
);
-
+ this.isdestroyed = false;
this.initRectangle();
- this.initPhysics();
+ this.initPhysics();
this.scene.add.existing(this);
}
private initRectangle(): void {
this.setOrigin(0);
+ this.setScale(0,0);
+ const x = this.x / (settings.BRICK.WIDTH + settings.BRICK.SPACING);
+ const y = (this.y - settings.BRICK.MARGIN_TOP) / (settings.BRICK.HEIGHT + settings.BRICK.SPACING);
+ const WIDTH = settings.LEVELS[settings.currentLevel].WIDTH;
+ this.scene.tweens.add({
+ targets: this,
+ scaleX: 1,
+ scaleY: 1,
+ ease: 'Sine.easeInOut',
+ duration: 300,
+ delay: this.scene.tweens.stagger(50, {}),
+ repeat: 0,
+ yoyo: false,
+ onComplete: () => {
+ this.body.setSize(settings.BRICK.WIDTH, settings.BRICK.HEIGHT);
+ }
+ });
+
+ }
+
+ update(): void {
+ if(this.y > this.scene.scale.height - 100)
+ this.destroy();
}
private initPhysics(): void {
this.scene.physics.world.enable(this);
this.body.setImmovable(true);
}
+
+ public destroyBrick(): void {
+ this.isdestroyed = true;
+ this.setOrigin(0.5,0.5);
+ this.body.setAccelerationY(150);
+ this.body.checkCollision.none = true;
+ this.scene.tweens.add({
+ targets: this,
+ duration: 1000,
+ yoyo: false,
+ angle: 360,
+ repeat: -1,
+ });
+ }
}
diff --git a/src/games/breakout/src/objects/player.ts b/src/games/breakout/src/objects/player.ts
index 28f5e382..d19d8d9c 100644
--- a/src/games/breakout/src/objects/player.ts
+++ b/src/games/breakout/src/objects/player.ts
@@ -1,4 +1,3 @@
-import { IRectangleConstructor } from '../interfaces/interfaces';
export class Player extends Phaser.GameObjects.Rectangle {
body: Phaser.Physics.Arcade.Body;
diff --git a/src/games/breakout/src/scenes/bootScene.ts b/src/games/breakout/src/scenes/bootScene.ts
new file mode 100644
index 00000000..402dc245
--- /dev/null
+++ b/src/games/breakout/src/scenes/bootScene.ts
@@ -0,0 +1,61 @@
+export class BootScene extends Phaser.Scene {
+ private loadingBar: Phaser.GameObjects.Graphics;
+ private progressBar: Phaser.GameObjects.Graphics;
+
+ constructor() {
+ super({
+ key: 'BootScene'
+ });
+ }
+
+ preload(): void {
+ // set the background and create loading bar
+ // this.cameras.main.setBackgroundColor(0x98d687);
+ this.createLoadingbar();
+
+ // pass value to change the loading bar fill
+ this.load.on(
+ 'progress',
+ function (value: number) {
+ this.progressBar.clear();
+ this.progressBar.fillStyle(0xfff6d3, 1);
+ this.progressBar.fillRect(
+ this.cameras.main.width / 4,
+ this.cameras.main.height / 2 - 16,
+ (this.cameras.main.width / 2) * value,
+ 16
+ );
+ },
+ this
+ );
+
+ // delete bar graphics, when loading complete
+ this.load.on(
+ 'complete',
+ function () {
+ this.progressBar.destroy();
+ this.loadingBar.destroy();
+ },
+ this
+ );
+
+ // load out package
+ this.load.pack('preload', './assets/pack.json', 'preload');
+ }
+
+ update(): void {
+ this.scene.start('GameScene');
+ }
+
+ private createLoadingbar(): void {
+ this.loadingBar = this.add.graphics();
+ this.loadingBar.fillStyle(0x5dae47, 1);
+ this.loadingBar.fillRect(
+ this.cameras.main.width / 4 - 2,
+ this.cameras.main.height / 2 - 18,
+ this.cameras.main.width / 2 + 4,
+ 20
+ );
+ this.progressBar = this.add.graphics();
+ }
+}
diff --git a/src/games/breakout/src/scenes/game-scene.ts b/src/games/breakout/src/scenes/gameScene.ts
similarity index 76%
rename from src/games/breakout/src/scenes/game-scene.ts
rename to src/games/breakout/src/scenes/gameScene.ts
index 1d885927..e438d0ec 100644
--- a/src/games/breakout/src/scenes/game-scene.ts
+++ b/src/games/breakout/src/scenes/gameScene.ts
@@ -8,6 +8,7 @@ const BRICK_COLORS: number[] = [0xf2e49b, 0xbed996, 0xf2937e, 0xffffff];
export class GameScene extends Phaser.Scene {
private ball: Ball;
private bricks: Phaser.GameObjects.Group;
+ private isBrickVisible!: boolean;
private player: Player;
private scoreText: Phaser.GameObjects.BitmapText;
private highScoreText: Phaser.GameObjects.BitmapText;
@@ -23,22 +24,27 @@ export class GameScene extends Phaser.Scene {
settings.highScore = settings.score;
settings.score = 0;
settings.lives = 3;
+ this.isBrickVisible = false;
}
create(): void {
+
// game objects
// ------------
// bricks
- this.bricks = this.add.group();
+ this.bricks = this.add.group({
+ /*classType: Brick,*/
+ runChildUpdate: true
+ });
const BRICKS = settings.LEVELS[settings.currentLevel].BRICKS;
const WIDTH = settings.LEVELS[settings.currentLevel].WIDTH;
const HEIGHT = settings.LEVELS[settings.currentLevel].HEIGHT;
for (let y = 0; y < HEIGHT; y++) {
for (let x = 0; x < WIDTH; x++) {
- this.bricks.add(
- new Brick({
+
+ const brick = new Brick({
scene: this,
x: (settings.BRICK.WIDTH + settings.BRICK.SPACING) * x,
y:
@@ -48,16 +54,39 @@ export class GameScene extends Phaser.Scene {
height: settings.BRICK.HEIGHT,
fillColor: BRICK_COLORS[BRICKS[y * 14 + x]]
})
- );
+ this.bricks.add(brick);
}
}
+ // wait for the brick init finishes
+ this.time.delayedCall(50*WIDTH*HEIGHT+600, ()=>{
+ this.isBrickVisible = true;
+ this.bricks.getChildren().map((brick, index) => {
+ let y = Math.floor(index/WIDTH);
+ let x = index - y * WIDTH;
+ this.tweens.add({
+ targets: brick,
+ scaleX: 0.3,
+ scaleY: 0.3,
+ ease: 'Sine.easeInOut',
+ duration: 300,
+ delay: (x+y) * 50,
+ yoyo: true,
+ repeat: -1,
+ repeatDelay: 5000,
+ onRepeat: () => {
+ console.log("loop finished")
+ }
+ });
+ })
+ }, [], this)
+
// player
this.player = new Player({
scene: this,
x: +this.game.config.width / 2 - 20,
y: +this.game.config.height - 50,
- width: 50,
+ width: 100,
height: 10
});
@@ -112,9 +141,9 @@ export class GameScene extends Phaser.Scene {
update(): void {
this.player.update();
-
- if (this.player.body.velocity.x !== 0 && !this.ball.visible) {
+ if (this.player.body.velocity.x !== 0 && !this.ball.visible && this.isBrickVisible) {
this.ball.setPosition(this.player.x, this.player.y - 200);
+
this.ball.applyInitVelocity();
this.ball.setVisible(true);
}
@@ -131,17 +160,20 @@ export class GameScene extends Phaser.Scene {
this.ball.setPosition(0, 0);
this.ball.body.setVelocity(0);
this.ball.setVisible(false);
+ this.ball.emitter.stop();
}
}
}
private ballBrickCollision(ball: Ball, brick: Brick): void {
- brick.destroy();
+ // brick.destroy();
+ brick.destroyBrick();
settings.score += 10;
this.events.emit('scoreChanged');
if (this.bricks.countActive() === 0) {
// all bricks are gone!
+ this.scene.restart();
}
}
diff --git a/src/games/breakout/tsconfig.json b/src/games/breakout/tsconfig.json
index 12c795f0..b8a5ff55 100644
--- a/src/games/breakout/tsconfig.json
+++ b/src/games/breakout/tsconfig.json
@@ -3,7 +3,8 @@
"target": "ES6",
"module": "CommonJS",
"moduleResolution": "node",
- "noImplicitAny": true
+ "noImplicitAny": true,
+ "typeRoots": ["*/**/*.interface.ts"]
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
diff --git a/src/games/candy-crush/assets/images/UFO2.png b/src/games/candy-crush/assets/images/UFO2.png
new file mode 100644
index 00000000..8f613689
Binary files /dev/null and b/src/games/candy-crush/assets/images/UFO2.png differ
diff --git a/src/games/candy-crush/assets/images/flares.json b/src/games/candy-crush/assets/images/flares.json
new file mode 100644
index 00000000..9b9c2d8a
--- /dev/null
+++ b/src/games/candy-crush/assets/images/flares.json
@@ -0,0 +1,57 @@
+{"frames": {
+
+ "blue":
+ {
+ "frame": {"x":2,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "green":
+ {
+ "frame": {"x":132,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "red":
+ {
+ "frame": {"x":262,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "white":
+ {
+ "frame": {"x":392,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "yellow":
+ {
+ "frame": {"x":522,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ }},
+ "meta": {
+ "app": "http://www.codeandweb.com/texturepacker",
+ "version": "1.0",
+ "image": "flares.png",
+ "format": "RGBA8888",
+ "size": {"w":652,"h":132},
+ "scale": "1",
+ "smartupdate": "$TexturePacker:SmartUpdate:f2781d89823d5a67fc31381af364b421:da82646b19b2f0c08684086824b1e581:71625947cf221c10549b852c13ffedc7$"
+ }
+ }
\ No newline at end of file
diff --git a/src/games/candy-crush/assets/images/flares.png b/src/games/candy-crush/assets/images/flares.png
new file mode 100644
index 00000000..df04af53
Binary files /dev/null and b/src/games/candy-crush/assets/images/flares.png differ
diff --git a/src/games/candy-crush/assets/pack.json b/src/games/candy-crush/assets/pack.json
index d6c0bcbd..573b65e4 100644
--- a/src/games/candy-crush/assets/pack.json
+++ b/src/games/candy-crush/assets/pack.json
@@ -60,6 +60,12 @@
"type": "image",
"key": "starcookie2",
"url": "./assets/images/starcookie2.png"
+ },
+ {
+ "type": "atlas",
+ "key": "flares",
+ "textureURL": "./assets/images/flares.png",
+ "atlasURL": "./assets/images/flares.json"
}
]
}
diff --git a/src/games/candy-crush/src/config.ts b/src/games/candy-crush/src/config.ts
index 777b4c1a..4c2bac48 100644
--- a/src/games/candy-crush/src/config.ts
+++ b/src/games/candy-crush/src/config.ts
@@ -1,5 +1,5 @@
-import { BootScene } from './scenes/boot-scene';
-import { GameScene } from './scenes/game-scene';
+import { BootScene } from './scenes/bootScene';
+import { GameScene } from './scenes/gameScene';
export const GameConfig: Phaser.Types.Core.GameConfig = {
title: 'Candy crush',
diff --git a/src/games/candy-crush/src/const/const.ts b/src/games/candy-crush/src/const/const.ts
index 3e86e5de..e11ea3a4 100644
--- a/src/games/candy-crush/src/const/const.ts
+++ b/src/games/candy-crush/src/const/const.ts
@@ -11,12 +11,12 @@ export let CONST = {
'croissant',
'cupcake',
'donut',
- 'eclair',
- 'macaroon',
- 'pie',
- 'poptart1',
- 'poptart2',
- 'starcookie1',
- 'starcookie2'
+ // 'eclair',
+ // 'macaroon',
+ // 'pie',
+ // 'poptart1',
+ // 'poptart2',
+ // 'starcookie1',
+ // 'starcookie2'
]
};
diff --git a/src/games/candy-crush/src/objects/tile.ts b/src/games/candy-crush/src/objects/tile.ts
index 5bdf2759..0817c3bc 100644
--- a/src/games/candy-crush/src/objects/tile.ts
+++ b/src/games/candy-crush/src/objects/tile.ts
@@ -1,13 +1,69 @@
+import { CONST } from '../const/const';
import { IImageConstructor } from '../interfaces/image.interface';
export class Tile extends Phaser.GameObjects.Image {
+ public tween: Phaser.Tweens.Tween;
+ particles!: Phaser.GameObjects.Particles.ParticleEmitter;
constructor(aParams: IImageConstructor) {
super(aParams.scene, aParams.x, aParams.y, aParams.texture, aParams.frame);
// set image settings
this.setOrigin(0, 0);
this.setInteractive();
-
this.scene.add.existing(this);
}
+
+ public initTween(){
+ this.tween = this.scene.tweens.add({
+ targets: this,
+ scaleX: 0.5,
+ scaleY: 0.5,
+ ease: 'Sine.easeInOut',
+ duration: 500,
+ delay: (this.x / CONST.tileWidth + this.y / CONST.tileHeight) * 50,
+ yoyo: true,
+ repeat: 0,
+ });
+
+ }
+
+ public initTweenMatch(){
+ this.particles = this.scene.add.particles('flares').createEmitter({
+ frame: "red",
+ lifespan: 500,
+ speed: { min: 400, max: 600 },
+ angle: {min: 40, max: 80},
+ gravityY: 300,
+ scale: { start: 0.1, end: 0 },
+ quantity: 2,
+ blendMode: 'ADD',
+ follow: this,
+ followOffset: {x:CONST.tileWidth/2, y: CONST.tileHeight/2}
+ }).stop();
+
+ this.setDepth(1);
+ this.scene.tweens.timeline({
+ targets: this,
+ ease: 'Sine.easeInOut',
+ duration: 1000,
+ yoyo: false,
+ tweens: [{
+ scaleX: 1.5,
+ scaleY: 1.5,
+ onComplete:()=>{
+ this.particles.start();
+ }
+ },
+ {
+ scaleX: 0.5,
+ scaleY: 0.5,
+ x: -10,
+ y: -10,
+ }],
+ onComplete:()=>{
+ this.destroy();
+ this.particles.stop();
+ }
+ });
+ }
}
diff --git a/src/games/candy-crush/src/scenes/boot-scene.ts b/src/games/candy-crush/src/scenes/bootScene.ts
similarity index 100%
rename from src/games/candy-crush/src/scenes/boot-scene.ts
rename to src/games/candy-crush/src/scenes/bootScene.ts
diff --git a/src/games/candy-crush/src/scenes/game-scene.ts b/src/games/candy-crush/src/scenes/gameScene.ts
similarity index 75%
rename from src/games/candy-crush/src/scenes/game-scene.ts
rename to src/games/candy-crush/src/scenes/gameScene.ts
index 02d9fc02..bb8672e4 100644
--- a/src/games/candy-crush/src/scenes/game-scene.ts
+++ b/src/games/candy-crush/src/scenes/gameScene.ts
@@ -4,10 +4,13 @@ import { Tile } from '../objects/tile';
export class GameScene extends Phaser.Scene {
// Variables
private canMove: boolean;
+ private match: boolean;
// Grid with tiles
private tileGrid: Tile[][];
+ emitter!: Phaser.GameObjects.Particles.ParticleEmitter;
+
// Selected Tiles
private firstSelectedTile: Tile;
private secondSelectedTile: Tile;
@@ -19,8 +22,11 @@ export class GameScene extends Phaser.Scene {
}
init(): void {
+ this.initPractices();
+
// Init variables
this.canMove = true;
+ this.match = false;
// set background color
this.cameras.main.setBackgroundColor(0x78aade);
@@ -31,6 +37,7 @@ export class GameScene extends Phaser.Scene {
this.tileGrid[y] = [];
for (let x = 0; x < CONST.gridWidth; x++) {
this.tileGrid[y][x] = this.addTile(x, y);
+ this.tileGrid[y][x].initTween();
}
}
@@ -45,6 +52,36 @@ export class GameScene extends Phaser.Scene {
this.checkMatches();
}
+ create(){
+ // after 10 seconds create tween
+ this.time.addEvent({ delay: 10000, callback: ()=>{
+ if(!this.match){
+ for (let y = 0; y < CONST.gridHeight; y++) {
+ for (let x = 0; x < CONST.gridWidth; x++) {
+ this.tileGrid[y][x].initTween();
+ }
+ }
+ }
+ }, loop: true, callbackScope: this })
+ }
+
+ update(time: number, delta: number): void {
+ if(!this.firstSelectedTile){
+ this.emitter.stop();
+ }
+ }
+
+ initPractices(): void {
+ const particles = this.add.particles('flares');
+ var circle = new Phaser.Geom.Circle(CONST.tileWidth/2, CONST.tileHeight/2, (CONST.tileWidth/2));
+ this.emitter = particles.createEmitter({
+ frame: 'red',
+ lifespan: 500,
+ scale: { start: 0.1, end: 0 },
+ emitZone: { type: 'edge', source: circle, quantity: 120}
+ })
+ }
+
/**
* Add a new random tile at the specified position.
* @param x
@@ -73,13 +110,16 @@ export class GameScene extends Phaser.Scene {
* @param event
*/
private tileDown(pointer: any, gameobject: any, event: any): void {
+ this.match = true;
if (this.canMove) {
if (!this.firstSelectedTile) {
this.firstSelectedTile = gameobject;
+ this.emitter.stop();
+ this.emitter.start();
+ this.emitter.startFollow(this.firstSelectedTile)
} else {
// So if we are here, we must have selected a second tile
this.secondSelectedTile = gameobject;
-
let dx =
Math.abs(this.firstSelectedTile.x - this.secondSelectedTile.x) /
CONST.tileWidth;
@@ -92,6 +132,12 @@ export class GameScene extends Phaser.Scene {
this.canMove = false;
this.swapTiles();
}
+ else{
+ this.firstSelectedTile = gameobject;
+ this.emitter.stop();
+ this.emitter.start();
+ this.emitter.startFollow(this.firstSelectedTile)
+ }
}
}
}
@@ -100,9 +146,17 @@ export class GameScene extends Phaser.Scene {
* This function will take care of the swapping of the two selected tiles.
* It will only work, if two tiles have been selected.
*/
- private swapTiles(): void {
+ private swapTiles() {
if (this.firstSelectedTile && this.secondSelectedTile) {
- // Get the position of the two tiles
+ this.emitter.stop();
+ var firstSelectedTile = this.firstSelectedTile;
+ var secondSelectedTile = this.secondSelectedTile;
+ if(this.canMove){
+ firstSelectedTile = this.secondSelectedTile;
+ secondSelectedTile = this.firstSelectedTile;
+ }
+
+ // Get the position of the two tiles
let firstTilePosition = {
x: this.firstSelectedTile.x,
y: this.firstSelectedTile.y
@@ -123,28 +177,40 @@ export class GameScene extends Phaser.Scene {
// Move them on the screen with tweens
this.add.tween({
- targets: this.firstSelectedTile,
- x: this.secondSelectedTile.x,
- y: this.secondSelectedTile.y,
+ targets: firstSelectedTile,
+ x: secondSelectedTile.x,
+ y: secondSelectedTile.y,
ease: 'Linear',
+ scaleX: 1.5,
+ scaleY: 1.5,
duration: 400,
repeat: 0,
- yoyo: false
+ yoyo: false,
});
this.add.tween({
- targets: this.secondSelectedTile,
- x: this.firstSelectedTile.x,
- y: this.firstSelectedTile.y,
+ targets: secondSelectedTile,
+ x: firstSelectedTile.x,
+ y: firstSelectedTile.y,
ease: 'Linear',
duration: 400,
repeat: 0,
yoyo: false,
+ });
+
+ this.tweens.add({
+ targets: [firstSelectedTile],
+ ease: 'Sine.easeInOut',
+ duration: 200,
+ scaleX: 1,
+ scaleY: 1,
+ repeat: 0,
+ delay: 400,
+ yoyo: false,
onComplete: () => {
this.checkMatches();
}
- });
-
+ })
this.firstSelectedTile = this.tileGrid[
firstTilePosition.y / CONST.tileHeight
][firstTilePosition.x / CONST.tileWidth];
@@ -164,16 +230,25 @@ export class GameScene extends Phaser.Scene {
//Remove the tiles
this.removeTileGroup(matches);
// Move the tiles currently on the board into their new positions
- this.resetTile();
- //Fill the board with new tiles wherever there is an empty spot
- this.fillTile();
- this.tileUp();
- this.checkMatches();
+ this.time.delayedCall(2000, ()=>{
+ for(var i=0; i< 7; i++) {
+ this.resetTile();
+ }
+
+ //Fill the board with new tiles wherever there is an empty spot
+ this.time.delayedCall(500, ()=>{
+ this.fillTile();
+ this.tileUp();
+ this.checkMatches();
+ },[], this)
+ }, [], this)
+
} else {
// No match so just swap the tiles back to their original position and reset
- this.swapTiles();
- this.tileUp();
this.canMove = true;
+ this.match = false;
+ this.swapTiles()
+ this.tileUp();
}
}
@@ -212,17 +287,17 @@ export class GameScene extends Phaser.Scene {
private fillTile(): void {
//Check for blank spaces in the grid and add new tiles at that position
- for (var y = 0; y < this.tileGrid.length; y++) {
- for (var x = 0; x < this.tileGrid[y].length; x++) {
- if (this.tileGrid[y][x] === undefined) {
- //Found a blank spot so lets add animate a tile there
- let tile = this.addTile(x, y);
-
- //And also update our "theoretical" grid
- this.tileGrid[y][x] = tile;
+ for (var y = 0; y < this.tileGrid.length; y++) {
+ for (var x = 0; x < this.tileGrid[y].length; x++) {
+ if (this.tileGrid[y][x] === undefined) {
+ //Found a blank spot so lets add animate a tile there
+ let tile = this.addTile(x, y);
+ //And also update our "theoretical" grid
+ this.tileGrid[y][x] = tile;
+ }
}
}
- }
+ this.match = false;
}
private tileUp(): void {
@@ -243,7 +318,8 @@ export class GameScene extends Phaser.Scene {
// Remove the tile from the theoretical grid
if (tilePos.x !== -1 && tilePos.y !== -1) {
- tile.destroy();
+ tile.initTweenMatch();
+ this.match = true;
this.tileGrid[tilePos.y][tilePos.x] = undefined;
}
}
diff --git a/src/games/coin-runner/assets/images/flares.json b/src/games/coin-runner/assets/images/flares.json
new file mode 100644
index 00000000..9b9c2d8a
--- /dev/null
+++ b/src/games/coin-runner/assets/images/flares.json
@@ -0,0 +1,57 @@
+{"frames": {
+
+ "blue":
+ {
+ "frame": {"x":2,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "green":
+ {
+ "frame": {"x":132,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "red":
+ {
+ "frame": {"x":262,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "white":
+ {
+ "frame": {"x":392,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "yellow":
+ {
+ "frame": {"x":522,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ }},
+ "meta": {
+ "app": "http://www.codeandweb.com/texturepacker",
+ "version": "1.0",
+ "image": "flares.png",
+ "format": "RGBA8888",
+ "size": {"w":652,"h":132},
+ "scale": "1",
+ "smartupdate": "$TexturePacker:SmartUpdate:f2781d89823d5a67fc31381af364b421:da82646b19b2f0c08684086824b1e581:71625947cf221c10549b852c13ffedc7$"
+ }
+ }
\ No newline at end of file
diff --git a/src/games/coin-runner/assets/images/flares.png b/src/games/coin-runner/assets/images/flares.png
new file mode 100644
index 00000000..df04af53
Binary files /dev/null and b/src/games/coin-runner/assets/images/flares.png differ
diff --git a/src/games/coin-runner/assets/pack.json b/src/games/coin-runner/assets/pack.json
new file mode 100644
index 00000000..56883df2
--- /dev/null
+++ b/src/games/coin-runner/assets/pack.json
@@ -0,0 +1,27 @@
+{
+ "preload": {
+ "files": [
+ {
+ "type": "image",
+ "key": "coin",
+ "url": "./assets/images/coin.png"
+ },
+ {
+ "type": "image",
+ "key": "player",
+ "url": "./assets/images/player.png"
+ },
+ {
+ "type": "image",
+ "key": "background",
+ "url": "./assets/images/background.png"
+ },
+ {
+ "type": "atlas",
+ "key": "flares",
+ "textureURL": "./assets/images/flares.png",
+ "atlasURL": "./assets/images/flares.json"
+ }
+ ]
+ }
+}
diff --git a/src/games/coin-runner/src/config.ts b/src/games/coin-runner/src/config.ts
index 8082ddd3..f690848a 100644
--- a/src/games/coin-runner/src/config.ts
+++ b/src/games/coin-runner/src/config.ts
@@ -1,4 +1,5 @@
-import { GameScene } from './scenes/game-scene';
+import { BootScene } from './scenes/bootScene';
+import { GameScene } from './scenes/gameScene';
export const GameConfig: Phaser.Types.Core.GameConfig = {
title: 'Coin Runner',
@@ -8,7 +9,7 @@ export const GameConfig: Phaser.Types.Core.GameConfig = {
height: 576,
type: Phaser.AUTO,
parent: 'game',
- scene: [GameScene],
+ scene: [BootScene, GameScene],
input: {
keyboard: true
},
diff --git a/src/games/coin-runner/src/interfaces/image.interface.ts b/src/games/coin-runner/src/interfaces/image.interface.ts
index 4e54a6db..184b070e 100644
--- a/src/games/coin-runner/src/interfaces/image.interface.ts
+++ b/src/games/coin-runner/src/interfaces/image.interface.ts
@@ -1,4 +1,4 @@
-export interface IImageConstructor {
+interface IImageConstructor {
scene: Phaser.Scene;
x: number;
y: number;
diff --git a/src/games/coin-runner/src/objects/coin.ts b/src/games/coin-runner/src/objects/coin.ts
index 863a78a9..445b6e35 100644
--- a/src/games/coin-runner/src/objects/coin.ts
+++ b/src/games/coin-runner/src/objects/coin.ts
@@ -1,4 +1,3 @@
-import { IImageConstructor } from '../interfaces/image.interface';
export class Coin extends Phaser.GameObjects.Image {
private centerOfScreen: number;
@@ -23,6 +22,16 @@ export class Coin extends Phaser.GameObjects.Image {
private initImage(): void {
this.setOrigin(0.5, 0.5);
+ this.setScale(0.01,1);
+ this.scene.tweens.add({
+ targets: this,
+ scaleX: 1,
+ flipX: true,
+ ease: 'Sine.easeInOut',
+ duration: 1000,
+ yoyo: true,
+ repeat: -1
+ });
}
private initEvents(): void {
@@ -64,4 +73,43 @@ export class Coin extends Phaser.GameObjects.Image {
this.lastPosition = 'right';
}
}
+
+ public playerHitCoin(){
+ // emitter
+ var particles = this.scene.add.particles('flares');
+ const emitterUpCoin = particles.createEmitter({
+ frame: 'yellow',
+ x: this.x,
+ y: this.y,
+ quantity: 2,
+ speed: { random: [50, 100] },
+ lifespan: { random: [200, 400]},
+ scale: { start: 0.2, end: 0 },
+ angle: { random: true, start: 0, end: 270 },
+ blendMode: 'ADD'
+ })
+
+ const xVals = [this.x,100, 300, 100, this.scene.sys.canvas.width / 2]
+ const yVals = [this.y,200, 100, 150, this.scene.sys.canvas.height - 50]
+
+ this.scene.tweens.addCounter({
+ from: 0,
+ to: 1,
+ ease: Phaser.Math.Easing.Sine.InOut,
+ duration: 1000,
+ onUpdate: tween => {
+ const v = tween.getValue()
+ const x = Phaser.Math.Interpolation.CatmullRom(xVals, v)
+ const y = Phaser.Math.Interpolation.CatmullRom(yVals, v)
+
+ emitterUpCoin.setPosition(x, y)
+ },
+ onComplete: () => {
+ emitterUpCoin.stop()
+ this.scene.time.delayedCall(1000, () => {
+ particles.removeEmitter(emitterUpCoin);
+ })
+ }
+ })
+ }
}
diff --git a/src/games/coin-runner/src/objects/player.ts b/src/games/coin-runner/src/objects/player.ts
index 1fc33d69..765cff5e 100644
--- a/src/games/coin-runner/src/objects/player.ts
+++ b/src/games/coin-runner/src/objects/player.ts
@@ -1,4 +1,3 @@
-import { IImageConstructor } from '../interfaces/image.interface';
export class Player extends Phaser.GameObjects.Image {
private cursors: Phaser.Types.Input.Keyboard.CursorKeys;
diff --git a/src/games/breakout/src/scenes/boot-scene.ts b/src/games/coin-runner/src/scenes/bootScene.ts
similarity index 96%
rename from src/games/breakout/src/scenes/boot-scene.ts
rename to src/games/coin-runner/src/scenes/bootScene.ts
index f5f5d9dc..14b980bf 100644
--- a/src/games/breakout/src/scenes/boot-scene.ts
+++ b/src/games/coin-runner/src/scenes/bootScene.ts
@@ -10,7 +10,7 @@ export class BootScene extends Phaser.Scene {
preload(): void {
// set the background and create loading bar
- //this.cameras.main.setBackgroundColor(0x98d687);
+ this.cameras.main.setBackgroundColor(0x98d687);
this.createLoadingbar();
// pass value to change the loading bar fill
diff --git a/src/games/coin-runner/src/scenes/game-scene.ts b/src/games/coin-runner/src/scenes/gameScene.ts
similarity index 82%
rename from src/games/coin-runner/src/scenes/game-scene.ts
rename to src/games/coin-runner/src/scenes/gameScene.ts
index 830ce12f..e4a7a45a 100644
--- a/src/games/coin-runner/src/scenes/game-scene.ts
+++ b/src/games/coin-runner/src/scenes/gameScene.ts
@@ -14,12 +14,6 @@ export class GameScene extends Phaser.Scene {
});
}
- preload(): void {
- this.load.image('background', './assets/images/background.png');
- this.load.image('player', './assets/images/player.png');
- this.load.image('coin', './assets/images/coin.png');
- }
-
init(): void {
this.collectedCoins = 0;
}
@@ -56,6 +50,7 @@ export class GameScene extends Phaser.Scene {
color: '#000000'
}
);
+
}
update(): void {
@@ -70,13 +65,17 @@ export class GameScene extends Phaser.Scene {
this.coin.getBounds()
)
) {
- this.updateCoinStatus();
+ this.updateCoinStatus();
}
}
private updateCoinStatus(): void {
- this.collectedCoins++;
- this.coinsCollectedText.setText(this.collectedCoins + '');
+ this.coin.playerHitCoin();
+ this.time.delayedCall(1000, () => {
+
+ this.collectedCoins++;
+ this.coinsCollectedText.setText(this.collectedCoins + '');
+ })
this.coin.changePosition();
}
}
diff --git a/src/games/coin-runner/tsconfig.json b/src/games/coin-runner/tsconfig.json
index 12c795f0..b8a5ff55 100644
--- a/src/games/coin-runner/tsconfig.json
+++ b/src/games/coin-runner/tsconfig.json
@@ -3,7 +3,8 @@
"target": "ES6",
"module": "CommonJS",
"moduleResolution": "node",
- "noImplicitAny": true
+ "noImplicitAny": true,
+ "typeRoots": ["*/**/*.interface.ts"]
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
diff --git a/src/games/endless-runner/assets/images/flares.json b/src/games/endless-runner/assets/images/flares.json
new file mode 100644
index 00000000..9b9c2d8a
--- /dev/null
+++ b/src/games/endless-runner/assets/images/flares.json
@@ -0,0 +1,57 @@
+{"frames": {
+
+ "blue":
+ {
+ "frame": {"x":2,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "green":
+ {
+ "frame": {"x":132,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "red":
+ {
+ "frame": {"x":262,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "white":
+ {
+ "frame": {"x":392,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "yellow":
+ {
+ "frame": {"x":522,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ }},
+ "meta": {
+ "app": "http://www.codeandweb.com/texturepacker",
+ "version": "1.0",
+ "image": "flares.png",
+ "format": "RGBA8888",
+ "size": {"w":652,"h":132},
+ "scale": "1",
+ "smartupdate": "$TexturePacker:SmartUpdate:f2781d89823d5a67fc31381af364b421:da82646b19b2f0c08684086824b1e581:71625947cf221c10549b852c13ffedc7$"
+ }
+ }
\ No newline at end of file
diff --git a/src/games/endless-runner/assets/images/flares.png b/src/games/endless-runner/assets/images/flares.png
new file mode 100644
index 00000000..df04af53
Binary files /dev/null and b/src/games/endless-runner/assets/images/flares.png differ
diff --git a/src/games/endless-runner/assets/pack.json b/src/games/endless-runner/assets/pack.json
new file mode 100644
index 00000000..a19db3c0
--- /dev/null
+++ b/src/games/endless-runner/assets/pack.json
@@ -0,0 +1,12 @@
+{
+ "preload": {
+ "files": [
+ {
+ "type": "atlas",
+ "key": "flares",
+ "textureURL": "./assets/images/flares.png",
+ "atlasURL": "./assets/images/flares.json"
+ }
+ ]
+ }
+}
diff --git a/src/games/endless-runner/index.html b/src/games/endless-runner/index.html
index eaf00987..9600c31e 100644
--- a/src/games/endless-runner/index.html
+++ b/src/games/endless-runner/index.html
@@ -6,7 +6,7 @@
Endless Runner
-
+
Endless Runner
diff --git a/src/games/endless-runner/src/config.ts b/src/games/endless-runner/src/config.ts
index 70ddd9b7..ed0607f2 100644
--- a/src/games/endless-runner/src/config.ts
+++ b/src/games/endless-runner/src/config.ts
@@ -1,3 +1,4 @@
+import { BootScene } from './scenes/boot-scene';
import { GameScene } from './scenes/game-scene';
export const GameConfig: Phaser.Types.Core.GameConfig = {
@@ -5,7 +6,7 @@ export const GameConfig: Phaser.Types.Core.GameConfig = {
url: 'https://github.com/digitsensitive/phaser3-typescript',
version: '1.0',
type: Phaser.AUTO,
- scene: [GameScene],
+ scene: [BootScene, GameScene],
input: {
mouse: true
},
@@ -22,5 +23,5 @@ export const GameConfig: Phaser.Types.Core.GameConfig = {
width: 960,
height: 640
},
- backgroundColor: 0x4ac7ff
+ // backgroundColor: 0x4ac7ff
};
diff --git a/src/games/endless-runner/src/scenes/boot-scene.ts b/src/games/endless-runner/src/scenes/boot-scene.ts
new file mode 100644
index 00000000..16f52efd
--- /dev/null
+++ b/src/games/endless-runner/src/scenes/boot-scene.ts
@@ -0,0 +1,59 @@
+export class BootScene extends Phaser.Scene {
+ private loadingBar: Phaser.GameObjects.Graphics;
+ private progressBar: Phaser.GameObjects.Graphics;
+
+ constructor() {
+ super({
+ key: 'BootScene'
+ });
+ }
+
+ preload(): void {
+ // create loading bar
+ this.createLoadingbar();
+ // pass value to change the loading bar fill
+ this.load.on(
+ 'progress',
+ function (value: number) {
+ this.progressBar.clear();
+ this.progressBar.fillStyle(0xfff6d3, 1);
+ this.progressBar.fillRect(
+ this.cameras.main.width / 4,
+ this.cameras.main.height / 2 - 16,
+ (this.cameras.main.width / 2) * value,
+ 16
+ );
+ },
+ this
+ );
+
+ // delete bar graphics, when loading complete
+ this.load.on(
+ 'complete',
+ function () {
+ this.progressBar.destroy();
+ this.loadingBar.destroy();
+ },
+ this
+ );
+
+ // load out package
+ this.load.pack('preload', './assets/pack.json', 'preload');
+ }
+
+ update(): void {
+ this.scene.start('GameScene');
+ }
+
+ private createLoadingbar(): void {
+ this.loadingBar = this.add.graphics();
+ this.loadingBar.fillStyle(0x5dae47, 1);
+ this.loadingBar.fillRect(
+ this.cameras.main.width / 4 - 2,
+ this.cameras.main.height / 2 - 18,
+ this.cameras.main.width / 2 + 4,
+ 20
+ );
+ this.progressBar = this.add.graphics();
+ }
+}
diff --git a/src/games/endless-runner/src/scenes/game-scene.ts b/src/games/endless-runner/src/scenes/game-scene.ts
index 5c23a21e..0358354c 100644
--- a/src/games/endless-runner/src/scenes/game-scene.ts
+++ b/src/games/endless-runner/src/scenes/game-scene.ts
@@ -6,6 +6,8 @@ export class GameScene extends Phaser.Scene {
private isPlayerJumping: boolean;
private loadingBar: Phaser.GameObjects.Rectangle;
private loadingBarTween: Phaser.Tweens.Tween;
+ private checkTween!: boolean;
+ private emitter!: Phaser.GameObjects.Particles.ParticleEmitter
constructor() {
super({
@@ -16,9 +18,13 @@ export class GameScene extends Phaser.Scene {
init(): void {
this.isPlayerJumping = false;
settings.createTowerXPosition = 0;
+ this.checkTween = false;
}
create(): void {
+
+ this.initPractices();
+
this.loadingBar = this.add
.rectangle(
0,
@@ -45,7 +51,7 @@ export class GameScene extends Phaser.Scene {
.pause();
this.towers = this.add.group();
-
+
for (let i = 0; i < settings.MAX_ACTIVE_TOWERS; i++) {
this.spawnNewTower();
@@ -74,6 +80,37 @@ export class GameScene extends Phaser.Scene {
);
// setup input
+ this.initHandleInput();
+
+ // setup camera
+ this.cameras.main.setBounds(
+ 0,
+ 0,
+ +this.game.config.width,
+ +this.game.config.height
+ );
+
+
+ this.emitter.startFollow(this.player,settings.BLOCK_WIDTH/2,settings.BLOCK_WIDTH/2);
+ this.player.body.velocity.y = 1;
+
+ this.cameras.main.startFollow(this.player);
+ }
+
+ private initPractices(){
+ // emitter
+ const particles = this.add.particles('flares');
+
+ this.emitter = particles.createEmitter({
+ frame: 'red',
+ speed: 100,
+ gravityY: 475,
+ scale: { start: 0.2, end: 0 },
+ blendMode: 'ADD'
+ });
+ }
+
+ private initHandleInput(){
this.input.on(
'pointerdown',
() => {
@@ -84,15 +121,6 @@ export class GameScene extends Phaser.Scene {
this
);
this.input.on('pointerup', this.playerJump, this);
-
- // setup camera
- this.cameras.main.setBounds(
- 0,
- 0,
- +this.game.config.width,
- +this.game.config.height
- );
- this.cameras.main.startFollow(this.player);
}
update(): void {
@@ -113,6 +141,31 @@ export class GameScene extends Phaser.Scene {
if (this.player.y > this.game.config.height) {
this.scene.start('GameScene');
}
+
+ if(this.player.body.velocity.y !=0){
+ this.emitter.start();
+ }else{
+ this.emitter.stop();
+ if(!this.checkTween) {
+ this.checkTween = true;
+ var tweenUpDown = this.tweens.add({
+ targets: this.player,
+ y: this.player.y - 10,
+ ease: 'Power1',
+ duration: 200,
+ yoyo: true,
+ repeat : 0,
+ onComplete:()=>{
+ tweenUpDown.remove();
+ }
+ })
+ }
+ }
+
+ if(this.player.body.velocity.y <0){
+ this.emitter.setAngle({min: 100, max: 180});
+ }
+
}
private spawnNewTower(): void {
@@ -153,6 +206,7 @@ export class GameScene extends Phaser.Scene {
const playerBody = this.player.body as Phaser.Physics.Arcade.Body;
playerBody.setVelocityY(-this.loadingBar.width);
this.isPlayerJumping = true;
+ this.checkTween = false;
this.loadingBarTween.stop();
this.loadingBar.width = 0;
}
diff --git a/src/games/space-invaders/assets/images/flares.json b/src/games/space-invaders/assets/images/flares.json
new file mode 100644
index 00000000..9b9c2d8a
--- /dev/null
+++ b/src/games/space-invaders/assets/images/flares.json
@@ -0,0 +1,57 @@
+{"frames": {
+
+ "blue":
+ {
+ "frame": {"x":2,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "green":
+ {
+ "frame": {"x":132,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "red":
+ {
+ "frame": {"x":262,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "white":
+ {
+ "frame": {"x":392,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "yellow":
+ {
+ "frame": {"x":522,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ }},
+ "meta": {
+ "app": "http://www.codeandweb.com/texturepacker",
+ "version": "1.0",
+ "image": "flares.png",
+ "format": "RGBA8888",
+ "size": {"w":652,"h":132},
+ "scale": "1",
+ "smartupdate": "$TexturePacker:SmartUpdate:f2781d89823d5a67fc31381af364b421:da82646b19b2f0c08684086824b1e581:71625947cf221c10549b852c13ffedc7$"
+ }
+ }
\ No newline at end of file
diff --git a/src/games/space-invaders/assets/images/flares.png b/src/games/space-invaders/assets/images/flares.png
new file mode 100644
index 00000000..df04af53
Binary files /dev/null and b/src/games/space-invaders/assets/images/flares.png differ
diff --git a/src/games/space-invaders/assets/pack.json b/src/games/space-invaders/assets/pack.json
index bc82e913..0cd944f4 100644
--- a/src/games/space-invaders/assets/pack.json
+++ b/src/games/space-invaders/assets/pack.json
@@ -22,6 +22,17 @@
"key": "player",
"url": "./assets/sprites/player.png"
},
+ {
+ "type": "image",
+ "key": "star",
+ "url": "https://cdn.shopify.com/s/files/1/3003/0152/files/nebula_star_100x_db655bb7-85f7-433d-8a52-d2e5e7cfbf5d_100x.png?v=1607703030"
+ },
+ {
+ "type": "atlas",
+ "key": "flares",
+ "textureURL": "./assets/images/flares.png",
+ "atlasURL": "./assets/images/flares.json"
+ },
{
"type": "spritesheet",
"key": "octopus",
diff --git a/src/games/space-invaders/src/objects/enemy.ts b/src/games/space-invaders/src/objects/enemy.ts
index 823b3f25..55681f11 100644
--- a/src/games/space-invaders/src/objects/enemy.ts
+++ b/src/games/space-invaders/src/objects/enemy.ts
@@ -139,6 +139,18 @@ export class Enemy extends Phaser.GameObjects.Sprite {
this.lives -= 1;
if (this.lives === 0) {
this.setActive(false);
+ var particles = this.scene.add.particles('flares').createEmitter({
+ frame: 'yellow',
+ x: this.x,
+ y: this.y,
+ lifespan: 200,
+ speed: { min: 10, max: 50 },
+ angle: {min: 0, max: 360},
+ scale: { start: 0.1, end: 0 },
+ quantity: 1,
+ maxParticles: 10,
+ blendMode: 'ADD'
+ });
} else {
this.isHurt = true;
}
diff --git a/src/games/space-invaders/src/objects/player.ts b/src/games/space-invaders/src/objects/player.ts
index 820b167d..2ac19a5d 100644
--- a/src/games/space-invaders/src/objects/player.ts
+++ b/src/games/space-invaders/src/objects/player.ts
@@ -9,6 +9,7 @@ export class Player extends Phaser.GameObjects.Image {
private flyingSpeed: number;
private lastShoot: number;
private shootingKey: Phaser.Input.Keyboard.Key;
+ private emitter!: Phaser.GameObjects.Particles.ParticleEmitter;
public getBullets(): Phaser.GameObjects.Group {
return this.bullets;
@@ -21,10 +22,26 @@ export class Player extends Phaser.GameObjects.Image {
this.initImage();
this.initInput();
this.initPhysics();
-
+ this.initParticles();
this.scene.add.existing(this);
}
+ private initParticles(){
+ var particles = this.scene.add.particles('flares');
+
+ this.emitter = particles.createEmitter({
+ frame: 'red',
+ lifespan: 200,
+ speed: { min: 200, max: 300 },
+ angle: {min: 80, max: 100},
+ gravityY: 300,
+ scale: { start: 0.1, end: 0 },
+ quantity: 1,
+ blendMode: 'ADD'
+ });
+ this.emitter.startFollow(this,0,6);
+ }
+
private initVariables(): void {
this.bullets = this.scene.add.group({
runChildUpdate: true
diff --git a/src/games/space-invaders/src/scenes/menu-scene.ts b/src/games/space-invaders/src/scenes/menu-scene.ts
index 7adc572b..9a802bd2 100644
--- a/src/games/space-invaders/src/scenes/menu-scene.ts
+++ b/src/games/space-invaders/src/scenes/menu-scene.ts
@@ -17,32 +17,58 @@ export class MenuScene extends Phaser.Scene {
}
create(): void {
+ var guideText = this.add.bitmapText(
+ this.sys.canvas.width / 2 ,
+ this.sys.canvas.height / 2,
+ 'font',
+ 'PRESS S TO PLAY',
+ 8
+ )
+ .setScale(0,0)
+ .setOrigin(0.5, 0.5)
+ .setAlpha(0)
+
this.bitmapTexts.push(
- this.add.bitmapText(
- this.sys.canvas.width / 2 - 65,
- this.sys.canvas.height / 2,
- 'font',
- 'PRESS S TO PLAY',
- 8
- )
+ guideText
);
-
+ var titleText = this.add.bitmapText(
+ this.sys.canvas.width / 2 - 60,
+ this.sys.canvas.height / 2 - 40,
+ 'font',
+ 'SPACE INVADERS',
+ 8
+ ).setScale(0,0);
this.bitmapTexts.push(
- this.add.bitmapText(
- this.sys.canvas.width / 2 - 60,
- this.sys.canvas.height / 2 - 40,
- 'font',
- 'SPACE INVADERS',
- 8
- )
+ titleText
);
+
+ this.tweens.add({
+ targets: this.bitmapTexts,
+ ease: 'Power1',
+ duration: 2000,
+ angle: 360,
+ alpha: 1,
+ scaleX: 1,
+ scaleY: 1,
+ yoyo: false,
+ repeat: 0,
+ });
}
update(): void {
if (this.startKey.isDown) {
- this.scene.start('HUDScene');
- this.scene.start('GameScene');
- this.scene.bringToTop('HUDScene');
+ this.tweens.add({
+ targets: this.bitmapTexts,
+ y: this.cameras.main.height +10,
+ ease: 'Power1',
+ duration: 1000,
+ onComplete: () => {
+ this.scene.stop();
+ this.scene.start('HUDScene');
+ this.scene.start('GameScene');
+ this.scene.bringToTop('HUDScene');
+ }
+ });
}
}
diff --git a/src/games/super-mario-land/src/objects/mario.ts b/src/games/super-mario-land/src/objects/mario.ts
index aaa6eb85..9983ad02 100644
--- a/src/games/super-mario-land/src/objects/mario.ts
+++ b/src/games/super-mario-land/src/objects/mario.ts
@@ -64,6 +64,7 @@ export class Mario extends Phaser.GameObjects.Sprite {
}
update(): void {
+ console.log('update',this.anims.getTotalFrames());
if (!this.isDying) {
this.handleInput();
this.handleAnimations();
diff --git a/src/games/tank/assets/animations/animations.json b/src/games/tank/assets/animations/animations.json
new file mode 100644
index 00000000..4863b9b0
--- /dev/null
+++ b/src/games/tank/assets/animations/animations.json
@@ -0,0 +1,15 @@
+{
+ "anims": [
+ {
+ "key": "btn-music",
+ "frames": {
+ "typeOfGeneration": "generateFrameNumbers",
+ "key": "btn-music",
+ "start": 0,
+ "end": 1
+ },
+ "repeat": -1,
+ "frameRate": 9
+ }
+ ]
+}
diff --git a/src/games/tank/assets/audio/battle.ogg b/src/games/tank/assets/audio/battle.ogg
new file mode 100644
index 00000000..bd2d3b86
Binary files /dev/null and b/src/games/tank/assets/audio/battle.ogg differ
diff --git a/src/games/tank/assets/audio/click.ogg b/src/games/tank/assets/audio/click.ogg
new file mode 100644
index 00000000..3939e8d9
Binary files /dev/null and b/src/games/tank/assets/audio/click.ogg differ
diff --git a/src/games/tank/assets/audio/destroy_0.ogg b/src/games/tank/assets/audio/destroy_0.ogg
new file mode 100644
index 00000000..2d29d0eb
Binary files /dev/null and b/src/games/tank/assets/audio/destroy_0.ogg differ
diff --git a/src/games/tank/assets/audio/destroy_1.ogg b/src/games/tank/assets/audio/destroy_1.ogg
new file mode 100644
index 00000000..39075274
Binary files /dev/null and b/src/games/tank/assets/audio/destroy_1.ogg differ
diff --git a/src/games/tank/assets/audio/dist_assets_TownTheme.mp3 b/src/games/tank/assets/audio/dist_assets_TownTheme.mp3
new file mode 100644
index 00000000..c85e6a39
Binary files /dev/null and b/src/games/tank/assets/audio/dist_assets_TownTheme.mp3 differ
diff --git a/src/games/tank/assets/audio/failed.ogg b/src/games/tank/assets/audio/failed.ogg
new file mode 100644
index 00000000..14bbbc48
Binary files /dev/null and b/src/games/tank/assets/audio/failed.ogg differ
diff --git a/src/games/tank/assets/audio/fire_0.ogg b/src/games/tank/assets/audio/fire_0.ogg
new file mode 100644
index 00000000..06ec4a7a
Binary files /dev/null and b/src/games/tank/assets/audio/fire_0.ogg differ
diff --git a/src/games/tank/assets/audio/fire_1.ogg b/src/games/tank/assets/audio/fire_1.ogg
new file mode 100644
index 00000000..b0884519
Binary files /dev/null and b/src/games/tank/assets/audio/fire_1.ogg differ
diff --git a/src/games/tank/assets/audio/menu_track.m4a b/src/games/tank/assets/audio/menu_track.m4a
new file mode 100644
index 00000000..5caef139
Binary files /dev/null and b/src/games/tank/assets/audio/menu_track.m4a differ
diff --git a/src/games/tank/assets/audio/menu_track.ogg b/src/games/tank/assets/audio/menu_track.ogg
new file mode 100644
index 00000000..8f18e8fc
Binary files /dev/null and b/src/games/tank/assets/audio/menu_track.ogg differ
diff --git a/src/games/tank/assets/audio/pickupammo_sfx.m4a b/src/games/tank/assets/audio/pickupammo_sfx.m4a
new file mode 100644
index 00000000..78cf7597
Binary files /dev/null and b/src/games/tank/assets/audio/pickupammo_sfx.m4a differ
diff --git a/src/games/tank/assets/audio/pickupammo_sfx.ogg b/src/games/tank/assets/audio/pickupammo_sfx.ogg
new file mode 100644
index 00000000..779853ad
Binary files /dev/null and b/src/games/tank/assets/audio/pickupammo_sfx.ogg differ
diff --git a/src/games/tank/assets/audio/player_death.ogg b/src/games/tank/assets/audio/player_death.ogg
new file mode 100644
index 00000000..c94aee23
Binary files /dev/null and b/src/games/tank/assets/audio/player_death.ogg differ
diff --git a/src/games/tank/assets/audio/rpgfire_sfx.m4a b/src/games/tank/assets/audio/rpgfire_sfx.m4a
new file mode 100644
index 00000000..7f9a7dd4
Binary files /dev/null and b/src/games/tank/assets/audio/rpgfire_sfx.m4a differ
diff --git a/src/games/tank/assets/audio/rpgfire_sfx.ogg b/src/games/tank/assets/audio/rpgfire_sfx.ogg
new file mode 100644
index 00000000..0222262c
Binary files /dev/null and b/src/games/tank/assets/audio/rpgfire_sfx.ogg differ
diff --git a/src/games/tank/assets/audio/select_sfx.ogg b/src/games/tank/assets/audio/select_sfx.ogg
new file mode 100644
index 00000000..214df9f2
Binary files /dev/null and b/src/games/tank/assets/audio/select_sfx.ogg differ
diff --git a/src/games/tank/assets/audio/tankshot_sfx.m4a b/src/games/tank/assets/audio/tankshot_sfx.m4a
new file mode 100644
index 00000000..3e553f28
Binary files /dev/null and b/src/games/tank/assets/audio/tankshot_sfx.m4a differ
diff --git a/src/games/tank/assets/audio/tankshot_sfx.ogg b/src/games/tank/assets/audio/tankshot_sfx.ogg
new file mode 100644
index 00000000..66a813f6
Binary files /dev/null and b/src/games/tank/assets/audio/tankshot_sfx.ogg differ
diff --git a/src/games/tank/assets/audio/tc_fire_0.ogg b/src/games/tank/assets/audio/tc_fire_0.ogg
new file mode 100644
index 00000000..064c0c51
Binary files /dev/null and b/src/games/tank/assets/audio/tc_fire_0.ogg differ
diff --git a/src/games/tank/assets/audio/tc_fire_1.ogg b/src/games/tank/assets/audio/tc_fire_1.ogg
new file mode 100644
index 00000000..5a5d278e
Binary files /dev/null and b/src/games/tank/assets/audio/tc_fire_1.ogg differ
diff --git a/src/games/tank/assets/audio/war_start.ogg b/src/games/tank/assets/audio/war_start.ogg
new file mode 100644
index 00000000..7228bf04
Binary files /dev/null and b/src/games/tank/assets/audio/war_start.ogg differ
diff --git a/src/games/tank/assets/audio/win.ogg b/src/games/tank/assets/audio/win.ogg
new file mode 100644
index 00000000..0b74e720
Binary files /dev/null and b/src/games/tank/assets/audio/win.ogg differ
diff --git a/src/games/tank/assets/images/bg.png b/src/games/tank/assets/images/bg.png
new file mode 100644
index 00000000..6d83c861
Binary files /dev/null and b/src/games/tank/assets/images/bg.png differ
diff --git a/src/games/tank/assets/images/btn_menu.png b/src/games/tank/assets/images/btn_menu.png
new file mode 100644
index 00000000..7aef15ad
Binary files /dev/null and b/src/games/tank/assets/images/btn_menu.png differ
diff --git a/src/games/tank/assets/images/btn_startbattle.png b/src/games/tank/assets/images/btn_startbattle.png
new file mode 100644
index 00000000..c495a906
Binary files /dev/null and b/src/games/tank/assets/images/btn_startbattle.png differ
diff --git a/src/games/tank/assets/images/curosr.png b/src/games/tank/assets/images/curosr.png
new file mode 100644
index 00000000..f6891810
Binary files /dev/null and b/src/games/tank/assets/images/curosr.png differ
diff --git a/src/games/tank/assets/images/exit-btn.png b/src/games/tank/assets/images/exit-btn.png
new file mode 100644
index 00000000..c056bf52
Binary files /dev/null and b/src/games/tank/assets/images/exit-btn.png differ
diff --git a/src/games/tank/assets/images/flares.json b/src/games/tank/assets/images/flares.json
new file mode 100644
index 00000000..9b9c2d8a
--- /dev/null
+++ b/src/games/tank/assets/images/flares.json
@@ -0,0 +1,57 @@
+{"frames": {
+
+ "blue":
+ {
+ "frame": {"x":2,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "green":
+ {
+ "frame": {"x":132,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "red":
+ {
+ "frame": {"x":262,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "white":
+ {
+ "frame": {"x":392,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ },
+ "yellow":
+ {
+ "frame": {"x":522,"y":2,"w":128,"h":128},
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
+ "sourceSize": {"w":128,"h":128},
+ "pivot": {"x":0.5,"y":0.5}
+ }},
+ "meta": {
+ "app": "http://www.codeandweb.com/texturepacker",
+ "version": "1.0",
+ "image": "flares.png",
+ "format": "RGBA8888",
+ "size": {"w":652,"h":132},
+ "scale": "1",
+ "smartupdate": "$TexturePacker:SmartUpdate:f2781d89823d5a67fc31381af364b421:da82646b19b2f0c08684086824b1e581:71625947cf221c10549b852c13ffedc7$"
+ }
+ }
\ No newline at end of file
diff --git a/src/games/tank/assets/images/flares.png b/src/games/tank/assets/images/flares.png
new file mode 100644
index 00000000..df04af53
Binary files /dev/null and b/src/games/tank/assets/images/flares.png differ
diff --git a/src/games/tank/assets/images/logo.png b/src/games/tank/assets/images/logo.png
new file mode 100644
index 00000000..32a64d4a
Binary files /dev/null and b/src/games/tank/assets/images/logo.png differ
diff --git a/src/games/tank/assets/images/muzzleflash3.png b/src/games/tank/assets/images/muzzleflash3.png
new file mode 100644
index 00000000..525cf221
Binary files /dev/null and b/src/games/tank/assets/images/muzzleflash3.png differ
diff --git a/src/games/tank/assets/images/pause-btn.png b/src/games/tank/assets/images/pause-btn.png
new file mode 100644
index 00000000..791c8dbc
Binary files /dev/null and b/src/games/tank/assets/images/pause-btn.png differ
diff --git a/src/games/tank/assets/images/play-btn.png b/src/games/tank/assets/images/play-btn.png
new file mode 100644
index 00000000..b2629c41
Binary files /dev/null and b/src/games/tank/assets/images/play-btn.png differ
diff --git a/src/games/tank/assets/images/replay-btn.png b/src/games/tank/assets/images/replay-btn.png
new file mode 100644
index 00000000..5cb01a2f
Binary files /dev/null and b/src/games/tank/assets/images/replay-btn.png differ
diff --git a/src/games/tank/assets/images/smoke-puff.png b/src/games/tank/assets/images/smoke-puff.png
new file mode 100644
index 00000000..ebf19193
Binary files /dev/null and b/src/games/tank/assets/images/smoke-puff.png differ
diff --git a/src/games/tank/assets/images/smoke0.png b/src/games/tank/assets/images/smoke0.png
new file mode 100644
index 00000000..4d27a696
Binary files /dev/null and b/src/games/tank/assets/images/smoke0.png differ
diff --git a/src/games/tank/assets/pack.json b/src/games/tank/assets/pack.json
index ee4c9606..9fd0d75b 100644
--- a/src/games/tank/assets/pack.json
+++ b/src/games/tank/assets/pack.json
@@ -81,6 +81,131 @@
"type": "image",
"key": "treeLarge",
"url": "./assets/obstacles/tree-large.png"
+ },
+ {
+ "type": "image",
+ "key": "background",
+ "url": "./assets/images/bg.png"
+ }
+ ,
+ {
+ "type": "image",
+ "key": "btn-start",
+ "url": "./assets/images/btn_startbattle.png"
+ },
+ {
+ "type": "image",
+ "key": "logo",
+ "url": "./assets/images/logo.png"
+ },
+ {
+ "type": "image",
+ "key": "btn-menu",
+ "url": "./assets/images/btn_menu.png"
+ },
+ {
+ "type": "image",
+ "key": "btn-pause",
+ "url": "./assets/images/pause-btn.png"
+ },
+ {
+ "type": "image",
+ "key": "btn-replay",
+ "url": "./assets/images/replay-btn.png"
+ },
+ {
+ "type": "image",
+ "key": "btn-play",
+ "url": "./assets/images/play-btn.png"
+ },
+ {
+ "type": "image",
+ "key": "curosr",
+ "url": "./assets/images/curosr.png"
+ },
+ {
+ "type": "image",
+ "key": "fire",
+ "url": "./assets/images/muzzleflash3.png"
+ },
+ {
+ "type": "image",
+ "key": "dark-smoke",
+ "url": "./assets/images/smoke-puff.png"
+ },
+ {
+ "type": "spritesheet",
+ "key": "btn-sound",
+ "url": "./assets/sprites/btn-sound.png",
+ "frameConfig": {
+ "frameWidth": 167,
+ "frameHeight": 156
+ }
+ },
+ {
+ "type": "spritesheet",
+ "key": "btn-music",
+ "url": "./assets/sprites/btn-music.png",
+ "frameConfig": {
+ "frameWidth": 167,
+ "frameHeight": 156
+ }
+ },
+ {
+ "type": "json",
+ "key": "animationJSON",
+ "url": "./assets/animations/animations.json"
+ },
+ {
+ "type": "atlas",
+ "key": "flares",
+ "textureURL": "./assets/images/flares.png",
+ "atlasURL": "./assets/images/flares.json"
+ },
+ {
+ "type": "audio",
+ "key": "menu_track",
+ "url": "./assets/audio/menu_track.m4a"
+ },
+ {
+ "type": "audio",
+ "key": "select",
+ "url": "./assets/audio/select_sfx.ogg"
+ },
+ {
+ "type": "audio",
+ "key": "click",
+ "url": "./assets/audio/click.ogg"
+ },
+ {
+ "type": "audio",
+ "key": "player-shooter",
+ "url": "./assets/audio/fire_1.ogg"
+ },
+ {
+ "type": "audio",
+ "key": "player-death",
+ "url": "./assets/audio/player_death.ogg"
+ },
+ {
+ "type": "audio",
+ "key": "enemy-death",
+ "url": "./assets/audio/destroy_1.ogg"
+ },
+ {
+ "type": "audio",
+ "key": "battle",
+ "url": "./assets/audio/battle.ogg"
+ },
+ {
+ "type": "audio",
+ "key": "gameover",
+ "url": "./assets/audio/dist_assets_TownTheme.mp3"
+ },
+ {
+ "type": "audio",
+ "key": "menu_start",
+ "url": "./assets/audio/rpgfire_sfx.ogg"
}
]
}
diff --git a/src/games/tank/assets/sprites/btn-music.png b/src/games/tank/assets/sprites/btn-music.png
new file mode 100644
index 00000000..bef4c1dd
Binary files /dev/null and b/src/games/tank/assets/sprites/btn-music.png differ
diff --git a/src/games/tank/assets/sprites/btn-sound.png b/src/games/tank/assets/sprites/btn-sound.png
new file mode 100644
index 00000000..acbc516b
Binary files /dev/null and b/src/games/tank/assets/sprites/btn-sound.png differ
diff --git a/src/games/tank/assets/sprites/play-pause.png b/src/games/tank/assets/sprites/play-pause.png
new file mode 100644
index 00000000..6ffe350e
Binary files /dev/null and b/src/games/tank/assets/sprites/play-pause.png differ
diff --git a/src/games/tank/src/config.ts b/src/games/tank/src/config.ts
index 10a62c2a..607f2f07 100644
--- a/src/games/tank/src/config.ts
+++ b/src/games/tank/src/config.ts
@@ -1,6 +1,8 @@
-import { BootScene } from './scenes/boot-scene';
-import { GameScene } from './scenes/game-scene';
-import { MenuScene } from './scenes/menu-scene';
+import { BootScene } from './scenes/BootScene';
+import { GameScene } from './scenes/GameScene';
+import GameOverScene from './scenes/game-over-scene/GameOverScene';
+import { MenuScene } from './scenes/menu-scene/MenuScene';
+import { PauseScene } from './scenes/pause-scene/PauseScene';
export const GameConfig: Phaser.Types.Core.GameConfig = {
title: 'Tank',
@@ -11,7 +13,7 @@ export const GameConfig: Phaser.Types.Core.GameConfig = {
zoom: 0.6,
type: Phaser.AUTO,
parent: 'game',
- scene: [BootScene, MenuScene, GameScene],
+ scene: [BootScene,GameOverScene, MenuScene, GameScene, PauseScene],
input: {
keyboard: true
},
@@ -19,7 +21,7 @@ export const GameConfig: Phaser.Types.Core.GameConfig = {
default: 'arcade',
arcade: {
gravity: { y: 0 },
- debug: false
+ // debug: true
}
},
backgroundColor: '#000000',
diff --git a/src/games/tank/src/consts/EventKeys.ts b/src/games/tank/src/consts/EventKeys.ts
new file mode 100644
index 00000000..d5a20edf
--- /dev/null
+++ b/src/games/tank/src/consts/EventKeys.ts
@@ -0,0 +1,12 @@
+enum EventKeys {
+ RESTART_GAME = 'restart-game',
+ CONTINUE = 'continue',
+ START_GAME = 'start-game',
+ MUTE_MUSIC = 'mute-music',
+ UNMUTE_MUSIC = 'unmute-music',
+ ENEMY_DEATH = 'enemy-death',
+ PLAYER_SHOOTING = 'player-shooting',
+ PLAYER_DEATH = 'player-death',
+}
+
+export default EventKeys;
\ No newline at end of file
diff --git a/src/games/tank/src/consts/SceneKeys.ts b/src/games/tank/src/consts/SceneKeys.ts
new file mode 100644
index 00000000..205780c6
--- /dev/null
+++ b/src/games/tank/src/consts/SceneKeys.ts
@@ -0,0 +1,9 @@
+enum SceneKeys {
+ BOOT_SCENE = "BootScene",
+ MENU_SCENE = "MenuScene",
+ GAME_SCENE = "GameScene",
+ GAME_OVER_SCENE = "GameOverScene",
+ PAUSE_SCENE = "PauseScene",
+}
+
+export default SceneKeys;
\ No newline at end of file
diff --git a/src/games/tank/src/consts/const.ts b/src/games/tank/src/consts/const.ts
new file mode 100644
index 00000000..5c8487d0
--- /dev/null
+++ b/src/games/tank/src/consts/const.ts
@@ -0,0 +1,4 @@
+export let CONST = {
+ TIME_ROTATE_STEP : 100,
+ TANK_SPEED : 200,
+};
diff --git a/src/games/tank/src/helpers/helpers.ts b/src/games/tank/src/helpers/helpers.ts
new file mode 100644
index 00000000..7a428abe
--- /dev/null
+++ b/src/games/tank/src/helpers/helpers.ts
@@ -0,0 +1,35 @@
+import { CONST } from "../consts/const";
+import { Player } from "../objects/Player";
+
+export const highScore = function (scene: Phaser.Scene){
+ var score = scene.registry.get('score');
+ if (localStorage.getItem('highscore')) {
+ if (localStorage.getItem('highscore') < score) {
+ localStorage.setItem('highscore', score);
+ }
+ } else {
+ localStorage.setItem('highscore', score);
+ }
+ return localStorage.getItem('highscore');
+}
+
+export const angleParticleBullet = function (angle: number){
+ if(angle < 0){
+ return angle+360 - 90;
+ }
+ return angle - 90;
+}
+
+export const playSound = function (scene: Phaser.Scene, audioKey: string){
+ scene.sound.add(audioKey).play;
+}
+
+export const newPlayer = function (scene: Phaser.Scene, x: number, y: number){
+ return new Player({
+ scene: this,
+ x: x,
+ y: y,
+ texture: 'tankBlue',
+ rateOfFire: 80,
+ });
+}
\ No newline at end of file
diff --git a/src/games/tank/src/interfaces/bullet.interface.ts b/src/games/tank/src/interfaces/IBulletConstructor.d.ts
similarity index 70%
rename from src/games/tank/src/interfaces/bullet.interface.ts
rename to src/games/tank/src/interfaces/IBulletConstructor.d.ts
index 5a64b052..f5a5c558 100644
--- a/src/games/tank/src/interfaces/bullet.interface.ts
+++ b/src/games/tank/src/interfaces/IBulletConstructor.d.ts
@@ -1,8 +1,9 @@
-export interface IBulletConstructor {
+interface IBulletConstructor {
scene: Phaser.Scene;
rotation: number;
x: number;
y: number;
texture: string;
frame?: string | number;
+ damage: number;
}
diff --git a/src/games/tank/src/interfaces/IButtonConstructor.d.ts b/src/games/tank/src/interfaces/IButtonConstructor.d.ts
new file mode 100644
index 00000000..64240d40
--- /dev/null
+++ b/src/games/tank/src/interfaces/IButtonConstructor.d.ts
@@ -0,0 +1,8 @@
+interface IButtonConstructor {
+ scene: Phaser.Scene;
+ x: number;
+ y: number;
+ texture: string;
+ frame?: string | number;
+ soundPress: string;
+}
diff --git a/src/games/tank/src/interfaces/image.interface.ts b/src/games/tank/src/interfaces/IImageConstructor.d.ts
similarity index 72%
rename from src/games/tank/src/interfaces/image.interface.ts
rename to src/games/tank/src/interfaces/IImageConstructor.d.ts
index 4e54a6db..184b070e 100644
--- a/src/games/tank/src/interfaces/image.interface.ts
+++ b/src/games/tank/src/interfaces/IImageConstructor.d.ts
@@ -1,4 +1,4 @@
-export interface IImageConstructor {
+interface IImageConstructor {
scene: Phaser.Scene;
x: number;
y: number;
diff --git a/src/games/tank/src/interfaces/ISpriteConstructor.d.ts b/src/games/tank/src/interfaces/ISpriteConstructor.d.ts
new file mode 100644
index 00000000..fb448794
--- /dev/null
+++ b/src/games/tank/src/interfaces/ISpriteConstructor.d.ts
@@ -0,0 +1,7 @@
+interface ISpriteConstructor {
+ scene: Phaser.Scene;
+ x: number;
+ y: number;
+ texture: string;
+ frame?: string | number;
+}
diff --git a/src/games/tank/src/interfaces/ITankConstructor.d.ts b/src/games/tank/src/interfaces/ITankConstructor.d.ts
new file mode 100644
index 00000000..b0b04bf8
--- /dev/null
+++ b/src/games/tank/src/interfaces/ITankConstructor.d.ts
@@ -0,0 +1,8 @@
+interface ITankConstructor {
+ scene: Phaser.Scene;
+ x: number;
+ y: number;
+ texture: string;
+ frame?: string | number;
+ rateOfFire: number;
+}
diff --git a/src/games/tank/src/interfaces/IToggleButtonConstructor.d.ts b/src/games/tank/src/interfaces/IToggleButtonConstructor.d.ts
new file mode 100644
index 00000000..828350c1
--- /dev/null
+++ b/src/games/tank/src/interfaces/IToggleButtonConstructor.d.ts
@@ -0,0 +1,9 @@
+interface IToggleButtonConstructor {
+ scene: Phaser.Scene;
+ x: number;
+ y: number;
+ texture: string;
+ frame?: string | number;
+ numberOfFrames: number;
+ soundPress: string;
+}
diff --git a/src/games/tank/src/objects/bullet.ts b/src/games/tank/src/objects/bullet.ts
index 45ac251a..d95c816f 100644
--- a/src/games/tank/src/objects/bullet.ts
+++ b/src/games/tank/src/objects/bullet.ts
@@ -1,26 +1,47 @@
-import { IBulletConstructor } from '../interfaces/bullet.interface';
+import { angleParticleBullet } from "../helpers/helpers";
export class Bullet extends Phaser.GameObjects.Image {
body: Phaser.Physics.Arcade.Body;
-
private bulletSpeed: number;
+ private damage!: number;
+
+ // particle
+ private fire: Phaser.GameObjects.Particles.ParticleEmitter;
+ private darkSmoke: Phaser.GameObjects.Particles.ParticleEmitter;
constructor(aParams: IBulletConstructor) {
super(aParams.scene, aParams.x, aParams.y, aParams.texture);
this.rotation = aParams.rotation;
+ this.damage = aParams.damage;
+
+ this.initVariables();
this.initImage();
+ this.initPhysics();
+ this.createParticalBullet();
this.scene.add.existing(this);
}
- private initImage(): void {
+ update(): void {
+ this.fire.setAngle(angleParticleBullet(this.angle))
+ }
+
+ public getDamage(){
+ return this.damage;
+ }
+
+ public destroyBullet() {
+ this.fire.stop();
+ this.darkSmoke.stop();
+ this.destroy();
+ }
+
+ private initVariables(){
// variables
this.bulletSpeed = 1000;
+ }
- // image
- this.setOrigin(0.5, 0.5);
- this.setDepth(2);
-
+ private initPhysics(){
// physics
this.scene.physics.world.enable(this);
this.scene.physics.velocityFromRotation(
@@ -30,5 +51,32 @@ export class Bullet extends Phaser.GameObjects.Image {
);
}
- update(): void {}
+ private initImage(): void {
+ // image
+ this.setOrigin(0.5, 0.5);
+ this.setDepth(2);
+ }
+
+ private createParticalBullet(){
+ this.fire = this.scene.add.particles('fire').createEmitter({
+ speed: { min: 100, max: 200 },
+ scale: { start: 0, end: 1, ease: 'Back.easeOut' },
+ alpha: { start: 1, end: 0, ease: 'Quart.easeOut' },
+ lifespan: 600,
+ follow: this,
+ });
+ this.fire.reserve(1000);
+
+ this.darkSmoke = this.scene.add.particles('dark-smoke').createEmitter({
+ x: this.x,
+ y: this.y,
+ speed: { min: 20, max: 100 },
+ angle: { min: 0, max: 360},
+ scale: { start: 1, end: 0},
+ alpha: { start: 0, end: 0.1},
+ lifespan: 600,
+ follow: this,
+ });
+ this.darkSmoke.reserve(1000);
+ }
}
diff --git a/src/games/tank/src/objects/button/BaseButton.ts b/src/games/tank/src/objects/button/BaseButton.ts
new file mode 100644
index 00000000..02167973
--- /dev/null
+++ b/src/games/tank/src/objects/button/BaseButton.ts
@@ -0,0 +1,71 @@
+
+export class BaseButton extends Phaser.GameObjects.Image {
+ // variables
+ protected soundPress: Phaser.Sound.BaseSound;
+ private isClick: boolean;
+
+ constructor(aParams: IButtonConstructor) {
+ super(aParams.scene, aParams.x, aParams.y, aParams.texture, aParams.frame);
+ // variables
+ this.isClick = false;
+ this.soundPress = this.scene.sound.add(aParams.soundPress);
+ this.setInteractive({ useHandCursor: true });
+ this.initListenEvent();
+ this.scene.add.existing(this);
+ }
+
+ protected TouchDown(){
+ this.scene.tweens.add({
+ targets: this,
+ scaleX: 0.9,
+ scaleY: 0.9,
+ ease: 'Sine.easeInOut',
+ duration: 100,
+ repeat: 0,
+ paused: true
+ })
+ }
+
+ protected TouchUp(switchTexture?: Function){
+ this.scene.tweens.add({
+ targets: this,
+ scaleX: 1,
+ scaleY: 1,
+ ease: 'Sine.easeInOut',
+ duration: 100,
+ repeat: 0,
+ paused: true,
+ onComplete: () => {
+ console.log("onPressUp");
+ this.isClick = false;
+ this.handleOnPress();
+ switchTexture();
+ }
+ })
+ }
+
+ protected initListenEvent(switchTexture? : Function){
+ this.on(Phaser.Input.Events.POINTER_UP, () => {
+ this.TouchUp(switchTexture);
+ });
+
+ this.on(Phaser.Input.Events.POINTER_DOWN, () => {
+ console.log("Phaser.Input.Events.POINTER_DOWN");
+ this.isClick = true;
+ this.TouchDown();
+ // play audio click
+ if(!this.scene.registry.get('muteSound'))
+ this.soundPress.play();
+ });
+
+ this.on(Phaser.Input.Events.POINTER_OUT, () => {
+ if(this.isClick)
+ this.TouchUp();
+ });
+ }
+
+ public handleOnPress(){
+
+ }
+
+}
diff --git a/src/games/tank/src/objects/button/normal-button/Button.ts b/src/games/tank/src/objects/button/normal-button/Button.ts
new file mode 100644
index 00000000..85087be5
--- /dev/null
+++ b/src/games/tank/src/objects/button/normal-button/Button.ts
@@ -0,0 +1,71 @@
+
+export class Button extends Phaser.GameObjects.Image {
+ // variables
+ protected tweenDown: Phaser.Tweens.Tween;
+ protected tweenUp: Phaser.Tweens.Tween;
+ protected soundPress: Phaser.Sound.BaseSound;
+ private isClick: boolean;
+
+ constructor(aParams: IButtonConstructor) {
+ super(aParams.scene, aParams.x, aParams.y, aParams.texture, aParams.frame);
+ // variables
+ this.isClick = false;
+ this.soundPress = this.scene.sound.add(aParams.soundPress);
+ this.setInteractive({ useHandCursor: true });
+ this.initTween();
+ this.initListenEvent();
+ this.scene.add.existing(this);
+ }
+ update(...args: any[]): void {
+
+ }
+ protected initTween(){
+ this.tweenDown = this.scene.tweens.add({
+ targets: this,
+ scaleX: 0.9,
+ scaleY: 0.9,
+ ease: 'Sine.easeInOut',
+ duration: 100,
+ repeat: 0,
+ paused: true
+ })
+
+ this.tweenUp = this.scene.tweens.add({
+ targets: this,
+ scaleX: 1,
+ scaleY: 1,
+ ease: 'Sine.easeInOut',
+ duration: 100,
+ repeat: 0,
+ paused: true,
+ onComplete: () => {
+ this.isClick = false;
+ this.handleOnPress();
+ }
+ })
+ }
+
+ private initListenEvent(){
+ this.on(Phaser.Input.Events.POINTER_UP, () => {
+ this.tweenUp.play();
+ });
+
+ this.on(Phaser.Input.Events.POINTER_DOWN, () => {
+ this.isClick = true;
+ this.tweenDown.play();
+ // play audio click
+ if(!this.scene.registry.get('muteSound'))
+ this.soundPress.play();
+ });
+
+ this.on(Phaser.Input.Events.POINTER_OUT, () => {
+ if(this.isClick)
+ this.tweenUp.play();
+ });
+ }
+
+ public handleOnPress(){
+
+ }
+
+}
diff --git a/src/games/tank/src/objects/button/normal-button/MenuButton.ts b/src/games/tank/src/objects/button/normal-button/MenuButton.ts
new file mode 100644
index 00000000..cc71f5b5
--- /dev/null
+++ b/src/games/tank/src/objects/button/normal-button/MenuButton.ts
@@ -0,0 +1,9 @@
+import SceneKeys from "../../../consts/SceneKeys";
+import { Button } from "./Button";
+
+export class MenuButton extends Button{
+ public handleOnPress(){
+ this.scene.scene.pause();
+ this.scene.scene.launch(SceneKeys.PAUSE_SCENE);
+ }
+}
\ No newline at end of file
diff --git a/src/games/tank/src/objects/button/normal-button/PlayButton.ts b/src/games/tank/src/objects/button/normal-button/PlayButton.ts
new file mode 100644
index 00000000..4087d1d6
--- /dev/null
+++ b/src/games/tank/src/objects/button/normal-button/PlayButton.ts
@@ -0,0 +1,8 @@
+import EventKeys from "../../../consts/EventKeys";
+import { Button } from "./Button";
+
+export class PlayButton extends Button{
+ public handleOnPress(){
+ this.scene.events.emit(EventKeys.CONTINUE);
+ }
+}
\ No newline at end of file
diff --git a/src/games/tank/src/objects/button/normal-button/ReplayButton.ts b/src/games/tank/src/objects/button/normal-button/ReplayButton.ts
new file mode 100644
index 00000000..97134f68
--- /dev/null
+++ b/src/games/tank/src/objects/button/normal-button/ReplayButton.ts
@@ -0,0 +1,9 @@
+import EventKeys from "../../../consts/EventKeys";
+import { Button } from "./Button";
+
+export class ReplayButton extends Button{
+ public handleOnPress(){
+ this.scene.events.emit(EventKeys.RESTART_GAME);
+ console.log("GameScene: ");
+ }
+}
\ No newline at end of file
diff --git a/src/games/tank/src/objects/button/normal-button/StartButton.ts b/src/games/tank/src/objects/button/normal-button/StartButton.ts
new file mode 100644
index 00000000..397e9a95
--- /dev/null
+++ b/src/games/tank/src/objects/button/normal-button/StartButton.ts
@@ -0,0 +1,21 @@
+import EventKeys from "../../../consts/EventKeys";
+import SceneKeys from "../../../consts/SceneKeys";
+import { Button } from "./Button";
+
+export class StartButton extends Button{
+ protected initTween(){
+ super.initTween();
+ this.scene.tweens.add({
+ targets: this,
+ scaleX: 1.2,
+ scaleY: 1.2,
+ ease: 'Sine.easeInOut',
+ duration: 500,
+ yoyo: true,
+ repeat: -1,
+ })
+ }
+ public handleOnPress(){
+ this.scene.events.emit(EventKeys.START_GAME);
+ }
+}
\ No newline at end of file
diff --git a/src/games/tank/src/objects/button/toggle-button/ButtonMusic.ts b/src/games/tank/src/objects/button/toggle-button/ButtonMusic.ts
new file mode 100644
index 00000000..433607bd
--- /dev/null
+++ b/src/games/tank/src/objects/button/toggle-button/ButtonMusic.ts
@@ -0,0 +1,24 @@
+import EventKeys from "../../../consts/EventKeys";
+import { ToggleButton } from "./ToggleButton";
+
+export class ButtonMusic extends ToggleButton{
+ preUpdate(): void {
+ if(this.scene.registry.get('muteMusic'))
+ this.setFrame(0);
+ else{
+ this.setFrame(1);
+ }
+ }
+
+ protected handerOnPress(){
+ const isMuteMusic = this.scene.registry.get('muteMusic');
+
+ if(!isMuteMusic){
+ this.scene.registry.set('muteMusic', true);
+ this.scene.events.emit(EventKeys.MUTE_MUSIC);
+ }else{
+ this.scene.registry.set('muteMusic', false);
+ this.scene.events.emit(EventKeys.UNMUTE_MUSIC);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/games/tank/src/objects/button/toggle-button/ButtonSound.ts b/src/games/tank/src/objects/button/toggle-button/ButtonSound.ts
new file mode 100644
index 00000000..4c46028e
--- /dev/null
+++ b/src/games/tank/src/objects/button/toggle-button/ButtonSound.ts
@@ -0,0 +1,18 @@
+import { ToggleButton } from "./ToggleButton";
+
+export class ButtonSound extends ToggleButton{
+ preUpdate(): void {
+ if(this.scene.registry.get('muteSound'))
+ this.setFrame(0);
+ else{
+ this.setFrame(1);
+ }
+ }
+ protected handerOnPress(): void {
+ if(!this.scene.registry.get('muteSound')){
+ this.scene.registry.set('muteSound', true);
+ }else{
+ this.scene.registry.set('muteSound', false);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/games/tank/src/objects/button/toggle-button/ToggleButton.ts b/src/games/tank/src/objects/button/toggle-button/ToggleButton.ts
new file mode 100644
index 00000000..ea8c26e5
--- /dev/null
+++ b/src/games/tank/src/objects/button/toggle-button/ToggleButton.ts
@@ -0,0 +1,86 @@
+
+export class ToggleButton extends Phaser.GameObjects.Sprite {
+ protected soundPress!: Phaser.Sound.BaseSound;
+
+ // variables
+ private tweenDown: Phaser.Tweens.Tween;
+ private tweenUp: Phaser.Tweens.Tween;
+ private numberOfFrames!: number;
+ private isClick: boolean;
+
+ constructor(aParams: IToggleButtonConstructor) {
+ super(aParams.scene, aParams.x, aParams.y, aParams.texture, aParams.frame);
+
+ // variables
+ this.scene = aParams.scene;
+ this.numberOfFrames = aParams.numberOfFrames;
+ this.isClick = false;
+ this.soundPress = this.scene.sound.add(aParams.soundPress);
+
+ this.initSprite();
+ this.initTween();
+ this.onPress();
+ this.scene.add.existing(this);
+ this.setInteractive({ useHandCursor: true });
+ }
+
+ private initSprite() {
+ // sprite
+ }
+ private initTween(){
+ this.tweenDown = this.scene.tweens.add({
+ targets: this,
+ scaleX: 0.9,
+ scaleY: 0.9,
+ ease: 'Sine.easeInOut',
+ duration: 100,
+ repeat: 0,
+ paused: true
+ })
+
+ this.tweenUp = this.scene.tweens.add({
+ targets: this,
+ scaleX: 1,
+ scaleY: 1,
+ ease: 'Sine.easeInOut',
+ duration: 100,
+ repeat: 0,
+ paused: true,
+ onComplete: ()=>{
+ this.isClick = false;
+ this.switchTexture();
+ this.handerOnPress();
+ }
+ })
+ }
+
+ private onPress(){
+ this.on(Phaser.Input.Events.POINTER_UP, () => {
+ this.tweenUp.play();
+ });
+
+ this.on(Phaser.Input.Events.POINTER_DOWN, () => {
+ this.isClick = true;
+ this.tweenDown.play();
+ if(!this.scene.registry.get('muteSound'))
+ this.soundPress.play();
+ });
+
+ this.on(Phaser.Input.Events.POINTER_OVER, () => {
+ if(this.isClick)
+ this.tweenUp.play();
+ })
+ }
+
+ private switchTexture() {
+ let currentFrame = parseInt(this.frame.name);
+ let nextFrame = currentFrame + 1;
+ if(nextFrame > this.numberOfFrames - 1)
+ nextFrame = 0;
+ this.setFrame(nextFrame);
+ }
+
+ protected handerOnPress(){
+
+ }
+}
diff --git a/src/games/tank/src/objects/enemy.ts b/src/games/tank/src/objects/enemy.ts
index 4d5f78d6..46eb5700 100644
--- a/src/games/tank/src/objects/enemy.ts
+++ b/src/games/tank/src/objects/enemy.ts
@@ -1,21 +1,57 @@
-import { Bullet } from './bullet';
-import { IImageConstructor } from '../interfaces/image.interface';
+import EventKeys from "../consts/EventKeys";
+import { Bullet } from "./Bullet";
+import { Player } from "./Player";
-export class Enemy extends Phaser.GameObjects.Image {
+export class Enemy extends Phaser.GameObjects.Container {
body: Phaser.Physics.Arcade.Body;
// variables
private health: number;
- private lastShoot: number;
- private speed: number;
+ private nextShoot: number;
+ private texture: string;
+ private rateOfFire: number;
// children
private barrel: Phaser.GameObjects.Image;
private lifeBar: Phaser.GameObjects.Graphics;
-
+ private tank: Phaser.GameObjects.Image;
+
// game objects
private bullets: Phaser.GameObjects.Group;
+ constructor(aParams: ITankConstructor) {
+ super(aParams.scene, aParams.x, aParams.y);
+
+ this.texture = aParams.texture;
+ this.rateOfFire = aParams.rateOfFire;
+
+ this.initVariables();
+ this.initContainer();
+ this.moveEnemy();
+ this.scene.add.existing(this);
+ }
+
+ update(player: Player) : void {
+ if (player.active && this.active) {
+ this.shooting();
+
+ var angle = Phaser.Math.Angle.Between(
+ this.body.x,
+ this.body.y,
+ player.body.x,
+ player.body.y
+ );
+
+ this.getBarrel().angle =
+ (angle + Math.PI / 2) * Phaser.Math.RAD_TO_DEG;
+
+ } else {
+ this.destroy();
+ this.barrel.destroy();
+ this.lifeBar.destroy();
+ }
+ }
+
public getBarrel(): Phaser.GameObjects.Image {
return this.barrel;
}
@@ -24,37 +60,60 @@ export class Enemy extends Phaser.GameObjects.Image {
return this.bullets;
}
- constructor(aParams: IImageConstructor) {
- super(aParams.scene, aParams.x, aParams.y, aParams.texture, aParams.frame);
-
- this.initContainer();
- this.scene.add.existing(this);
+ public updateHealth(damage: number): void {
+ this.initTweenDamage(damage);
+ if (this.health > 0) {
+ this.health -= damage;
+ this.redrawLifebar();
+ } else {
+ this.scene.events.emit(EventKeys.ENEMY_DEATH)
+ this.health = 0;
+ // particles
+ this.initParticlesDeath();
+ this.active = false;
+ }
}
- private initContainer() {
+ private initVariables(){
// variables
this.health = 1;
- this.lastShoot = 0;
- this.speed = 100;
+ this.nextShoot = 0;
+ }
+ private initContainer() {
// image
- this.setDepth(0);
+ this.tank = this.scene.physics.add.image(0, 0, this.texture)
+ .setImmovable(true);
+ this.body = this.tank.body as Phaser.Physics.Arcade.Body;
this.barrel = this.scene.add.image(0, 0, 'barrelRed');
this.barrel.setOrigin(0.5, 1);
this.barrel.setDepth(1);
-
+
this.lifeBar = this.scene.add.graphics();
this.redrawLifebar();
+ // add objects to container
+ this.add([
+ this.tank,
+ this.lifeBar,
+ this.barrel
+ ]);
+
// game objects
- this.bullets = this.scene.add.group({
- /*classType: Bullet,*/
- active: true,
- maxSize: 10,
- runChildUpdate: true
- });
+ // game objects
+ this.bullets = this.scene.add.group({
+ /*classType: Bullet,*/
+ active: true,
+ maxSize: 10,
+ runChildUpdate: true
+ });
+
+ // physics
+ this.scene.physics.world.enable(this);
+ }
+ private moveEnemy(){
// tweens
this.scene.tweens.add({
targets: this,
@@ -68,39 +127,22 @@ export class Enemy extends Phaser.GameObjects.Image {
repeatDelay: 0,
yoyo: true
});
-
- // physics
- this.scene.physics.world.enable(this);
}
- update(): void {
- if (this.active) {
- this.barrel.x = this.x;
- this.barrel.y = this.y;
- this.lifeBar.x = this.x;
- this.lifeBar.y = this.y;
- this.handleShooting();
- } else {
- this.destroy();
- this.barrel.destroy();
- this.lifeBar.destroy();
- }
- }
-
- private handleShooting(): void {
- if (this.scene.time.now > this.lastShoot) {
+ private shooting(): void {
+ if (this.scene.time.now > this.nextShoot) {
if (this.bullets.getLength() < 10) {
this.bullets.add(
new Bullet({
scene: this.scene,
rotation: this.barrel.rotation,
- x: this.barrel.x,
- y: this.barrel.y,
- texture: 'bulletRed'
+ x: this.x,
+ y: this.y,
+ texture: 'bulletRed',
+ damage: 0.05
})
);
-
- this.lastShoot = this.scene.time.now + 400;
+ this.nextShoot = this.scene.time.now + this.rateOfFire;
}
}
}
@@ -109,23 +151,58 @@ export class Enemy extends Phaser.GameObjects.Image {
this.lifeBar.clear();
this.lifeBar.fillStyle(0xe66a28, 1);
this.lifeBar.fillRect(
- -this.width / 2,
- this.height / 2,
- this.width * this.health,
+ -this.tank.width / 2,
+ this.tank.height / 2,
+ this.tank.width * this.health,
15
);
this.lifeBar.lineStyle(2, 0xffffff);
- this.lifeBar.strokeRect(-this.width / 2, this.height / 2, this.width, 15);
+ this.lifeBar.strokeRect(-this.tank.width / 2, this.tank.height / 2, this.tank.width, 15);
this.lifeBar.setDepth(1);
}
- public updateHealth(): void {
- if (this.health > 0) {
- this.health -= 0.05;
- this.redrawLifebar();
- } else {
- this.health = 0;
- this.active = false;
- }
+ private initTweenDamage(damage: number): void {
+ const xTextHealth = Phaser.Math.Between(this.x - 30, this.x + 30)
+ const yTextHealth = this.y
+ const textHealth = this.scene.add.text(xTextHealth, yTextHealth, `-${damage*100/5}`, {
+ fontFamily: 'Bangers',
+ fontSize: '50px',
+ color: '#B21E1E',
+ }).setOrigin(0.5, 0.5);
+
+ this.scene.tweens.add({
+ targets: textHealth,
+ y: yTextHealth -100,
+ ease: 'Power1',
+ duration: 300,
+ yoyo: false,
+ repeat: 0,
+ onComplete: ()=>{
+ textHealth.destroy();
+ }
+ })
+ }
+
+ private initParticlesDeath(){
+ const zone = new Phaser.Geom.Rectangle(-32, -32, 64, 64);
+ const particles = this.scene.add.particles('fire');
+ particles.createEmitter({
+ alpha: { start: 1, end: 0 },
+ scale: { start: 0.5, end: 2.5 },
+ speed: 20,
+ accelerationY: -300,
+ angle: { min: -85, max: -95 },
+ rotate: { min: -180, max: 180 },
+ lifespan: { min: 1000, max: 1100 },
+ frequency: 110,
+ maxParticles: 10,
+ x: this.x,
+ y: this.y,
+ emitZone: {
+ type: 'random' ,
+ source: zone,
+ quantity: 10
+ }
+ });
}
}
diff --git a/src/games/tank/src/objects/obstacles/obstacle.ts b/src/games/tank/src/objects/obstacles/obstacle.ts
index e8a429ea..30eef954 100644
--- a/src/games/tank/src/objects/obstacles/obstacle.ts
+++ b/src/games/tank/src/objects/obstacles/obstacle.ts
@@ -1,4 +1,3 @@
-import { IImageConstructor } from '../../interfaces/image.interface';
export class Obstacle extends Phaser.GameObjects.Image {
body: Phaser.Physics.Arcade.Body;
diff --git a/src/games/tank/src/objects/player.ts b/src/games/tank/src/objects/player.ts
index 67a26b14..4f1eade9 100644
--- a/src/games/tank/src/objects/player.ts
+++ b/src/games/tank/src/objects/player.ts
@@ -1,57 +1,119 @@
-import { Bullet } from './bullet';
-import { IImageConstructor } from '../interfaces/image.interface';
+import { CONST } from '../consts/const';
+import EventKeys from '../consts/EventKeys';
+import SceneKeys from '../consts/SceneKeys';
+import { Bullet } from './Bullet';
-export class Player extends Phaser.GameObjects.Image {
+export class Player extends Phaser.GameObjects.Container {
body: Phaser.Physics.Arcade.Body;
-
// variables
private health: number;
- private lastShoot: number;
+ private nextShoot: number;
private speed: number;
+ private texture: string;
+ private rateOfFire: number;
// children
private barrel: Phaser.GameObjects.Image;
private lifeBar: Phaser.GameObjects.Graphics;
-
+ private tank: Phaser.GameObjects.Image;
+
// game objects
private bullets: Phaser.GameObjects.Group;
+ private cursor: Phaser.GameObjects.Image;
// input
- private cursors: Phaser.Types.Input.Keyboard.CursorKeys;
- private rotateKeyLeft: Phaser.Input.Keyboard.Key;
- private rotateKeyRight: Phaser.Input.Keyboard.Key;
- private shootingKey: Phaser.Input.Keyboard.Key;
+ private moveKeyLeft: Phaser.Input.Keyboard.Key;
+ private moveKeyRight: Phaser.Input.Keyboard.Key;
+ private moveKeyUp: Phaser.Input.Keyboard.Key;
+ private moveKeyDown: Phaser.Input.Keyboard.Key;
+
+ constructor(aParams: ITankConstructor) {
+ super(aParams.scene, aParams.x, aParams.y);
+ this.texture = aParams.texture;
+ this.rateOfFire = aParams.rateOfFire;
+
+ this.initVariables();
+ this.initContainer();
+ // input mouse
+ this.initHandleInput();
+
+ this.scene.add.existing(this);
+ // set body of container
+ this.body.setOffset(-this.tank.width/2, -this.tank.height/2);
+ this.body.setSize(this.tank.width, this.tank.height);
+ }
+
+ update(): void {
+ if (this.active) {
+ if (!this.scene.input.mouse.locked){
+ this.cursor.setVisible(false);
+ }
+ this.rotateBarrelFollowMoune();
+ this.moveCurosrFollowPlayer();
+ this.handleInput();
+
+ } else {
+ this.destroy();
+ this.barrel.destroy();
+ this.lifeBar.destroy();
+ }
+ }
public getBullets(): Phaser.GameObjects.Group {
return this.bullets;
}
- constructor(aParams: IImageConstructor) {
- super(aParams.scene, aParams.x, aParams.y, aParams.texture, aParams.frame);
+ public updateHealth(damage: number): void {
+ this.initTweenDamage(damage);
- this.initImage();
- this.scene.add.existing(this);
- }
+ if (this.health > 0) {
+ this.health -= damage;
+ this.redrawLifebar();
+ } else {
+ this.scene.events.emit(EventKeys.PLAYER_DEATH);
+ this.health = 0;
+ this.active = false;
+ this.cursor.setVisible(false);
- private initImage() {
+ // pause current scene and show scene game over
+ this.scene.scene.pause();
+ this.scene.scene.launch(SceneKeys.GAME_OVER_SCENE);
+ this.scene.scene.bringToTop(SceneKeys.GAME_OVER_SCENE);
+ }
+ }
+
+ private initVariables(){
// variables
this.health = 1;
- this.lastShoot = 0;
- this.speed = 100;
+ this.nextShoot = 0;
+ this.speed = CONST.TANK_SPEED;
+ }
+ private initContainer() {
+
// image
- this.setOrigin(0.5, 0.5);
- this.setDepth(0);
- this.angle = 180;
-
- this.barrel = this.scene.add.image(this.x, this.y, 'barrelBlue');
- this.barrel.setOrigin(0.5, 1);
- this.barrel.setDepth(1);
+ this.tank = this.scene.physics.add.image(0, 0, this.texture);
+ this.tank.angle = 180;
+
+ this.barrel = this.scene.add.image(0, 0, 'barrelBlue')
+ .setOrigin(0.5, 1)
this.barrel.angle = 180;
+ this.cursor = this.scene.physics.add.image(this.x, this.y, 'curosr')
+ .setCollideWorldBounds(true)
+ .setDisplaySize(64,64)
+ .setDepth(2)
+
this.lifeBar = this.scene.add.graphics();
this.redrawLifebar();
+ // add objects to container
+ this.add([
+ this.tank,
+ this.lifeBar,
+ this.barrel
+ ]);
+
// game objects
this.bullets = this.scene.add.group({
/*classType: Bullet,*/
@@ -60,126 +122,183 @@ export class Player extends Phaser.GameObjects.Image {
runChildUpdate: true
});
+ // physics
+ this.scene.physics.world.enable(this);
+ }
+
+ private initHandleInput(){
// input
- this.cursors = this.scene.input.keyboard.createCursorKeys();
- this.rotateKeyLeft = this.scene.input.keyboard.addKey(
+ this.moveKeyLeft = this.scene.input.keyboard.addKey(
Phaser.Input.Keyboard.KeyCodes.A
);
- this.rotateKeyRight = this.scene.input.keyboard.addKey(
+ this.moveKeyRight = this.scene.input.keyboard.addKey(
Phaser.Input.Keyboard.KeyCodes.D
);
- this.shootingKey = this.scene.input.keyboard.addKey(
- Phaser.Input.Keyboard.KeyCodes.SPACE
+ this.moveKeyUp = this.scene.input.keyboard.addKey(
+ Phaser.Input.Keyboard.KeyCodes.W
+ );
+ this.moveKeyDown = this.scene.input.keyboard.addKey(
+ Phaser.Input.Keyboard.KeyCodes.S
);
- // physics
- this.scene.physics.world.enable(this);
+ this.scene.input.on(Phaser.Input.Events.POINTER_MOVE,
+ (pointer: Phaser.Input.Pointer)=>{
+ this.cursor.x += pointer.movementX;
+ this.cursor.y += pointer.movementY;
+ }, this);
+
+ this.scene.input.on(Phaser.Input.Events.POINTER_DOWN,
+ (pointer: Phaser.Input.Pointer)=>{
+ if (this&&!this.scene?.input.mouse.locked){
+ this.cursor.setVisible(true);
+ this.scene.game.input.mouse.requestPointerLock();
+ }
+ else this.shooting();
+ }, this);
+
+ // using unblock mouse
+ this.scene.input.keyboard.on('keydown-SPACE',
+ ()=>{
+ if (this.scene.input.mouse.locked){
+ this.scene.input.mouse.releasePointerLock();
+ this.cursor.setVisible(false);
+ }
+ });
+
+ // when player continue playing
+ this.scene.events.on('resume',
+ () => {
+ this.cursor.setVisible(true);
+ })
}
- update(): void {
- if (this.active) {
- this.barrel.x = this.x;
- this.barrel.y = this.y;
- this.lifeBar.x = this.x;
- this.lifeBar.y = this.y;
- this.handleInput();
- this.handleShooting();
- } else {
- this.destroy();
- this.barrel.destroy();
- this.lifeBar.destroy();
- }
+ private rotateBarrelFollowMoune(){
+ this.barrel.rotation = Phaser.Math.Angle.Between(
+ this.x,
+ this.y,
+ this.cursor.x,
+ this.cursor.y
+ )
+ + Math.PI/2;
+ }
+
+ private moveCurosrFollowPlayer() {
+ // move cursor
+ var bodyCurosr = this.cursor.body as Phaser.Physics.Arcade.Body;
+ bodyCurosr.setVelocity(this.body.velocity.x, this.body.velocity.y)
}
private handleInput() {
// move tank forward
// small corrections with (- MATH.PI / 2) to align tank correctly
- if (this.cursors.up.isDown) {
+ if (this.moveKeyUp.isDown) {
this.scene.physics.velocityFromRotation(
- this.rotation - Math.PI / 2,
+ this.tank.rotation - Math.PI / 2,
this.speed,
this.body.velocity
);
- } else if (this.cursors.down.isDown) {
+ }
+ else if (this.moveKeyDown.isDown) {
this.scene.physics.velocityFromRotation(
- this.rotation - Math.PI / 2,
+ this.tank.rotation - Math.PI / 2,
-this.speed,
this.body.velocity
);
- } else {
+ }
+ else {
this.body.setVelocity(0, 0);
}
// rotate tank
- if (this.cursors.left.isDown) {
- this.rotation -= 0.02;
- } else if (this.cursors.right.isDown) {
- this.rotation += 0.02;
- }
-
- // rotate barrel
- if (this.rotateKeyLeft.isDown) {
- this.barrel.rotation -= 0.05;
- } else if (this.rotateKeyRight.isDown) {
- this.barrel.rotation += 0.05;
+ if (this.moveKeyLeft.isDown) {
+ this.tank.rotation -= 0.02;
+ }
+ else if (this.moveKeyRight.isDown) {
+ this.tank.rotation += 0.02;
}
}
- private handleShooting(): void {
- if (this.shootingKey.isDown && this.scene.time.now > this.lastShoot) {
+ private shooting(): void {
+ if (this.scene.time.now > this.nextShoot) {
+ this.scene.events.emit(EventKeys.PLAYER_SHOOTING);
this.scene.cameras.main.shake(20, 0.005);
- this.scene.tweens.add({
- targets: this,
- props: { alpha: 0.8 },
- delay: 0,
- duration: 5,
- ease: 'Power1',
- easeParams: null,
- hold: 0,
- repeat: 0,
- repeatDelay: 0,
- yoyo: true,
- paused: false
- });
-
+ this.createTweenWhenShooting();
if (this.bullets.getLength() < 10) {
this.bullets.add(
new Bullet({
scene: this.scene,
rotation: this.barrel.rotation,
- x: this.barrel.x,
- y: this.barrel.y,
- texture: 'bulletBlue'
+ x: this.x,
+ y: this.y,
+ texture: 'bulletBlue',
+ damage: 0.1
})
);
-
- this.lastShoot = this.scene.time.now + 80;
+ this.nextShoot = this.scene.time.now + this.rateOfFire;
}
+
}
}
+ private createTweenWhenShooting() {
+ this.scene.tweens.add({
+ targets: this,
+ props: { alpha: 0.8 },
+ delay: 0,
+ duration: 5,
+ ease: 'Power1',
+ easeParams: null,
+ hold: 0,
+ repeat: 0,
+ repeatDelay: 0,
+ yoyo: true,
+ paused: false
+ });
+ }
+
private redrawLifebar(): void {
this.lifeBar.clear();
this.lifeBar.fillStyle(0xe66a28, 1);
this.lifeBar.fillRect(
- -this.width / 2,
- this.height / 2,
- this.width * this.health,
+ -this.tank.width / 2,
+ this.tank.height / 2,
+ this.tank.width * this.health,
15
);
this.lifeBar.lineStyle(2, 0xffffff);
- this.lifeBar.strokeRect(-this.width / 2, this.height / 2, this.width, 15);
+ this.lifeBar.strokeRect(
+ -this.tank.width / 2,
+ this.tank.height / 2,
+ this.tank.width, 15
+ );
this.lifeBar.setDepth(1);
}
- public updateHealth(): void {
- if (this.health > 0) {
- this.health -= 0.05;
- this.redrawLifebar();
- } else {
- this.health = 0;
- this.active = false;
- this.scene.scene.start('MenuScene');
- }
+ private initTweenDamage(damage: number): void {
+ const xTextHealth = Phaser.Math.Between(this.x - 30, this.x + 30)
+ const yTextHealth = this.y;
+ const textDamage = this.scene.add.text(
+ xTextHealth,
+ yTextHealth,
+ `-${damage*100/5}`,
+ {
+ fontFamily: 'Bangers',
+ fontSize: '50px',
+ color: '#4A90E2',
+ }
+ )
+ .setOrigin(0.5, 0.5);
+
+ this.scene.tweens.add({
+ targets: textDamage,
+ y: yTextHealth -100,
+ ease: 'Power1',
+ duration: 300,
+ yoyo: false,
+ repeat: 0,
+ onComplete: ()=>{
+ textDamage.destroy();
+ }
+ })
}
}
diff --git a/src/games/tank/src/scenes/boot-scene.ts b/src/games/tank/src/scenes/bootScene.ts
similarity index 91%
rename from src/games/tank/src/scenes/boot-scene.ts
rename to src/games/tank/src/scenes/bootScene.ts
index 7fa14cb7..f5971a8f 100644
--- a/src/games/tank/src/scenes/boot-scene.ts
+++ b/src/games/tank/src/scenes/bootScene.ts
@@ -1,10 +1,12 @@
+import SceneKeys from "../consts/SceneKeys";
+
export class BootScene extends Phaser.Scene {
private loadingBar: Phaser.GameObjects.Graphics;
private progressBar: Phaser.GameObjects.Graphics;
constructor() {
super({
- key: 'BootScene'
+ key: SceneKeys.BOOT_SCENE,
});
}
@@ -41,10 +43,11 @@ export class BootScene extends Phaser.Scene {
// load our package
this.load.pack('preload', './assets/pack.json', 'preload');
- }
+
+ }
update(): void {
- this.scene.start('MenuScene');
+ this.scene.start(SceneKeys.MENU_SCENE);
}
private createLoadingGraphics(): void {
diff --git a/src/games/tank/src/scenes/game-over-scene/GameOverContainer.ts b/src/games/tank/src/scenes/game-over-scene/GameOverContainer.ts
new file mode 100644
index 00000000..14605782
--- /dev/null
+++ b/src/games/tank/src/scenes/game-over-scene/GameOverContainer.ts
@@ -0,0 +1,230 @@
+import SceneKeys from "../../consts/SceneKeys";
+import { highScore } from "../../helpers/helpers";
+import { ReplayButton } from "../../objects/button/normal-button/ReplayButton";
+
+export class GameOverContainer extends Phaser.GameObjects.Container{
+ private zone!: Phaser.GameObjects.Zone;
+ private score!: Phaser.GameObjects.Text;
+ private gameOverText!: Phaser.GameObjects.Text;
+ private currentScoreText!: Phaser.GameObjects.Text;
+ private highScoreText!: Phaser.GameObjects.Text;
+ private highScore!: Phaser.GameObjects.Text;
+ private tween!: Phaser.Tweens.Tween;
+ private replayButton!: ReplayButton;
+
+ constructor(scene: Phaser.Scene, x: number, y: number){
+ super(scene, x, y);
+ this.createUI();
+ this.alignUI();
+ this.setStartPosition();
+ this.createTweens();
+ this.setDepth(3);
+ this.scene.add.existing(this);
+ }
+
+ update(...args: any[]): void {
+ this.score.setText(
+ Math.floor(this.tween.getValue()).toString()
+ )
+ }
+
+ public createTweenClose(){
+ const camerasHeight= this.scene.cameras.main.height;
+
+ this.scene.tweens.add({
+ targets: [this.currentScoreText, this.highScoreText, this.highScore, this.score],
+ y: - 200,
+ ease: 'Power1',
+ duration: 500,
+ });
+
+ this.scene.tweens.add({
+ targets: [this.replayButton],
+ y: camerasHeight + 200,
+ ease: 'Power1',
+ duration: 500,
+ onComplete: () => {
+ this.scene.scene.stop();
+ this.scene.scene.stop(SceneKeys.GAME_SCENE);
+ this.scene.scene.sendToBack();
+ this.scene.scene.stop(SceneKeys.MENU_SCENE);
+ this.scene.scene.start(SceneKeys.MENU_SCENE);
+ }
+ });
+ }
+
+ private createUI() {
+ const camerasWidth= this.scene.cameras.main.width;
+ const camerasHeight= this.scene.cameras.main.height;
+
+ const background = this.scene.add.rectangle(
+ 0,
+ 0,
+ camerasWidth,
+ camerasHeight,
+ 0x000000
+ )
+ .setOrigin(0,0)
+ .setAlpha(0.8);
+
+ this.gameOverText = this.scene.add.text(
+ 0, 0,
+ 'Game Over',
+ {
+ fontFamily: 'Quicksand',
+ fontSize: '96px'
+ }
+ );
+ this.currentScoreText = this.scene.add.text(
+ 0, 0,
+ `Current score`,
+ {
+ fontFamily: 'Quicksand',
+ fontSize: '48px'
+ }
+ );
+
+ this.highScoreText = this.scene.add.text(
+ 0, 0,
+ `High score`,
+ {
+ fontFamily: 'Quicksand',
+ fontSize: '48px'
+ }
+ )
+ .setOrigin(0.5,0.5)
+ .setVisible(false)
+
+ this.highScore = this.scene.add.text(
+ 0, 0,
+ `${highScore(this.scene)}`,
+ {
+ fontFamily: 'Quicksand',
+ fontSize: '48px'
+ }
+ )
+ .setOrigin(0.5,0.5)
+ .setVisible(false)
+
+ this.score = this.scene.add.text(
+ 0, 0,
+ `${this.scene.registry.get('score')}`,
+ {
+ fontFamily: 'Quicksand',
+ fontSize: '48px'
+ }
+ )
+ .setOrigin(0.5,0.5)
+ .setVisible(false)
+
+ this.replayButton = new ReplayButton({
+ scene: this.scene,
+ x: 0,
+ y: 0,
+ texture: 'btn-replay',
+ soundPress: 'click',
+ }).setOrigin(0,0)
+
+ this.zone = this.scene.add.zone(
+ 140,
+ 90,
+ camerasWidth - 140*2,
+ camerasHeight - 90*2
+ )
+ .setOrigin(0,0);
+
+ this.add([
+ this.zone,
+ this.replayButton,
+ this.highScoreText,
+ this.highScore,
+ this.currentScoreText,
+ this.score,
+ this.gameOverText
+ ])
+ }
+
+ private alignUI(){
+ Phaser.Display.Align.In.Center(
+ this.gameOverText,
+ this.zone,
+ );
+ Phaser.Display.Align.In.Center(
+ this.score,
+ this.zone,
+ );
+ Phaser.Display.Align.In.BottomCenter(
+ this.replayButton,
+ this.zone,
+ );
+
+ Phaser.Display.Align.In.Center(
+ this.currentScoreText,
+ this.zone,
+ );
+
+ Phaser.Display.Align.In.Center(
+ this.highScore,
+ this.zone,
+ );
+ Phaser.Display.Align.In.Center(
+ this.highScoreText,
+ this.zone,
+ );
+ }
+
+ private setStartPosition(){
+ const camerasHeight = this.scene.cameras.main.height;
+ this.currentScoreText.setY(camerasHeight + 100);
+ this.replayButton.setY(camerasHeight + 100);
+ this.score.setY(300);
+ this.highScoreText.setY(400);
+ this.highScore.setY(500);
+ }
+
+ private createTweens() {
+ const durationTween = (this.scene.registry.get('score')/100)* 5000;
+ const score = this.scene.registry.get('score')
+ this.tween = this.scene.tweens.addCounter({
+ from: 0,
+ to: score,
+ duration: durationTween,
+ paused: true
+ });
+
+ this.scene.tweens.add({
+ targets: this.gameOverText,
+ y: -100,
+ ease: 'Power1',
+ duration: 3000,
+ delay: 1000,
+ onComplete() {
+ this.destroy;
+ },
+ });
+
+ this.scene.tweens.add({
+ targets: this.currentScoreText,
+ y: 200,
+ ease: 'Power1',
+ duration: 5000,
+ delay: 1000,
+ onComplete: ()=>{
+ this.score.visible = true;
+ this.tween.resume();
+ },
+ });
+
+ this.tween.on("complete", () =>{
+ const camerasHeight = this.scene.cameras.main.height;
+ this.highScoreText.setVisible(true);
+ this.highScore.setVisible(true);
+ this.scene.tweens.add({
+ targets: this.replayButton,
+ y: camerasHeight - 300,
+ ease: 'Power1',
+ duration: 1000,
+ });
+ })
+ }
+}
\ No newline at end of file
diff --git a/src/games/tank/src/scenes/game-over-scene/GameOverScene.ts b/src/games/tank/src/scenes/game-over-scene/GameOverScene.ts
new file mode 100644
index 00000000..628c70fe
--- /dev/null
+++ b/src/games/tank/src/scenes/game-over-scene/GameOverScene.ts
@@ -0,0 +1,45 @@
+/* eslint no-undef: 0 */
+/* eslint no-unused-expressions: 0 */
+import 'phaser';
+import EventKeys from '../../consts/EventKeys';
+import SceneKeys from '../../consts/SceneKeys';
+import { GameOverContainer } from './GameOverContainer';
+
+export default class GameOverScene extends Phaser.Scene {
+ private gameOverContainer: GameOverContainer;
+
+ // audio
+ private audioGameOver: Phaser.Sound.BaseSound;
+
+ constructor() {
+ super({
+ key: SceneKeys.GAME_OVER_SCENE,
+ });
+ }
+
+ create() {
+ this.gameOverContainer = new GameOverContainer(this, 0,0);
+ this.add.existing(this.gameOverContainer)
+ this.initAudio();
+ this.createHandleEvents();
+ }
+
+ update(time: number, delta: number): void {
+ this.gameOverContainer.update(time, delta);
+ }
+
+ private initAudio(){
+ this.audioGameOver = this.sound.add('gameover');
+ if(!this.registry.get('muteMusic'))
+ this.audioGameOver.play();
+ }
+
+ private createHandleEvents(){
+ this.events.on(EventKeys.RESTART_GAME,
+ ()=>{
+ this.audioGameOver.pause();
+ this.gameOverContainer.createTweenClose();
+ }, this);
+ }
+
+}
\ No newline at end of file
diff --git a/src/games/tank/src/scenes/game-scene.ts b/src/games/tank/src/scenes/game-scene.ts
deleted file mode 100644
index 5d72ca77..00000000
--- a/src/games/tank/src/scenes/game-scene.ts
+++ /dev/null
@@ -1,166 +0,0 @@
-import { Player } from '../objects/player';
-import { Enemy } from '../objects/enemy';
-import { Obstacle } from '../objects/obstacles/obstacle';
-import { Bullet } from '../objects/bullet';
-
-export class GameScene extends Phaser.Scene {
- private map: Phaser.Tilemaps.Tilemap;
- private tileset: Phaser.Tilemaps.Tileset;
- private layer: Phaser.Tilemaps.TilemapLayer;
-
- private player: Player;
- private enemies: Phaser.GameObjects.Group;
- private obstacles: Phaser.GameObjects.Group;
-
- private target: Phaser.Math.Vector2;
-
- constructor() {
- super({
- key: 'GameScene'
- });
- }
-
- init(): void {}
-
- create(): void {
- // create tilemap from tiled JSON
- this.map = this.make.tilemap({ key: 'levelMap' });
-
- this.tileset = this.map.addTilesetImage('tiles');
- this.layer = this.map.createLayer('tileLayer', this.tileset, 0, 0);
- this.layer.setCollisionByProperty({ collide: true });
-
- this.obstacles = this.add.group({
- /*classType: Obstacle,*/
- runChildUpdate: true
- });
-
- this.enemies = this.add.group({
- /*classType: Enemy*/
- });
- this.convertObjects();
-
- // collider layer and obstacles
- this.physics.add.collider(this.player, this.layer);
- this.physics.add.collider(this.player, this.obstacles);
-
- // collider for bullets
- this.physics.add.collider(
- this.player.getBullets(),
- this.layer,
- this.bulletHitLayer,
- null,
- this
- );
-
- this.physics.add.collider(
- this.player.getBullets(),
- this.obstacles,
- this.bulletHitObstacles,
- null,
- this
- );
-
- this.enemies.children.each((enemy: Enemy) => {
- this.physics.add.overlap(
- this.player.getBullets(),
- enemy,
- this.playerBulletHitEnemy,
- null,
- this
- );
- this.physics.add.overlap(
- enemy.getBullets(),
- this.player,
- this.enemyBulletHitPlayer,
- null
- );
-
- this.physics.add.collider(
- enemy.getBullets(),
- this.obstacles,
- this.bulletHitObstacles,
- null
- );
- this.physics.add.collider(
- enemy.getBullets(),
- this.layer,
- this.bulletHitLayer,
- null
- );
- }, this);
-
- this.cameras.main.startFollow(this.player);
- }
-
- update(): void {
- this.player.update();
-
- this.enemies.children.each((enemy: Enemy) => {
- enemy.update();
- if (this.player.active && enemy.active) {
- var angle = Phaser.Math.Angle.Between(
- enemy.body.x,
- enemy.body.y,
- this.player.body.x,
- this.player.body.y
- );
-
- enemy.getBarrel().angle =
- (angle + Math.PI / 2) * Phaser.Math.RAD_TO_DEG;
- }
- }, this);
- }
-
- private convertObjects(): void {
- // find the object layer in the tilemap named 'objects'
- const objects = this.map.getObjectLayer('objects').objects as any[];
-
- objects.forEach((object) => {
- if (object.type === 'player') {
- this.player = new Player({
- scene: this,
- x: object.x,
- y: object.y,
- texture: 'tankBlue'
- });
- } else if (object.type === 'enemy') {
- let enemy = new Enemy({
- scene: this,
- x: object.x,
- y: object.y,
- texture: 'tankRed'
- });
-
- this.enemies.add(enemy);
- } else {
- let obstacle = new Obstacle({
- scene: this,
- x: object.x,
- y: object.y - 40,
- texture: object.type
- });
-
- this.obstacles.add(obstacle);
- }
- });
- }
-
- private bulletHitLayer(bullet: Bullet): void {
- bullet.destroy();
- }
-
- private bulletHitObstacles(bullet: Bullet, obstacle: Obstacle): void {
- bullet.destroy();
- }
-
- private enemyBulletHitPlayer(bullet: Bullet, player: Player): void {
- bullet.destroy();
- player.updateHealth();
- }
-
- private playerBulletHitEnemy(bullet: Bullet, enemy: Enemy): void {
- bullet.destroy();
- enemy.updateHealth();
- }
-}
diff --git a/src/games/tank/src/scenes/gameScene.ts b/src/games/tank/src/scenes/gameScene.ts
new file mode 100644
index 00000000..fc02c714
--- /dev/null
+++ b/src/games/tank/src/scenes/gameScene.ts
@@ -0,0 +1,350 @@
+import { Player } from '../objects/Player';
+import { Enemy } from '../objects/Enemy';
+import { Obstacle } from '../objects/obstacles/Obstacle';
+import { Bullet } from '../objects/Bullet';
+import { MenuButton } from '../objects/button/normal-button/MenuButton';
+import SceneKeys from '../consts/SceneKeys';
+import EventKeys from '../consts/EventKeys';
+
+export class GameScene extends Phaser.Scene {
+ private map: Phaser.Tilemaps.Tilemap;
+ private tileset: Phaser.Tilemaps.Tileset;
+ private layer: Phaser.Tilemaps.TilemapLayer;
+
+ private player: Player;
+ private enemies: Phaser.GameObjects.Group;
+ private obstacles: Phaser.GameObjects.Group;
+ private textScore!: Phaser.GameObjects.Text;
+
+ private buttonMenu!: MenuButton;
+ private zone!: Phaser.GameObjects.Zone;
+
+ // audio
+ private audioBattle: Phaser.Sound.BaseSound;
+ private audioPlayerShooter: Phaser.Sound.BaseSound;
+ private audioPlayerDeath: Phaser.Sound.BaseSound;
+ private audioEnemyDeath: Phaser.Sound.BaseSound;
+
+ constructor() {
+ super({
+ key: SceneKeys.GAME_SCENE
+ });
+
+ }
+
+ init(): void {
+ }
+
+ create(): void {
+
+ this.initAudio();
+ this.createUI();
+ this.createMap();
+ this.initEnemies();
+ this.initObstacles();
+ this.createObjects();
+ this.handlePhysics();
+ this.initListenEvents();
+ this.setUpCameraFollowPlayer();
+ }
+
+ update(): void {
+ this.player.update();
+ this.updateEnemys();
+ }
+
+ private initAudio() {
+ this.audioBattle = this.sound.add('battle');
+ this.audioBattle.play();
+ this.audioPlayerShooter = this.sound.add('player-shooter');
+ this.audioPlayerDeath = this.sound.add('player-death');
+ this.audioEnemyDeath = this.sound.add('enemy-death');
+ }
+
+ private createUI(){
+ const camerasWidth= this.cameras.main.width;
+ const camerasHeight= this.cameras.main.height;
+
+ this.buttonMenu = new MenuButton({
+ scene: this,
+ x: 0,
+ y: 0,
+ texture: "btn-menu",
+ soundPress: 'click',
+ }).setScrollFactor(0);
+
+ this.textScore = this.add.text(
+ 0,
+ 0,
+ `Score: ${this.registry.get('score')}`,
+ {
+ fontFamily: 'Quicksand',
+ fontSize: '48px',
+ color: '#fff'
+ }
+ )
+ .setScrollFactor(0)
+ .setOrigin(0, 0);
+
+ this.zone = this.add.zone(
+ camerasWidth/2,
+ camerasHeight / 2,
+ camerasWidth - 40,
+ camerasHeight - 20
+ )
+ Phaser.Display.Align.In.TopLeft(
+ this.buttonMenu,
+ this.zone
+ );
+
+ Phaser.Display.Align.In.TopRight(
+ this.textScore,
+ this.zone
+ );
+ this.textScore.setX(this.textScore.x - 25)
+ }
+
+ private createMap(){
+ // create tilemap from tiled JSON
+ this.map = this.make.tilemap({ key: 'levelMap' });
+
+ this.tileset = this.map.addTilesetImage('tiles');
+ this.layer = this.map.createLayer('tileLayer', this.tileset, 0, 0);
+ this.layer.setCollisionByProperty({ collide: true });
+ }
+
+ private initEnemies(){
+ this.enemies = this.add.group({
+ /*classType: Enemy*/
+ });
+ }
+
+ private initObstacles(){
+ this.obstacles = this.add.group({
+ /*classType: Obstacle,*/
+ runChildUpdate: true
+ });
+ }
+
+ private setUpCameraFollowPlayer(){
+ this.cameras.main.startFollow(this.player);
+ }
+
+ private handlePhysics(){
+
+ this.physics.world.setBounds(
+ 0,
+ 0,
+ this.layer.width,
+ this.layer.height
+ );
+
+ // collider layer and obstacles
+ this.physics.add.collider(this.player, this.layer);
+ this.physics.add.collider(this.player, this.obstacles);
+
+ // collider for bullets
+ this.physics.add.collider(
+ this.player.getBullets(),
+ this.layer,
+ (obj1, obj2) => this.bulletHitLayer(obj1 as Bullet),
+ null,
+ this
+ );
+
+ this.physics.add.collider(
+ this.player.getBullets(),
+ this.obstacles,
+ (obj1, obj2) =>this.bulletHitObstacles(obj1 as Bullet, obj2 as Obstacle),
+ null,
+ this
+ );
+
+ this.physics.add.collider(
+ this.player.getBullets(),
+ this.enemies,
+ (obj1, obj2) =>this.playerBulletHitEnemy(obj1 as Bullet, obj2 as Enemy),
+ null,
+ this
+ );
+
+ this.enemies.children.each((enemy: Enemy) => {
+ this.physics.add.overlap(
+ enemy.getBullets(),
+ this.player,
+ (obj1, obj2)=>this.enemyBulletHitPlayer(obj1 as Bullet, obj2 as Player),
+ null
+ );
+
+ this.physics.add.collider(
+ enemy.getBullets(),
+ this.obstacles,
+ (obj1, obj2) =>this.bulletHitObstacles(obj1 as Bullet, obj2 as Obstacle),
+ null
+ );
+ this.physics.add.collider(
+ enemy.getBullets(),
+ this.layer,
+ (obj1, obj2)=>this.bulletHitLayer(obj1 as Bullet),
+ null
+ );
+ }, this);
+ }
+
+ private initListenEvents() {
+ this.events.on('pause', ()=>{
+ if(this.input.mouse.locked)
+ this.input.mouse.releasePointerLock();
+ // pause audio
+ this.audioBattle.pause();
+ this.scene.sendToBack();
+ })
+
+ this.events.on('resume', () => {
+ if(!this.registry.get('muteMusic')&&!this.audioBattle.isPlaying){
+ if(this.audioBattle.isPaused)
+ this.audioBattle.resume();
+ else
+ this.audioBattle.play();
+ }
+ else if(this.audioBattle.isPlaying && this.registry.get('muteMusic')){
+ this.audioBattle.pause();
+ }
+ })
+
+ this.events.on(EventKeys.PLAYER_SHOOTING,()=>{
+ if(!this.registry.get('muteSound'))
+ this.audioPlayerShooter.play();
+ })
+
+ this.events.on(EventKeys.PLAYER_DEATH,()=>{
+ if(!this.registry.get('muteSound'))
+ this.audioPlayerDeath.play();
+ })
+
+ this.events.on(EventKeys.ENEMY_DEATH,()=>{
+ if(!this.registry.get('muteSound'))
+ this.audioEnemyDeath.play();
+ })
+
+ this.events.on("start",()=>{
+ this.removeListener();
+ })
+
+ }
+
+ private removeListener(){
+ this.events.removeListener(EventKeys.PLAYER_SHOOTING);
+ this.events.removeListener(EventKeys.PLAYER_DEATH);
+ this.events.removeListener('enemy_death');
+ }
+
+
+ private createObjects(): void {
+ // find the object layer in the tilemap named 'objects'
+ const objects = this.map.getObjectLayer('objects').objects as any[];
+
+ objects.forEach((object) => {
+ switch (object.type) {
+ case "player": {
+ this.player = this.createPlayer(object.x, object.y);
+ break;
+ }
+
+ case "enemy":{
+ let enemy = this.createEnemy(object.x, object.y);
+ this.enemies.add(enemy);
+ break;
+ }
+
+ default:{
+ let obstacle = this.createObstacle(object.x, object.y, object.type);
+ this.obstacles.add(obstacle);
+ break;
+ }
+ }
+ });
+ }
+
+ private createPlayer(x: number, y: number): Player {
+ return new Player({
+ scene: this,
+ x: x,
+ y: y,
+ texture: 'tankBlue',
+ rateOfFire: 80,
+ });
+ }
+
+ private createEnemy(x: number, y: number): Enemy {
+ return new Enemy({
+ scene: this,
+ x: x,
+ y: y,
+ texture: 'tankRed',
+ rateOfFire: 1000,
+ });
+ }
+
+ private createObstacle(x: number, y: number, texture: string): Obstacle {
+ return new Obstacle({
+ scene: this,
+ x: x,
+ y: y - 40,
+ texture: texture
+ });
+ }
+
+ private bulletHitLayer(bullet: Bullet): void {
+ this.createEmitter(bullet.x, bullet.y);
+ bullet.destroyBullet();
+ }
+
+ private bulletHitObstacles(bullet: Bullet, obstacle: Obstacle): void {
+ this.createEmitter(bullet.x, bullet.y);
+ bullet.destroyBullet();
+ }
+
+ private enemyBulletHitPlayer(bullet: Bullet, player: Player): void {
+ this.createEmitter(bullet.x, bullet.y);
+ bullet.destroyBullet();
+ player.updateHealth(bullet.getDamage());
+ }
+
+ private playerBulletHitEnemy(bullet: Bullet, enemy: Enemy): void {
+ this.createEmitter(bullet.x, bullet.y);
+ bullet.destroyBullet();
+ this.updateScore();
+ enemy.updateHealth(bullet.getDamage());
+ }
+
+ private createEmitter(x: number, y: number){
+ var particlesBullet = this.add.particles('flares')
+ .createEmitter({
+ frame: 'red',
+ x: x,
+ y: y,
+ lifespan: 500,
+ speed: { min: 400, max: 600 },
+ angle: {min: 0, max: 360},
+ scale: { start: 0.1, end: 0 },
+ quantity: 2,
+ blendMode: 'ADD',
+ });
+
+ this.time.delayedCall(150, ()=>{
+ particlesBullet.remove();
+ }, [], this)
+ }
+
+ private updateScore(){
+ this.registry.set('score' ,this.registry.get('score')+1);
+ this.textScore.setText(`Score: ${this.registry.get('score')}`);
+ }
+
+ private updateEnemys(){
+ this.enemies.children.each((enemy: Enemy) => {
+ enemy.update(this.player);
+ }, this);
+ }
+}
diff --git a/src/games/tank/src/scenes/menu-scene.ts b/src/games/tank/src/scenes/menu-scene.ts
deleted file mode 100644
index ab7c5cf5..00000000
--- a/src/games/tank/src/scenes/menu-scene.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-export class MenuScene extends Phaser.Scene {
- private startKey: Phaser.Input.Keyboard.Key;
- private bitmapTexts: Phaser.GameObjects.BitmapText[] = [];
-
- constructor() {
- super({
- key: 'MenuScene'
- });
- }
-
- init(): void {
- this.startKey = this.input.keyboard.addKey(
- Phaser.Input.Keyboard.KeyCodes.S
- );
- this.startKey.isDown = false;
- }
-
- create(): void {
- this.bitmapTexts.push(
- this.add.bitmapText(
- this.sys.canvas.width / 2 - 120,
- this.sys.canvas.height / 2,
- 'font',
- 'PRESS S TO PLAY',
- 30
- )
- );
-
- this.bitmapTexts.push(
- this.add.bitmapText(
- this.sys.canvas.width / 2 - 120,
- this.sys.canvas.height / 2 - 100,
- 'font',
- 'TANK',
- 100
- )
- );
- }
-
- update(): void {
- if (this.startKey.isDown) {
- this.scene.start('GameScene');
- }
- }
-}
diff --git a/src/games/tank/src/scenes/menu-scene/MenuContainer.ts b/src/games/tank/src/scenes/menu-scene/MenuContainer.ts
new file mode 100644
index 00000000..d7f5a9a1
--- /dev/null
+++ b/src/games/tank/src/scenes/menu-scene/MenuContainer.ts
@@ -0,0 +1,130 @@
+import SceneKeys from "../../consts/SceneKeys";
+import { StartButton } from "../../objects/button/normal-button/StartButton";
+import { ButtonMusic } from "../../objects/button/toggle-button/ButtonMusic";
+import { ButtonSound } from "../../objects/button/toggle-button/ButtonSound";
+
+export class MenuContainer extends Phaser.GameObjects.Container {
+ private startButton: StartButton;
+ private soundButton: ButtonSound;
+ private musicButton: ButtonMusic;
+ private logo: Phaser.GameObjects.Image;
+ private zone!: Phaser.GameObjects.Zone;
+
+ constructor(scene: Phaser.Scene, x: number, y: number){
+ super(scene, x, y);
+ this.createUI();
+ this.alignUI();
+ this.createTweens();
+ }
+
+ public createTweenClose(){
+ this.scene.tweens.add({
+ targets: [this.soundButton, this.musicButton],
+ y: this.scene.cameras.main.height + 200,
+ ease: 'Power1',
+ duration: 500,
+ });
+ this.scene.tweens.add({
+ targets: [this.startButton],
+ y: -200,
+ ease: 'Power1',
+ duration: 500,
+ onComplete: () => {
+ this.scene.game.input.mouse.requestPointerLock();
+ this.scene.scene.stop(SceneKeys.MENU_SCENE)
+ this.scene.scene.stop(SceneKeys.GAME_SCENE);
+ this.scene.scene.start(SceneKeys.GAME_SCENE);
+ }
+ });
+ }
+
+ public setVisibleBtnStart(){
+ this.startButton.setVisible(true);
+ }
+
+ private createUI(){
+ const camerasWidth= this.scene.cameras.main.width;
+ const camerasHeight= this.scene.cameras.main.height;
+
+ this.scene.add.image(0,0,'background')
+ .setOrigin(0,0)
+ .setScale(0.75,0.75);
+
+ this.logo = this.scene.add.image(0,0,'logo');
+ this.zone = this.scene.add.zone(
+ 140,
+ 90,
+ camerasWidth - 140*2,
+ camerasHeight - 90*2
+ )
+ .setOrigin(0,0);
+ this.add(this.zone);
+ // Center the picture in the game
+
+ this.startButton = new StartButton({
+ scene: this.scene,
+ x: 0,
+ y: 0,
+ texture: 'btn-start',
+ soundPress: 'select',
+ }).setVisible(false);
+
+
+ this.soundButton = new ButtonSound({
+ scene: this.scene,
+ x: 0,
+ y: 0,
+ texture: 'btn-sound',
+ frame: 1,
+ numberOfFrames: 2,
+ soundPress: 'click',
+ })
+
+ this.musicButton = new ButtonMusic({
+ scene: this.scene,
+ x: 0,
+ y: 0,
+ texture: 'btn-music',
+ frame: 1,
+ numberOfFrames: 2,
+ soundPress: 'click',
+ })
+
+ this.add([
+ this.soundButton,
+ this.musicButton,
+ this.startButton
+ ]);
+ }
+
+ private alignUI(){
+ Phaser.Display.Align.In.TopCenter(
+ this.logo,
+ this.zone
+ );
+ Phaser.Display.Align.In.Center(
+ this.startButton,
+ this.zone
+ );
+ Phaser.Display.Align.In.BottomLeft(
+ this.soundButton,
+ this.zone
+ );
+ Phaser.Display.Align.In.BottomRight(
+ this.musicButton,
+ this.zone
+ );
+ }
+
+ private createTweens(): void {
+ this.scene.tweens.add({
+ targets: this.startButton,
+ scaleX: 1.2,
+ scaleY: 1.2,
+ ease: 'Sine.easeInOut',
+ duration: 500,
+ yoyo: true,
+ repeat: -1,
+ })
+ }
+}
\ No newline at end of file
diff --git a/src/games/tank/src/scenes/menu-scene/MenuScene.ts b/src/games/tank/src/scenes/menu-scene/MenuScene.ts
new file mode 100644
index 00000000..7d4e7181
--- /dev/null
+++ b/src/games/tank/src/scenes/menu-scene/MenuScene.ts
@@ -0,0 +1,76 @@
+import EventKeys from "../../consts/EventKeys";
+import SceneKeys from "../../consts/SceneKeys";
+import { MenuContainer } from "./MenuContainer";
+
+export class MenuScene extends Phaser.Scene {
+ private menuContainer: MenuContainer;
+ private menuTrackAudio: Phaser.Sound.BaseSound;
+ private menuStartAudio: Phaser.Sound.BaseSound;
+ constructor() {
+ super({
+ key: SceneKeys.MENU_SCENE
+ });
+ }
+
+ init(): void {
+ this.initGlobalDataManager();
+ this.createHandleEvents();
+ }
+
+ create(): void {
+ this.menuContainer = new MenuContainer(this, 0,0);
+ this.add.existing(this.menuContainer);
+ this.initAudio();
+ }
+
+ update(): void {
+ }
+
+ private initAudio() {
+ this.menuTrackAudio = this.sound.add('menu_track');
+ this.menuStartAudio = this.sound.add('menu_start');
+ this.menuStartAudio.play();
+ this.menuStartAudio.on('complete', ()=>{
+ this.menuStartAudio.pause();
+ this.menuTrackAudio.play();
+ this.menuContainer.setVisibleBtnStart();
+ });
+ }
+
+ private createHandleEvents(): void {
+ this.events.on(EventKeys.START_GAME, ()=>{
+ this.menuTrackAudio.stop();
+ this.menuContainer.createTweenClose();
+ }, this);
+
+ this.events.on('start', ()=>{
+ this.removeListener();
+ this.input.mouse.releasePointerLock();
+ }, this);
+
+ this.events.on(EventKeys.MUTE_MUSIC, ()=>{
+ if(this.menuTrackAudio.isPlaying){
+ this.menuTrackAudio.pause();
+ }
+ })
+
+ this.events.on(EventKeys.UNMUTE_MUSIC, ()=>{
+ if(this.menuTrackAudio.isPaused)
+ this.menuTrackAudio.resume();
+ else
+ this.menuTrackAudio.play();
+ })
+ }
+
+ private removeListener() {
+ this.events.removeListener(EventKeys.START_GAME);
+ this.events.removeListener(EventKeys.MUTE_MUSIC);
+ this.events.removeListener(EventKeys.UNMUTE_MUSIC);
+ }
+
+ private initGlobalDataManager(): void {
+ this.registry.set('score', 0);
+ this.registry.set('muteSound', false);
+ this.registry.set('muteMusic', false);
+ }
+}
diff --git a/src/games/tank/src/scenes/pause-scene/PauseContainer.ts b/src/games/tank/src/scenes/pause-scene/PauseContainer.ts
new file mode 100644
index 00000000..31e3c7c9
--- /dev/null
+++ b/src/games/tank/src/scenes/pause-scene/PauseContainer.ts
@@ -0,0 +1,169 @@
+import SceneKeys from "../../consts/SceneKeys";
+import { PlayButton } from "../../objects/button/normal-button/PlayButton";
+import { ReplayButton } from "../../objects/button/normal-button/ReplayButton";
+import { ButtonMusic } from "../../objects/button/toggle-button/ButtonMusic";
+import { ButtonSound } from "../../objects/button/toggle-button/ButtonSound";
+
+export class PauseContainer extends Phaser.GameObjects.Container{
+ private musicButton: ButtonMusic;
+ private replayButton: ReplayButton;
+ private playButton: PlayButton;
+ private soundButton: ButtonSound;
+ private zone!: Phaser.GameObjects.Zone;
+
+ constructor(scene: Phaser.Scene, x: number, y: number){
+ super(scene, x, y);
+ this.scene = scene;
+ this.createUI();
+ this.alignUI();
+ this.createTweenOpen();
+ }
+
+ private createUI(){
+ const background = this.scene.add.rectangle(
+ 0,
+ 0,
+ this.scene.cameras.main.width,
+ this.scene.cameras.main.height,
+ 0x000000
+ )
+ .setOrigin(0,0)
+ .setAlpha(0.5);
+
+ this.zone = this.scene.add.zone(
+ 0,
+ 140,
+ 350,
+ 450
+ )
+ .setOrigin(0,0);
+ this.add(this.zone);
+
+ this.musicButton = new ButtonMusic({
+ scene: this.scene,
+ x: 0,
+ y: 0,
+ texture: 'btn-music',
+ frame: 1,
+ numberOfFrames: 2,
+ soundPress: 'click',
+ })
+
+ this.soundButton = new ButtonSound({
+ scene: this.scene,
+ x: 0,
+ y: 0,
+ texture: 'btn-sound',
+ frame: 1,
+ numberOfFrames: 2,
+ soundPress: 'click',
+ })
+
+ this.playButton = new PlayButton({
+ scene: this.scene,
+ x: 0,
+ y: 0,
+ texture: 'btn-play',
+ soundPress: 'click',
+ })
+
+ this.replayButton = new ReplayButton({
+ scene: this.scene,
+ x: 0,
+ y: 0,
+ texture: 'btn-replay',
+ soundPress: 'click',
+ })
+
+ this.add([
+ this.musicButton,
+ this.playButton,
+ this.replayButton,
+ this.soundButton
+ ]);
+ }
+
+ private alignUI(){
+ Phaser.Display.Align.In.TopRight(
+ this.musicButton,
+ this.zone
+ )
+ Phaser.Display.Align.In.TopLeft(
+ this.soundButton,
+ this.zone
+ )
+ Phaser.Display.Align.In.Center(
+ this.playButton,
+ this.zone
+ )
+
+ Phaser.Display.Align.In.BottomCenter(
+ this.replayButton,
+ this.zone
+ )
+ }
+
+ private createTweenOpen(): void {
+ // tweens open
+ this.scene.tweens.timeline({
+ ease: 'Back.easeOut',
+ duration: 300,
+ tweens:[
+ {
+ targets: this.musicButton,
+ x: 800,
+ },
+ {
+ targets: this.soundButton,
+ x: 600,
+ },
+ {
+ targets: this.playButton,
+ x: 750,
+ },
+ {
+ targets: this.replayButton,
+ x: 750,
+ }
+ ]
+ })
+ }
+
+ public createTweenClose(modeClose: string){
+ this.scene.tweens.timeline({
+ // targets: [this.btnReplay, this.btnPlay, this.btnSound, this.btnMusic],
+ ease: 'Power1',
+ duration: 200,
+ tweens:[
+ {
+ targets: this.soundButton,
+ x: -100,
+ },
+ {
+ targets: this.musicButton,
+ x: -100,
+ },
+ {
+ targets: this.playButton,
+ x: -100,
+ },
+ {
+ targets: this.replayButton,
+ x: -100,
+ }
+ ],
+ onComplete: () => {
+ if(modeClose == 'continue'){
+ this.scene.game.input.mouse.requestPointerLock();
+ this.scene.scene.resume(SceneKeys.GAME_SCENE);
+ this.scene.scene.sendToBack();
+ }else{
+ this.scene.scene.stop(SceneKeys.GAME_SCENE);
+ this.scene.scene.stop(SceneKeys.MENU_SCENE);
+ this.scene.scene.start(SceneKeys.MENU_SCENE);
+ this.scene.scene.stop();
+ }
+ },
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/games/tank/src/scenes/pause-scene/PauseScene.ts b/src/games/tank/src/scenes/pause-scene/PauseScene.ts
new file mode 100644
index 00000000..246aedc0
--- /dev/null
+++ b/src/games/tank/src/scenes/pause-scene/PauseScene.ts
@@ -0,0 +1,50 @@
+import EventKeys from "../../consts/EventKeys";
+import SceneKeys from "../../consts/SceneKeys";
+import { PauseContainer } from "./PauseContainer";
+
+export class PauseScene extends Phaser.Scene {
+ private pauseContainer: PauseContainer;
+
+ constructor() {
+ super({
+ key: SceneKeys.PAUSE_SCENE,
+ });
+ }
+
+ create(): void {
+ this.createUI();
+ this.createHandleEvents();
+ }
+
+ update(): void {
+ }
+
+ private createUI(){
+ this.pauseContainer = new PauseContainer(this, 0,0)
+ this.pauseContainer.setX(-400);
+ this.add.existing(this.pauseContainer);
+ }
+
+ private createHandleEvents(){
+ this.events.on(EventKeys.RESTART_GAME,
+ ()=>{
+ this.pauseContainer.createTweenClose("restart")
+ }, this);
+
+ // create events
+ this.events.on(EventKeys.CONTINUE,
+ ()=>{
+ this.pauseContainer.createTweenClose("continue")
+ }, this);
+
+ this.events.on('start',
+ ()=>{
+ this.removeListener();
+ }, this);
+ }
+
+ private removeListener(){
+ this.events.removeListener(EventKeys.CONTINUE);
+ this.events.removeListener(EventKeys.RESTART_GAME);
+ }
+}
diff --git a/src/games/tank/task.txt b/src/games/tank/task.txt
new file mode 100644
index 00000000..35a2f6aa
--- /dev/null
+++ b/src/games/tank/task.txt
@@ -0,0 +1,5 @@
+Container and Align Chỉnh sửa game Tank, bổ xung 2 popup: Pause & Game Over
+ + Bổ xung nút Pause trong game
+ + Bổ xung sound cho shoot & hit
+ + Pause: Có 2 nút Continue và New Game, Turn on/off Sound
+ + Game Over: Có Score, High Score và nút New Game
diff --git a/src/games/tank/tsconfig.json b/src/games/tank/tsconfig.json
index 12c795f0..28f97c03 100644
--- a/src/games/tank/tsconfig.json
+++ b/src/games/tank/tsconfig.json
@@ -3,8 +3,10 @@
"target": "ES6",
"module": "CommonJS",
"moduleResolution": "node",
- "noImplicitAny": true
+ "noImplicitAny": true,
+ "typeRoots": ["*/**/*.d.ts"]
},
+
"include": ["src/**/*"],
"exclude": ["node_modules"]
}