Skip to content

Commit

Permalink
✅ Add turn visualizer
Browse files Browse the repository at this point in the history
  • Loading branch information
rootasjey committed Feb 16, 2019
1 parent fda6d4e commit ab9a900
Show file tree
Hide file tree
Showing 8 changed files with 330 additions and 39 deletions.
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[WIP] A turn-based game system built with [Phaser 3](http://phaser.io).

<img src='./screenshot.gif' height='500' />
<img src='./cycles-preview.gif' height='500' />

## Roadmap

Expand All @@ -24,25 +24,25 @@

Reach one of the map objectives:

* Defeat all enemies
* Survive X days
* Defeat a specific enemy
* Rescue someone
- Defeat all enemies
- Survive X days
- Defeat a specific enemy
- Rescue someone

### A player turn

A typical player turn:

* Move units
* Make units attack or use items
* End turn
- Move units
- Make units attack or use items
- End turn

## Thanks

Thanks to these awesome tools and assets, I can have fun building a game:

* [Phaser 3](http://phaser.io)
* [Kenney assets](https://www.kenney.nl)
- [Phaser 3](http://phaser.io)
- [Kenney assets](https://www.kenney.nl)

## Licence

Expand Down
Binary file added cycles-preview.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 5 additions & 3 deletions src/gameObjects/Game.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import GameMap from './GameMap';
import MapUI from './MapUI';
import Turn from './Turn';
import GameMap from './GameMap';
import MapUI from './MapUI';
import Turn from './Turn';
import TurnVisualizer from './TurnVisualizer';

export class Game {
public static instance: Phaser.Game;
public static gameMap: GameMap;
public static mapUI: MapUI;
public static turn: Turn;
public static turnVisualizer: TurnVisualizer;
}
11 changes: 8 additions & 3 deletions src/gameObjects/GameMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export default class GameMap extends Phaser.GameObjects.GameObject {
// PUBLIC FUNCTIONS
// ~~~~~~~~~~~~~~~~~

public getAllPlayersOnMap() {
public getAllPlayersOnMap(): Player[] {
const players: PlayerMap = {};

const { units: unitsLayer } = this.layers;
Expand All @@ -99,7 +99,7 @@ export default class GameMap extends Phaser.GameObjects.GameObject {

}, undefined, undefined, undefined, undefined, undefined, { isNotEmpty: true });

return players;
return Object.values(players);
}

// ~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -449,8 +449,13 @@ export default class GameMap extends Phaser.GameObjects.GameObject {
}

private onMapActionEndTurn() {
Game.turn.next();
this.removeMapActionsListeners();

Game.turn.next();

const { currentPlayer, turnNumber } = Game.turn;

Game.turnVisualizer.showNext({ player: currentPlayer, turnNumber });
}

private onMapActionSuspend() {
Expand Down
7 changes: 6 additions & 1 deletion src/gameObjects/Turn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@ export default class Turn {
// PUBLIC PROPERTIES
// ~~~~~~~~~~~~~~~~~

/** The current turn since the beggining of the party. */
/** Current turn number since the beggining of the party. */
public get turnNumber(): number {
return this.TURN_NUMBER;
}

/** Current active player. */
public get currentPlayer(): Player {
return this.players[this.currentPlayerIndex];
}

// ~~~~~~~~~~~~~~~~~
// PRIVATE PROPERTIES
// ~~~~~~~~~~~~~~~~~
Expand Down
272 changes: 272 additions & 0 deletions src/gameObjects/TurnVisualizer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
import { fonts } from '../const/config';
export default class TurnVisualizer extends Phaser.GameObjects.GameObject {
// @ts-ignore : This prop is initialized in the `init()` method in the constructor.
private textPlayerName: Phaser.GameObjects.Text;

// @ts-ignore : This prop is initialized in the `init()` method in the constructor.
private textTurn: Phaser.GameObjects.Text;

// @ts-ignore : This prop is initialized in the `init()` method in the constructor.
private textTurnNumber: Phaser.GameObjects.Text;

// @ts-ignore : This prop is initialized in the `init()` method in the constructor.
private rectBackground: Phaser.GameObjects.Rectangle;

// @ts-ignore : This prop is initialized in the `init()` method in the constructor.
private rectTextBackground: Phaser.GameObjects.Rectangle;

constructor(scene: Phaser.Scene) {
super(scene, 'TurnVisualizer');

this.init();
}

// ~~~~~~~~~~~~~~~~~
// PUBLIC FUNCTIONS
// ~~~~~~~~~~~~~~~~~

/** Show next turn: player's name & turns number. */
public showNext(param: ShowTurnParam) {
const { player: { name }, turnNumber } = param;

this.textPlayerName.setText(name);
this.textTurnNumber.setText(turnNumber.toString());

this
.toggleVisibility(true)
.animateElements();
}

// ~~~~~~~~~~~~~~~~~
// PRIVATE FUNCTIONS
// ~~~~~~~~~~~~~~~~~

private animateElements() {
this
.fadeInElements()
.fadeOutElements();

return this;
}

private createElements() {
const { add } = this.scene;
const { normal: normalStyle } = fonts.styles;

const { innerHeight: windowHeight, innerWidth: windowWidth } = window;
const halfHeight = windowHeight / 2;
const halfWidth = windowWidth / 2;

this.rectBackground = add.rectangle(halfWidth, halfHeight, windowWidth, windowHeight + 20, 0xfff, .5);
this.rectTextBackground = add.rectangle(halfWidth, halfHeight, windowWidth, 100, 0x000);
this.textPlayerName = add.text(40, halfHeight - 50, 'player name', normalStyle);
this.textTurn = add.text(40, halfHeight - 20, 'TURN', { ...normalStyle, ...{ fontSize: 70 } });
this.textTurnNumber = add.text(240, halfHeight - 80, '0', { ...normalStyle, ...{ fontSize: 160 } });

return this;
}

private disableEvents() {
this.scene.events.off('gameResize', this.onGameResize, this);
return this;
}

private enableEvents() {
this.scene.events.on('gameResize', this.onGameResize, this);
return this;
}

private fadeInElements() {
const { tweens } = this.scene;

tweens.add({
alpha: .5,
duration: 600,
targets: this.rectBackground,
});

tweens.add({
alpha: 1,
displayHeight: 150,
duration: 600,
targets: this.rectTextBackground,
});

tweens.add({
alpha: 1,
delay: 200,
duration: 300,
targets: this.textTurn,
x: 20,
});

tweens.add({
alpha: 1,
delay: 300,
duration: 300,
targets: this.textPlayerName,
x: 20,
});

tweens.add({
alpha: 1,
delay: 400,
duration: 300,
targets: this.textTurnNumber,
x: 210,
});

return this;
}

private fadeOutElements() {
const { tweens } = this.scene;

const numberOfElements = 5;
let elementsCompleted = 0;

setTimeout(() => {
tweens.add({
alpha: 0,
duration: 500,
onComplete: () => {
elementsCompleted++;

if (elementsCompleted === numberOfElements) {
this.toggleVisibility(false);
}
},
targets: this.textTurnNumber,
x: 240,
});

tweens.add({
alpha: 0,
delay: 200,
duration: 500,
onComplete: () => {
elementsCompleted++;

if (elementsCompleted === numberOfElements) {
this.toggleVisibility(false);
}
},
targets: this.textTurn,
x: 40,
});

tweens.add({
alpha: 0,
delay: 300,
duration: 500,
onComplete: () => {
elementsCompleted++;

if (elementsCompleted === numberOfElements) {
this.toggleVisibility(false);
}
},
targets: this.textPlayerName,
x: 40,
});

tweens.add({
delay: 600,
duration: 600,
onComplete: () => {
elementsCompleted++;

if (elementsCompleted === numberOfElements) {
this.toggleVisibility(false);
}
},
targets: this.rectBackground,
alpha: 0,
});

tweens.add({
alpha: 0,
delay: 600,
displayHeight: 100,
duration: 600,
onComplete: () => {
elementsCompleted++;

if (elementsCompleted === numberOfElements) {
this.toggleVisibility(false);
}
},
targets: this.rectTextBackground,
});

}, 2000);

return this;
}

private glueElements() {
this.rectBackground.setScrollFactor(0);
this.rectTextBackground.setScrollFactor(0);
this.textPlayerName.setScrollFactor(0);
this.textTurn.setScrollFactor(0);
this.textTurnNumber.setScrollFactor(0);

return this;
}

private init() {
this
.createElements()
.glueElements()
.listenToEvents()
.toggleVisibility(false);

return this;
}

private listenToDestroy() {
this.once('destroy', () => {
this.textPlayerName.destroy();
this.textTurn.destroy();
this.textTurnNumber.destroy();
this.rectBackground.destroy();
this.rectTextBackground.destroy();
});

return this;
}

private listenToEvents() {
this.scene.events.on('subscribeTurnVisualizerEvents', this.enableEvents, this);
this.scene.events.on('unsubscribeTurnVisualizerEvents', this.disableEvents, this);

this
.enableEvents()
.listenToDestroy();

return this;
}

private onGameResize() {
// Move texts & rectangles.
}

private toggleVisibility(show: boolean) {
if (show) {
this.rectBackground.setAlpha(0);
this.rectTextBackground.setAlpha(0);
this.textPlayerName.setAlpha(0);
this.textTurn.setAlpha(0);
this.textTurnNumber.setAlpha(0);
}

this.rectBackground.setVisible(show);
this.rectTextBackground.setVisible(show);
this.textPlayerName.setVisible(show);
this.textTurn.setVisible(show);
this.textTurnNumber.setVisible(show);

return this;
}

}
Loading

1 comment on commit ab9a900

@rootasjey
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solve issue #11

Please sign in to comment.