12
public/assets/Towers.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Basic Tower",
|
||||||
|
"stats": {
|
||||||
|
"damage": 2,
|
||||||
|
"cooldown": 2,
|
||||||
|
"gemSlotsAmount": 2,
|
||||||
|
"cost": 100,
|
||||||
|
"range": 7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
0
public/assets/gui/button_02.png
Executable file → Normal file
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
BIN
public/assets/gui/frame.png
Executable file
After Width: | Height: | Size: 8.3 KiB |
BIN
public/assets/gui/heart.png
Executable file
After Width: | Height: | Size: 20 KiB |
BIN
public/assets/gui/shield.png
Executable file
After Width: | Height: | Size: 38 KiB |
BIN
public/assets/gui/star.png
Executable file
After Width: | Height: | Size: 69 KiB |
BIN
public/assets/gui/star_empty.png
Executable file
After Width: | Height: | Size: 43 KiB |
BIN
public/assets/gui/sword_01.png
Executable file
After Width: | Height: | Size: 34 KiB |
BIN
public/assets/gui/sword_02.png
Executable file
After Width: | Height: | Size: 111 KiB |
@ -1,5 +1,5 @@
|
|||||||
import * as PIXI from 'pixi.js';
|
import * as PIXI from 'pixi.js';
|
||||||
import { CreepStats, MissionDefinition } from './Definitions';
|
import { CreepStatsDefinition, MissionDefinition, TowerDefinition } from './Definitions';
|
||||||
|
|
||||||
export default class Assets {
|
export default class Assets {
|
||||||
public static async LoadAssets() {
|
public static async LoadAssets() {
|
||||||
@ -7,11 +7,20 @@ export default class Assets {
|
|||||||
Assets.ButtonTexture = await PIXI.Assets.load({
|
Assets.ButtonTexture = await PIXI.Assets.load({
|
||||||
src: '/assets/gui/button_02.png',
|
src: '/assets/gui/button_02.png',
|
||||||
});
|
});
|
||||||
|
Assets.SidebarTexture = await PIXI.Assets.load({
|
||||||
|
src: '/assets/gui/frame.png',
|
||||||
|
});
|
||||||
|
Assets.HealthTexture = await PIXI.Assets.load({
|
||||||
|
src: '/assets/gui/heart.png',
|
||||||
|
});
|
||||||
|
Assets.GoldTexture = await PIXI.Assets.load({
|
||||||
|
src: '/assets/gui/star.png',
|
||||||
|
});
|
||||||
Assets.BasicCreepTexture = await PIXI.Assets.load({
|
Assets.BasicCreepTexture = await PIXI.Assets.load({
|
||||||
src: '/assets/creeps/basic.jpg',
|
src: '/assets/creeps/basic.jpg',
|
||||||
});
|
});
|
||||||
console.log('Loading Missions');
|
|
||||||
await this.LoadMissions();
|
await this.LoadMissions();
|
||||||
|
await this.LoadTowers();
|
||||||
await this.LoadCreepStats();
|
await this.LoadCreepStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,6 +34,12 @@ export default class Assets {
|
|||||||
Assets.Missions = [await this.LoadMission('/assets/missions/mission_01.json')];
|
Assets.Missions = [await this.LoadMission('/assets/missions/mission_01.json')];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static async LoadTowers() {
|
||||||
|
const res = await fetch('/assets/Towers.json');
|
||||||
|
const towers = await res.json();
|
||||||
|
Assets.Towers = towers;
|
||||||
|
}
|
||||||
|
|
||||||
private static async LoadMission(missionUrl: string) {
|
private static async LoadMission(missionUrl: string) {
|
||||||
const res = await fetch(missionUrl);
|
const res = await fetch(missionUrl);
|
||||||
const mission = await res.json();
|
const mission = await res.json();
|
||||||
@ -40,10 +55,16 @@ export default class Assets {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ButtonTexture: PIXI.Texture;
|
|
||||||
public static BasicCreepTexture: PIXI.Texture;
|
public static BasicCreepTexture: PIXI.Texture;
|
||||||
|
|
||||||
|
public static ButtonTexture: PIXI.Texture;
|
||||||
|
public static SidebarTexture: PIXI.Texture;
|
||||||
|
public static HealthTexture: PIXI.Texture;
|
||||||
|
public static GoldTexture: PIXI.Texture;
|
||||||
|
|
||||||
public static MissionBackgrounds: PIXI.Texture[] = [];
|
public static MissionBackgrounds: PIXI.Texture[] = [];
|
||||||
public static Missions: MissionDefinition[];
|
public static Missions: MissionDefinition[];
|
||||||
public static CreepStats: CreepStats[];
|
public static Towers: TowerDefinition[];
|
||||||
|
public static CreepStats: CreepStatsDefinition[];
|
||||||
|
public static DebuggingEnabled: boolean = true;
|
||||||
}
|
}
|
||||||
|
@ -30,14 +30,14 @@ export type WaveDefinition = {
|
|||||||
creeps: CreepType[];
|
creeps: CreepType[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CreepStats = {
|
export type CreepStatsDefinition = {
|
||||||
health: number;
|
health: number;
|
||||||
speed: number;
|
speed: number;
|
||||||
special: Function;
|
special: Function;
|
||||||
resistance: CreepResistances;
|
resistance: CreepResistancesDefinition;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CreepResistances = {
|
export type CreepResistancesDefinition = {
|
||||||
physical: number;
|
physical: number;
|
||||||
divine: number;
|
divine: number;
|
||||||
fire: number;
|
fire: number;
|
||||||
@ -45,6 +45,19 @@ export type CreepResistances = {
|
|||||||
frostfire: number;
|
frostfire: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type TowerDefinition = {
|
||||||
|
name: string;
|
||||||
|
stats: TowerStatsDefinition;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TowerStatsDefinition = {
|
||||||
|
damage: number;
|
||||||
|
cooldown: number;
|
||||||
|
gemSlotsAmount: number;
|
||||||
|
cost: number;
|
||||||
|
range: number;
|
||||||
|
};
|
||||||
|
|
||||||
export type PathDefinition = [[row: number, column: number]];
|
export type PathDefinition = [[row: number, column: number]];
|
||||||
|
|
||||||
export enum CreepType {
|
export enum CreepType {
|
||||||
@ -64,3 +77,8 @@ export enum GemType {
|
|||||||
Titalium = 2,
|
Titalium = 2,
|
||||||
Soulforge = 3,
|
Soulforge = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum TowerType {
|
||||||
|
Shooting = 0,
|
||||||
|
Circle = 1,
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import Assets from '../base/Assets';
|
import Assets from '../base/Assets';
|
||||||
import { CreepStats, CreepType, PathDefinition } from '../base/Definitions';
|
import { CreepStatsDefinition, CreepType, PathDefinition } from '../base/Definitions';
|
||||||
import GameObject from '../base/GameObject';
|
import GameObject from '../base/GameObject';
|
||||||
import * as PIXI from 'pixi.js';
|
import * as PIXI from 'pixi.js';
|
||||||
import GameScene from '../scenes/GameScene';
|
import GameScene from '../scenes/GameScene';
|
||||||
@ -14,7 +14,7 @@ export enum CreepEvents {
|
|||||||
export default class Creep extends GameObject {
|
export default class Creep extends GameObject {
|
||||||
public creepType: CreepType;
|
public creepType: CreepType;
|
||||||
private path: PathDefinition;
|
private path: PathDefinition;
|
||||||
private stats: CreepStats;
|
private stats: CreepStatsDefinition;
|
||||||
private pathIndex: number = 0;
|
private pathIndex: number = 0;
|
||||||
private speed: number;
|
private speed: number;
|
||||||
private gameScene: GameScene;
|
private gameScene: GameScene;
|
||||||
|
@ -40,7 +40,7 @@ export class Cell extends GameObject {
|
|||||||
this.container.addChild(g);
|
this.container.addChild(g);
|
||||||
this.container.x = this.bounds.x;
|
this.container.x = this.bounds.x;
|
||||||
this.container.y = this.bounds.y;
|
this.container.y = this.bounds.y;
|
||||||
return; // comment to enable debugging
|
if (!Assets.DebuggingEnabled) return;
|
||||||
const text = new PIXI.Text({
|
const text = new PIXI.Text({
|
||||||
text: `${this.row}|${this.column}`,
|
text: `${this.row}|${this.column}`,
|
||||||
style: new PIXI.TextStyle({
|
style: new PIXI.TextStyle({
|
||||||
@ -101,10 +101,6 @@ export class Grid extends GameObject {
|
|||||||
protected draw() {
|
protected draw() {
|
||||||
console.log('Drawing Grid', this.bounds);
|
console.log('Drawing Grid', this.bounds);
|
||||||
this.container.removeChildren();
|
this.container.removeChildren();
|
||||||
// let g = new PIXI.Graphics();
|
|
||||||
// g.rect(0, 0, this.bounds.width, this.bounds.height + 100);
|
|
||||||
// g.fill(0xffffff);
|
|
||||||
// this.container.addChild(g);
|
|
||||||
let background = new PIXI.Sprite(Assets.MissionBackgrounds[this.gameScene.missionIndex]);
|
let background = new PIXI.Sprite(Assets.MissionBackgrounds[this.gameScene.missionIndex]);
|
||||||
background.x = 0;
|
background.x = 0;
|
||||||
background.y = 0;
|
background.y = 0;
|
||||||
@ -113,8 +109,8 @@ export class Grid extends GameObject {
|
|||||||
this.container.addChild(background);
|
this.container.addChild(background);
|
||||||
for (let cell of this.cells) {
|
for (let cell of this.cells) {
|
||||||
cell.setBounds(
|
cell.setBounds(
|
||||||
this.gridUnitsToPixels(cell.column),
|
parseFloat(this.gridUnitsToPixels(cell.column).toFixed(2)),
|
||||||
this.gridUnitsToPixels(cell.row),
|
parseFloat(this.gridUnitsToPixels(cell.row).toFixed(2)),
|
||||||
this.gridUnitsToPixels(1),
|
this.gridUnitsToPixels(1),
|
||||||
this.gridUnitsToPixels(1)
|
this.gridUnitsToPixels(1)
|
||||||
);
|
);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import Assets from '../base/Assets';
|
||||||
import GameObject from '../base/GameObject';
|
import GameObject from '../base/GameObject';
|
||||||
import * as PIXI from 'pixi.js';
|
import * as PIXI from 'pixi.js';
|
||||||
|
|
||||||
@ -33,18 +34,55 @@ export default class MissionStats extends GameObject {
|
|||||||
|
|
||||||
protected draw() {
|
protected draw() {
|
||||||
this.container.removeChildren();
|
this.container.removeChildren();
|
||||||
const g = new PIXI.Graphics();
|
const sprite = new PIXI.NineSliceSprite({
|
||||||
g.rect(0, 0, this.bounds.width, this.bounds.height);
|
texture: Assets.SidebarTexture,
|
||||||
g.fill(0x000000);
|
leftWidth: 100,
|
||||||
this.container.addChild(g);
|
topHeight: 100,
|
||||||
const text = new PIXI.Text({
|
rightWidth: 100,
|
||||||
text: `HP: ${this.hp}\nGold: ${this.gold}`,
|
bottomHeight: 100,
|
||||||
|
});
|
||||||
|
sprite.width = this.bounds.width + 200;
|
||||||
|
sprite.height = this.bounds.height + 5;
|
||||||
|
sprite.x = sprite.x - 100;
|
||||||
|
sprite.y = sprite.y - 5;
|
||||||
|
const healthText = new PIXI.Text({
|
||||||
|
text: `HP: ${this.hp}`,
|
||||||
style: new PIXI.TextStyle({
|
style: new PIXI.TextStyle({
|
||||||
fill: 'white',
|
fill: 'white',
|
||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
dropShadow: true,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
this.container.addChild(text);
|
healthText.x = 400;
|
||||||
|
const goldText = new PIXI.Text({
|
||||||
|
text: `Gold: ${this.gold}`,
|
||||||
|
style: new PIXI.TextStyle({
|
||||||
|
fill: 'white',
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
dropShadow: true,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
goldText.x = 400;
|
||||||
|
goldText.y = 30;
|
||||||
|
|
||||||
|
const healthSprite = new PIXI.Sprite(Assets.HealthTexture);
|
||||||
|
healthSprite.x = 365;
|
||||||
|
healthSprite.width = 30;
|
||||||
|
healthSprite.height = 26;
|
||||||
|
healthSprite.y = 1;
|
||||||
|
|
||||||
|
const goldSprite = new PIXI.Sprite(Assets.GoldTexture);
|
||||||
|
goldSprite.x = 365;
|
||||||
|
goldSprite.width = 30;
|
||||||
|
goldSprite.height = 26;
|
||||||
|
goldSprite.y = 30;
|
||||||
|
this.container.addChild(sprite);
|
||||||
|
this.container.addChild(healthText);
|
||||||
|
this.container.addChild(goldText);
|
||||||
|
this.container.addChild(healthSprite);
|
||||||
|
this.container.addChild(goldSprite);
|
||||||
this.container.x = this.bounds.x;
|
this.container.x = this.bounds.x;
|
||||||
this.container.y = this.bounds.y;
|
this.container.y = this.bounds.y;
|
||||||
}
|
}
|
||||||
|
27
src/components/Sidebar.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import * as PIXI from 'pixi.js';
|
||||||
|
import GameObject from '../base/GameObject';
|
||||||
|
import GameScene from '../scenes/GameScene';
|
||||||
|
import Assets from '../base/Assets';
|
||||||
|
|
||||||
|
export default class Sidebar extends GameObject {
|
||||||
|
private gameScene: GameScene;
|
||||||
|
constructor(gameScene: GameScene, bounds?: PIXI.Rectangle) {
|
||||||
|
super(bounds);
|
||||||
|
this.gameScene = gameScene;
|
||||||
|
}
|
||||||
|
protected draw() {
|
||||||
|
this.container.removeChildren();
|
||||||
|
const sprite = new PIXI.NineSliceSprite({
|
||||||
|
texture: Assets.SidebarTexture,
|
||||||
|
leftWidth: 100,
|
||||||
|
topHeight: 100,
|
||||||
|
rightWidth: 100,
|
||||||
|
bottomHeight: 100,
|
||||||
|
});
|
||||||
|
sprite.width = this.bounds.width;
|
||||||
|
sprite.height = this.bounds.height;
|
||||||
|
this.container.addChild(sprite);
|
||||||
|
this.container.x = this.bounds.x;
|
||||||
|
this.container.y = this.bounds.y;
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ import { MissionDefinition } from '../base/Definitions';
|
|||||||
import Creep, { CreepEvents } from '../components/Creep';
|
import Creep, { CreepEvents } from '../components/Creep';
|
||||||
import { Grid } from '../components/Grid';
|
import { Grid } from '../components/Grid';
|
||||||
import MissionStats from '../components/MissionStats';
|
import MissionStats from '../components/MissionStats';
|
||||||
|
import Sidebar from '../components/Sidebar';
|
||||||
import WaveManager, { WaveManagerEvents } from '../components/WaveManager';
|
import WaveManager, { WaveManagerEvents } from '../components/WaveManager';
|
||||||
import SceneBase from './SceneBase';
|
import SceneBase from './SceneBase';
|
||||||
import * as PIXI from 'pixi.js';
|
import * as PIXI from 'pixi.js';
|
||||||
@ -17,6 +18,7 @@ export default class GameScene extends SceneBase {
|
|||||||
private ticker: PIXI.Ticker;
|
private ticker: PIXI.Ticker;
|
||||||
private stats: MissionStats;
|
private stats: MissionStats;
|
||||||
private waveManager: WaveManager;
|
private waveManager: WaveManager;
|
||||||
|
private sidebar: Sidebar;
|
||||||
private roundMode = RoundMode.Purchase;
|
private roundMode = RoundMode.Purchase;
|
||||||
private changeRoundButton: Button;
|
private changeRoundButton: Button;
|
||||||
private currentRound: number = 0;
|
private currentRound: number = 0;
|
||||||
@ -36,6 +38,7 @@ export default class GameScene extends SceneBase {
|
|||||||
});
|
});
|
||||||
this.stats = new MissionStats(100, 200);
|
this.stats = new MissionStats(100, 200);
|
||||||
this.grid = new Grid(mission.gameMap, this);
|
this.grid = new Grid(mission.gameMap, this);
|
||||||
|
this.sidebar = new Sidebar(this);
|
||||||
this.gridWidth = mission.mapImage.width;
|
this.gridWidth = mission.mapImage.width;
|
||||||
this.gridHeight = mission.mapImage.height;
|
this.gridHeight = mission.mapImage.height;
|
||||||
this.ticker = new PIXI.Ticker();
|
this.ticker = new PIXI.Ticker();
|
||||||
@ -108,7 +111,9 @@ export default class GameScene extends SceneBase {
|
|||||||
this.container.addChild(g);
|
this.container.addChild(g);
|
||||||
this.stats.setBounds(this.getStatusBounds());
|
this.stats.setBounds(this.getStatusBounds());
|
||||||
this.grid.setBounds(this.getGridBounds());
|
this.grid.setBounds(this.getGridBounds());
|
||||||
|
this.sidebar.setBounds(this.getSidebarBounds());
|
||||||
this.changeRoundButton.setBounds(this.getChangeRoundButtonBounds());
|
this.changeRoundButton.setBounds(this.getChangeRoundButtonBounds());
|
||||||
|
this.container.addChild(this.sidebar.container);
|
||||||
this.container.addChild(this.stats.container);
|
this.container.addChild(this.stats.container);
|
||||||
this.container.addChild(this.grid.container);
|
this.container.addChild(this.grid.container);
|
||||||
this.container.addChild(this.changeRoundButton.container);
|
this.container.addChild(this.changeRoundButton.container);
|
||||||
@ -116,15 +121,16 @@ export default class GameScene extends SceneBase {
|
|||||||
this.container.y = this.bounds.y;
|
this.container.y = this.bounds.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getSidebarBounds(): PIXI.Rectangle {
|
||||||
|
return new PIXI.Rectangle(this.bounds.width - 350, 0, 350, this.bounds.height);
|
||||||
|
}
|
||||||
private getStatusBounds(): PIXI.Rectangle {
|
private getStatusBounds(): PIXI.Rectangle {
|
||||||
// Top / Center
|
// Top / Center
|
||||||
return new PIXI.Rectangle(this.bounds.width / 2 - 200 / 2, 0, 200, 100);
|
return new PIXI.Rectangle(0, 0, this.bounds.width, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getGridBounds(): PIXI.Rectangle {
|
private getGridBounds(): PIXI.Rectangle {
|
||||||
// Center / Center
|
// Center / Center
|
||||||
let width = 600;
|
|
||||||
let height = 600;
|
|
||||||
return new PIXI.Rectangle(
|
return new PIXI.Rectangle(
|
||||||
this.bounds.width / 2 - this.gridWidth / 2,
|
this.bounds.width / 2 - this.gridWidth / 2,
|
||||||
this.bounds.height / 2 - this.gridHeight / 2,
|
this.bounds.height / 2 - this.gridHeight / 2,
|
||||||
@ -134,7 +140,7 @@ export default class GameScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
private getChangeRoundButtonBounds(): PIXI.Rectangle {
|
private getChangeRoundButtonBounds(): PIXI.Rectangle {
|
||||||
// Center / Center
|
// Center / Center
|
||||||
let width = 300;
|
let width = 350;
|
||||||
let height = 150;
|
let height = 150;
|
||||||
return new PIXI.Rectangle(this.bounds.width - width, this.bounds.height - height, width, height);
|
return new PIXI.Rectangle(this.bounds.width - width, this.bounds.height - height, width, height);
|
||||||
}
|
}
|
||||||
|