base work on engine, expanded
This commit is contained in:
parent
cc51c3831d
commit
73eba44e5e
BIN
public/assets/gui/button_02.png
Executable file
BIN
public/assets/gui/button_02.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
44
src/base/Button.ts
Normal file
44
src/base/Button.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import GameObject from "./GameObject";
|
||||
import * as PIXI from "pixi.js";
|
||||
|
||||
export default class Button extends GameObject {
|
||||
private caption: string;
|
||||
private color: PIXI.Color;
|
||||
private buttonTexture: PIXI.Texture;
|
||||
|
||||
setCaption(caption: string) {
|
||||
this.caption = caption;
|
||||
this.createButton();
|
||||
}
|
||||
|
||||
constructor(caption: string, bounds: PIXI.Rectangle, color: PIXI.Color) {
|
||||
super(bounds);
|
||||
this.caption = caption;
|
||||
this.color = color;
|
||||
this.container.interactive = true;
|
||||
this.buttonTexture = PIXI.Texture.from("/assets/gui/button02.png");
|
||||
this.createButton();
|
||||
}
|
||||
|
||||
protected triggerBoundsChanged() {
|
||||
this.createButton();
|
||||
}
|
||||
|
||||
private createButton() {
|
||||
this.container.removeChildren();
|
||||
const button = new PIXI.Graphics();
|
||||
button.rect(0, 0, this.bounds.width, this.bounds.height);
|
||||
button.fill(this.color);
|
||||
this.container.addChild(button);
|
||||
const text = new PIXI.Text({ text: this.caption });
|
||||
this.container.addChild(text);
|
||||
text.anchor.set(0.5, 0.5);
|
||||
text.x = this.bounds.width / 2;
|
||||
text.y = this.bounds.height / 2;
|
||||
this._container.x = this.bounds.x;
|
||||
this._container.y = this.bounds.y;
|
||||
this._container.on("click", () => {
|
||||
this.events.emit("click");
|
||||
});
|
||||
}
|
||||
}
|
55
src/base/Game.ts
Normal file
55
src/base/Game.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import MainMenu from "../scenes/MainMenu";
|
||||
import MissionMenuSelect from "../scenes/MissionSelectMenu";
|
||||
import GameObject from "./GameObject";
|
||||
import * as PIXI from "pixi.js";
|
||||
|
||||
export default class Game extends GameObject {
|
||||
private _currentScene: GameObject | null = null;
|
||||
|
||||
constructor(bounds: PIXI.Rectangle) {
|
||||
super(bounds);
|
||||
this.onMainMenu();
|
||||
}
|
||||
|
||||
private onMainMenu() {
|
||||
const mainScene = new MainMenu(this.bounds);
|
||||
mainScene.events.on("newGame", this.onNewGame);
|
||||
mainScene.events.on("settings", this.onSettings);
|
||||
this.setScene(mainScene);
|
||||
}
|
||||
|
||||
private onNewGame = () => {
|
||||
console.log("New Game");
|
||||
const missionSelectScene = new MissionMenuSelect(this.bounds);
|
||||
missionSelectScene.events.on("mission", (mission) => {
|
||||
console.log("Mission selected", mission);
|
||||
});
|
||||
missionSelectScene.events.on("back", () => {
|
||||
this.onMainMenu();
|
||||
});
|
||||
this.setScene(missionSelectScene);
|
||||
};
|
||||
|
||||
private onSettings = () => {
|
||||
console.log("Settings");
|
||||
};
|
||||
|
||||
private setScene(scene: GameObject) {
|
||||
if (this._currentScene) {
|
||||
this.container.removeChild(this._currentScene.container);
|
||||
}
|
||||
this._currentScene = scene;
|
||||
this.container.addChild(scene.container);
|
||||
this.drawScene();
|
||||
}
|
||||
|
||||
protected triggerBoundsChanged(): void {
|
||||
this.drawScene();
|
||||
}
|
||||
|
||||
private drawScene() {
|
||||
if (this._currentScene) {
|
||||
this._currentScene.setBounds(0, 0, this.bounds.width, this.bounds.height);
|
||||
}
|
||||
}
|
||||
}
|
32
src/base/GameObject.ts
Normal file
32
src/base/GameObject.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import * as PIXI from "pixi.js";
|
||||
export default abstract class GameObject {
|
||||
protected _container: PIXI.Container;
|
||||
|
||||
protected bounds: PIXI.Rectangle;
|
||||
|
||||
private _events: PIXI.EventEmitter = new PIXI.EventEmitter();
|
||||
|
||||
public getBounds(): PIXI.Rectangle {
|
||||
return this.bounds;
|
||||
}
|
||||
|
||||
public setBounds(x: number, y: number, width: number, height: number) {
|
||||
this.bounds = new PIXI.Rectangle(x, y, width, height);
|
||||
this.triggerBoundsChanged(); // GameObject implements this.
|
||||
}
|
||||
|
||||
public get container(): PIXI.Container {
|
||||
return this._container;
|
||||
}
|
||||
|
||||
public get events(): PIXI.EventEmitter {
|
||||
return this._events;
|
||||
}
|
||||
|
||||
protected abstract triggerBoundsChanged();
|
||||
|
||||
constructor(bounds: PIXI.Rectangle) {
|
||||
this.bounds = bounds;
|
||||
this._container = new PIXI.Container();
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
import { Renderer } from "./Renderer.ts";
|
||||
import { BaseScene, SceneType, makeSceneFromType } from "./Scenes.ts";
|
||||
|
||||
export class Game {
|
||||
public Renderer: Renderer;
|
||||
public currentScene: BaseScene;
|
||||
constructor(sceneType: SceneType) {
|
||||
this.Renderer = new Renderer();
|
||||
this.changeScene(sceneType);
|
||||
}
|
||||
changeScene(sceneType): void {
|
||||
if (this.currentScene != undefined) this.currentScene.destroy();
|
||||
this.currentScene = makeSceneFromType(sceneType);
|
||||
}
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
import * as PIXI from "pixi.js";
|
||||
import { Tower } from "./Tower.ts";
|
||||
|
||||
export enum CellType {
|
||||
Path,
|
||||
NoBuild,
|
||||
Build,
|
||||
Undefined,
|
||||
}
|
||||
|
||||
export class Cell {
|
||||
public x: number;
|
||||
public y: number;
|
||||
public type: CellType;
|
||||
public tower: Tower;
|
||||
constructor(x, y, type) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
export class Grid {
|
||||
public rows: number;
|
||||
public columns: number;
|
||||
public gridObject: PIXI.Container;
|
||||
public cells: Array<Cell>;
|
||||
constructor(x, y, width, height, rows, columns) {
|
||||
this.rows = rows;
|
||||
this.columns = columns;
|
||||
this.gridObject = new PIXI.Container({
|
||||
width: width,
|
||||
height: height,
|
||||
x: x,
|
||||
y: y,
|
||||
});
|
||||
for (let y = 0; y < rows; y++) {
|
||||
for (let x = 0; x < columns; x++) {
|
||||
let cell = new Cell(x, y, CellType.Undefined);
|
||||
this.cells.push(cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getPixelScalingFactor() {
|
||||
const pixelScaleX = this.gridObject.width / this.columns;
|
||||
const pixelScaleY = this.gridObject.height / this.rows;
|
||||
return pixelScaleX < pixelScaleY ? pixelScaleX : pixelScaleY;
|
||||
}
|
||||
|
||||
gridUnitsToPixels(amount: number): number {
|
||||
return amount * this.getPixelScalingFactor();
|
||||
}
|
||||
|
||||
pixelsToGridUnits(pixels: number): number {
|
||||
return pixels / this.getPixelScalingFactor();
|
||||
}
|
||||
|
||||
render() {}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
import * as PIXI from "pixi.js";
|
||||
|
||||
export class Renderer {
|
||||
constructor() {}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
import * as PIXI from "pixi.js";
|
||||
|
||||
export function makeSceneFromType(type: SceneType) {
|
||||
if (type == SceneType.MainMenu) {
|
||||
return new MainMenu();
|
||||
}
|
||||
if (type == SceneType.MissionSelect) {
|
||||
return new MissionSelect();
|
||||
}
|
||||
}
|
||||
|
||||
export enum SceneType {
|
||||
MainMenu,
|
||||
MissionSelect,
|
||||
}
|
||||
|
||||
export class BaseScene {
|
||||
public type: SceneType = null;
|
||||
public destroy(): boolean {
|
||||
return true; // return when destroyed
|
||||
}
|
||||
}
|
||||
|
||||
export class MainMenu extends BaseScene {
|
||||
public type: SceneType = SceneType.MainMenu;
|
||||
public;
|
||||
}
|
||||
|
||||
export class MissionSelect extends BaseScene {
|
||||
public type: SceneType = SceneType.MissionSelect;
|
||||
}
|
@ -1 +0,0 @@
|
||||
export class Tower {}
|
10
src/main.ts
10
src/main.ts
@ -1,6 +1,5 @@
|
||||
import * as PIXI from "pixi.js";
|
||||
import { Game } from "./classes/Game.ts";
|
||||
import { SceneType } from "./classes/Scenes.ts";
|
||||
import Game from "./base/Game";
|
||||
(async () => {
|
||||
const app = new PIXI.Application();
|
||||
await app.init({
|
||||
@ -11,5 +10,10 @@ import { SceneType } from "./classes/Scenes.ts";
|
||||
});
|
||||
|
||||
document.body.appendChild(app.canvas);
|
||||
globalThis.Game = new Game(SceneType.MainMenu);
|
||||
const game = new Game(app.screen);
|
||||
app.stage.addChild(game.container);
|
||||
window.addEventListener("resize", () => {
|
||||
app.renderer.resize(window.innerWidth, window.innerHeight);
|
||||
game.setBounds(0, 0, app.screen.width, app.screen.height);
|
||||
});
|
||||
})();
|
||||
|
12
src/scenes/Base.ts
Normal file
12
src/scenes/Base.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import * as PIXI from "pixi.js";
|
||||
import GameObject from "../base/GameObject";
|
||||
export default abstract class Scene extends GameObject {
|
||||
constructor(bounds: PIXI.Rectangle) {
|
||||
super(bounds);
|
||||
this.createScene();
|
||||
}
|
||||
protected triggerBoundsChanged() {
|
||||
this.createScene();
|
||||
}
|
||||
protected abstract createScene();
|
||||
}
|
52
src/scenes/MainMenu.ts
Normal file
52
src/scenes/MainMenu.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import Button from "../base/Button";
|
||||
import Scene from "./Base";
|
||||
import * as PIXI from "pixi.js";
|
||||
|
||||
export default class MainMenu extends Scene {
|
||||
private _newGameButton: Button;
|
||||
private _settingsButton: Button;
|
||||
|
||||
constructor(bounds: PIXI.Rectangle) {
|
||||
super(bounds);
|
||||
}
|
||||
|
||||
protected createScene() {
|
||||
console.log("Creating main menu scene", this.bounds);
|
||||
this.container.removeChildren();
|
||||
const g = new PIXI.Graphics();
|
||||
g.rect(0, 0, this.bounds.width, this.bounds.height);
|
||||
g.fill(0x000000);
|
||||
this.container.addChild(g);
|
||||
this._newGameButton = new Button(
|
||||
"New Game",
|
||||
new PIXI.Rectangle(
|
||||
100,
|
||||
this.bounds.height / 2 - 80,
|
||||
this.bounds.width - 200,
|
||||
60
|
||||
),
|
||||
new PIXI.Color("blue")
|
||||
);
|
||||
this._newGameButton.events.on("click", () => {
|
||||
this.events.emit("newGame");
|
||||
});
|
||||
this.container.addChild(this._newGameButton.container);
|
||||
|
||||
this._settingsButton = new Button(
|
||||
"Settings",
|
||||
new PIXI.Rectangle(
|
||||
100,
|
||||
this.bounds.height / 2 + 20,
|
||||
this.bounds.width - 200,
|
||||
60
|
||||
),
|
||||
new PIXI.Color("gray")
|
||||
);
|
||||
this._settingsButton.events.on("click", () => {
|
||||
this.events.emit("settings");
|
||||
});
|
||||
this.container.addChild(this._settingsButton.container);
|
||||
this.container.x = this.bounds.x;
|
||||
this.container.y = this.bounds.y;
|
||||
}
|
||||
}
|
47
src/scenes/MissionSelectMenu.ts
Normal file
47
src/scenes/MissionSelectMenu.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import Button from "../base/Button";
|
||||
import Scene from "./Base";
|
||||
import * as PIXI from "pixi.js";
|
||||
|
||||
export default class MissionMenuSelect extends Scene {
|
||||
private _buttons: Button[] = [];
|
||||
|
||||
constructor(bounds: PIXI.Rectangle) {
|
||||
super(bounds);
|
||||
}
|
||||
|
||||
protected createScene() {
|
||||
this.container.removeChildren();
|
||||
this._buttons = [];
|
||||
const g = new PIXI.Graphics();
|
||||
g.rect(0, 0, this.bounds.width, this.bounds.height);
|
||||
g.fill(0x000000);
|
||||
this.container.addChild(g);
|
||||
this.addMission("Mission 1");
|
||||
this.addMission("Mission 2");
|
||||
this.addMission("Mission 3");
|
||||
this.addMission("Mission 4");
|
||||
this.addButton("Back", () => {
|
||||
this.events.emit("back");
|
||||
});
|
||||
this.container.x = this.bounds.x;
|
||||
this.container.y = this.bounds.y;
|
||||
}
|
||||
|
||||
private addMission(mission: string) {
|
||||
this.addButton(mission, () => {
|
||||
this.events.emit("mission", mission);
|
||||
});
|
||||
}
|
||||
|
||||
private addButton(caption: string, onClick: () => void) {
|
||||
const yOffset = this._buttons.length * 80 + 100;
|
||||
const button = new Button(
|
||||
caption,
|
||||
new PIXI.Rectangle(100, yOffset, this.bounds.width - 200, 60),
|
||||
new PIXI.Color("white")
|
||||
);
|
||||
button.events.on("click", onClick);
|
||||
this._buttons.push(button);
|
||||
this.container.addChild(button.container);
|
||||
}
|
||||
}
|
51
src/scenes/SettingsMenu.ts
Normal file
51
src/scenes/SettingsMenu.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import Button from "../base/Button";
|
||||
import Scene from "./Base";
|
||||
import * as PIXI from "pixi.js";
|
||||
|
||||
export default class SettingsMenu extends Scene {
|
||||
private _newGameButton: Button;
|
||||
private _settingsButton: Button;
|
||||
|
||||
constructor(bounds: PIXI.Rectangle) {
|
||||
super(bounds);
|
||||
}
|
||||
|
||||
protected createScene() {
|
||||
this.container.removeChildren();
|
||||
const g = new PIXI.Graphics();
|
||||
g.rect(0, 0, this.bounds.width, this.bounds.height);
|
||||
g.fill(0x000000);
|
||||
this.container.addChild(g);
|
||||
this._newGameButton = new Button(
|
||||
"New Game",
|
||||
new PIXI.Rectangle(
|
||||
100,
|
||||
this.bounds.height / 2 - 80,
|
||||
this.bounds.width - 200,
|
||||
60
|
||||
),
|
||||
new PIXI.Color("blue")
|
||||
);
|
||||
this._newGameButton.events.on("click", () => {
|
||||
this.events.emit("newGame");
|
||||
});
|
||||
this.container.addChild(this._newGameButton.container);
|
||||
|
||||
this._settingsButton = new Button(
|
||||
"Settings",
|
||||
new PIXI.Rectangle(
|
||||
100,
|
||||
this.bounds.height / 2 + 20,
|
||||
this.bounds.width - 200,
|
||||
60
|
||||
),
|
||||
new PIXI.Color("gray")
|
||||
);
|
||||
this._settingsButton.events.on("click", () => {
|
||||
this.events.emit("settings");
|
||||
});
|
||||
this.container.addChild(this._settingsButton.container);
|
||||
this.container.x = this.bounds.x;
|
||||
this.container.y = this.bounds.y;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user