this is difficult

This commit is contained in:
koneko 2024-12-23 21:25:24 +01:00
parent b394ff9e0a
commit 086c733bb3
22 changed files with 1267 additions and 1070 deletions

View File

@ -8,6 +8,9 @@
<title>Bastion App</title> <title>Bastion App</title>
</head> </head>
<body> <body>
<div id="game-container" style="background-color: black; width: 100%; height: 100%; overflow: hidden">
<canvas id="game-canvas"></canvas>
</div>
<script type="module" src="/src/main.ts"></script> <script type="module" src="/src/main.ts"></script>
</body> </body>
</html> </html>

10
package-lock.json generated
View File

@ -8,6 +8,7 @@
"name": "bastion", "name": "bastion",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"pixi-viewport": "^6.0.3",
"pixi.js": "^8.4.0" "pixi.js": "^8.4.0"
}, },
"devDependencies": { "devDependencies": {
@ -774,6 +775,15 @@
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/pixi-viewport": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/pixi-viewport/-/pixi-viewport-6.0.3.tgz",
"integrity": "sha512-2+qPJ0/n+8hQYhWvY+795+x9y3MiUrCOWacK0DY53whowWaGdx9iDocy7z1pBwjkZhC52YvrJQuZKK0sdVLtBw==",
"license": "MIT",
"peerDependencies": {
"pixi.js": ">=8"
}
},
"node_modules/pixi.js": { "node_modules/pixi.js": {
"version": "8.4.0", "version": "8.4.0",
"resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-8.4.0.tgz", "resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-8.4.0.tgz",

View File

@ -13,6 +13,7 @@
"vite": "^5.4.1" "vite": "^5.4.1"
}, },
"dependencies": { "dependencies": {
"pixi-viewport": "^6.0.3",
"pixi.js": "^8.4.0" "pixi.js": "^8.4.0"
} }
} }

28
public/Mission01.tmx Normal file
View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-down" width="20" height="20" tilewidth="64" tileheight="64" infinite="0" nextlayerid="2" nextobjectid="1">
<tileset firstgid="1" source="Tileset.tsx"/>
<layer id="1" name="Tile Layer 1" width="20" height="20">
<data encoding="csv">
15,15,15,15,15,15,15,16,15,15,15,15,15,15,15,15,15,15,15,15,
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,15,15,15,
4,4,4,4,4,4,4,4,4,4,4,5,15,15,15,15,15,15,15,15,
32,32,32,32,32,32,32,32,32,32,7,19,15,15,15,15,15,15,15,16,
15,15,15,15,15,15,16,15,15,15,17,19,15,15,15,15,15,15,15,15,
15,15,15,15,15,15,15,15,15,15,17,19,15,15,15,15,15,15,15,15,
15,16,15,15,15,15,15,15,15,15,17,19,15,15,16,15,15,15,15,15,
15,15,15,15,15,15,15,15,15,15,17,20,4,4,4,4,4,5,15,15,
15,15,15,15,16,15,15,15,15,15,31,32,32,32,32,32,7,19,15,15,
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,17,19,15,15,
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,17,19,15,15,
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,17,19,15,15,
15,16,15,15,3,4,4,4,4,4,4,4,4,4,4,4,21,19,15,15,
15,15,15,15,17,6,32,32,32,32,32,32,32,32,32,32,32,33,15,15,
15,15,15,15,17,19,16,15,15,15,15,15,15,15,15,15,15,15,15,15,
15,15,15,15,17,19,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
15,15,15,15,17,19,15,15,15,15,15,15,15,16,15,15,15,15,15,15,
15,15,15,15,17,19,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
15,15,15,15,17,19,15,15,15,15,15,15,15,15,15,15,15,15,15,15
</data>
</layer>
</map>

4
public/Tileset.tsx Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.10" tiledversion="1.11.0" name="TiledTDThree64" tilewidth="64" tileheight="64" tilecount="140" columns="14">
<image source="../../../../dumping/tiles/TiledTDThree64.png" width="896" height="640"/>
</tileset>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 127 KiB

View File

@ -3,11 +3,11 @@
"description": "This is the first mission", "description": "This is the first mission",
"mapImage": { "mapImage": {
"url": "/assets/maps/mission_01.png", "url": "/assets/maps/mission_01.png",
"width": 1200, "width": 1280,
"height": 900 "height": 1280
}, },
"gameMap": { "gameMap": {
"rows": 15, "rows": 20,
"columns": 20, "columns": 20,
"cells": [ "cells": [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
@ -24,6 +24,12 @@
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
], ],
"paths": [ "paths": [

14
public/maps.tiled-project Normal file
View File

@ -0,0 +1,14 @@
{
"automappingRulesFile": "",
"commands": [
],
"compatibilityVersion": 1100,
"extensionsPath": "extensions",
"folders": [
"."
],
"properties": [
],
"propertyTypes": [
]
}

43
public/maps.tiled-session Normal file
View File

@ -0,0 +1,43 @@
{
"Map/SizeTest": {
"height": 4300,
"width": 2
},
"activeFile": "",
"expandedProjectPaths": [
"."
],
"file.lastUsedOpenFilter": "All Files (*)",
"fileStates": {
"": {
"scaleInDock": 0.33
},
"#TiledTDThree128": {
"scaleInDock": 0.33,
"scaleInEditor": 1
},
"/home/koneko/dumping/tiles/TiledTDThree64.tmx": {
"scale": 0.187625,
"selectedLayer": 0,
"viewCenter": {
"x": 3197.8680879413732,
"y": 3197.8680879413732
}
},
"Tileset.tsx": {
"scaleInDock": 1
}
},
"last.externalTilesetPath": "/home/koneko/Programing/js/towerdefense/public",
"map.lastUsedFormat": "tmx",
"map.tileHeight": 64,
"map.tileWidth": 64,
"map.width": 20,
"openFiles": [
],
"project": "maps.tiled-project",
"recentFiles": [
"/home/koneko/dumping/tiles/TiledTDThree64.tmx"
],
"tileset.lastUsedFilter": "Tiled tileset files (*.tsx *.xml)"
}

View File

@ -7,9 +7,9 @@ html {
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
overflow: hidden; overflow: hidden;
background-color: black; /* background-color: white;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
justify-content: center; justify-content: center; */
} }

View File

@ -1,42 +1,55 @@
import * as PIXI from 'pixi.js'; import * as PIXI from 'pixi.js';
import { CreepStatsDefinition, MissionDefinition, TowerDefinition } from './Definitions'; import { CreepStatsDefinition, MissionDefinition, TowerDefinition } from './Definitions';
import { Globals } from './Bastion';
export default class Assets { export default class GameAssets {
public static async LoadAssets() { public static async LoadAssets() {
console.log('Loading Texture Assets'); console.log('Loading Texture Assets');
Assets.Button01Texture = await PIXI.Assets.load({ const text = new PIXI.Text({
text: 'Loading textures. This might take a while.',
style: new PIXI.TextStyle({
fill: 0xffffff,
fontSize: 50,
}),
});
text.x = Globals.WindowWidth / 2;
text.y = Globals.WindowHeight / 2;
text.anchor.set(0.5, 0.5);
Globals.app.stage.addChild(text);
GameAssets.Button01Texture = await PIXI.Assets.load({
src: '/assets/gui/button_01.png', src: '/assets/gui/button_01.png',
}); });
Assets.Button02Texture = await PIXI.Assets.load({ GameAssets.Button02Texture = await PIXI.Assets.load({
src: '/assets/gui/button_02.png', src: '/assets/gui/button_02.png',
}); });
Assets.Frame01Texture = await PIXI.Assets.load({ GameAssets.Frame01Texture = await PIXI.Assets.load({
src: '/assets/gui/frame_01.png', src: '/assets/gui/frame_01.png',
}); });
Assets.Frame02Texture = await PIXI.Assets.load({ GameAssets.Frame02Texture = await PIXI.Assets.load({
src: '/assets/gui/frame_02.png', src: '/assets/gui/frame_02.png',
}); });
Assets.FrameGreenTexture = await PIXI.Assets.load({ GameAssets.FrameGreenTexture = await PIXI.Assets.load({
src: '/assets/gui/frame_green.png', src: '/assets/gui/frame_green.png',
}); });
Assets.FrameRedTexture = await PIXI.Assets.load({ GameAssets.FrameRedTexture = await PIXI.Assets.load({
src: '/assets/gui/frame_red.png', src: '/assets/gui/frame_red.png',
}); });
Assets.FrameVioletTexture = await PIXI.Assets.load({ GameAssets.FrameVioletTexture = await PIXI.Assets.load({
src: '/assets/gui/frame_violet.png', src: '/assets/gui/frame_violet.png',
}); });
Assets.HealthTexture = await PIXI.Assets.load({ GameAssets.HealthTexture = await PIXI.Assets.load({
src: '/assets/gui/heart.png', src: '/assets/gui/heart.png',
}); });
Assets.GoldTexture = await PIXI.Assets.load({ GameAssets.GoldTexture = await PIXI.Assets.load({
src: '/assets/gui/star.png', src: '/assets/gui/star.png',
}); });
Assets.BasicCreepTexture = await PIXI.Assets.load({ GameAssets.BasicCreepTexture = await PIXI.Assets.load({
src: '/assets/creeps/basic.jpg', src: '/assets/creeps/basic.jpg',
}); });
await this.LoadMissions(); await this.LoadMissions();
await this.LoadTowers(); await this.LoadTowers();
await this.LoadCreepStats(); await this.LoadCreepStats();
text.destroy();
} }
public static async LoadCreepStats() { public static async LoadCreepStats() {
@ -46,13 +59,13 @@ export default class Assets {
} }
private static async LoadMissions() { private static async LoadMissions() {
Assets.Missions = [await this.LoadMission('/assets/missions/mission_01.json')]; GameAssets.Missions = [await this.LoadMission('/assets/missions/mission_01.json')];
} }
private static async LoadTowers() { private static async LoadTowers() {
const res = await fetch('/assets/Towers.json'); const res = await fetch('/assets/Towers.json');
const towers = await res.json(); const towers = await res.json();
Assets.Towers = towers; GameAssets.Towers = towers;
} }
private static async LoadMission(missionUrl: string) { private static async LoadMission(missionUrl: string) {

View File

@ -2,13 +2,15 @@ import * as PIXI from 'pixi.js';
import GameObject from './GameObject'; import GameObject from './GameObject';
import GuiObject from './GuiObject'; import GuiObject from './GuiObject';
import Scene from '../scenes/Scene'; import Scene from '../scenes/Scene';
import { Grid } from './game/Grid';
export class environment { export class Globals {
public static app: PIXI.Application; public static app: PIXI.Application;
public static GameMaster: GameMaster; public static GameMaster: GameMaster;
public static WindowHeight: number; public static WindowHeight: number;
public static WindowWidth: number; public static WindowWidth: number;
public static AspectRatio: number = 4 / 3; public static AspectRatio: number = 16 / 9;
public static Grid: Grid;
} }
export default class GameMaster { export default class GameMaster {
@ -17,7 +19,7 @@ export default class GameMaster {
private ticker: PIXI.Ticker; private ticker: PIXI.Ticker;
constructor() { constructor() {
environment.GameMaster = this; Globals.GameMaster = this;
this.ticker = new PIXI.Ticker(); this.ticker = new PIXI.Ticker();
this.ticker.maxFPS = 60; this.ticker.maxFPS = 60;
this.ticker.minFPS = 30; this.ticker.minFPS = 30;
@ -26,22 +28,24 @@ export default class GameMaster {
public _CreateGameObject(object: GameObject) { public _CreateGameObject(object: GameObject) {
this.GameObjects.push(object); this.GameObjects.push(object);
environment.app.stage.addChild(object.container);
} }
public _RemoveGameObject(object: GameObject) { public _RemoveGameObject(object: GameObject) {
this.GameObjects.splice(this.GameObjects.indexOf(object), 1); this.GameObjects.splice(this.GameObjects.indexOf(object), 1);
environment.app.stage.removeChild(object.container); }
public GetGameObjectByName(name: string) {
return this.GameObjects.filter((obj) => obj.name == name);
} }
public _CreateGuiObject(object: GuiObject) { public _CreateGuiObject(object: GuiObject) {
this.currentScene.gui.push(object); this.currentScene.gui.push(object);
environment.app.stage.addChild(object.container); Globals.app.stage.addChild(object.container);
} }
public _RemoveGuiObject(object: GuiObject) { public _RemoveGuiObject(object: GuiObject) {
this.currentScene.gui.splice(this.currentScene.gui.indexOf(object), 1); this.currentScene.gui.splice(this.currentScene.gui.indexOf(object), 1);
environment.app.stage.removeChild(object.container); Globals.app.stage.removeChild(object.container);
} }
public changeScene(newScene: Scene) { public changeScene(newScene: Scene) {

View File

@ -1,15 +1,18 @@
import * as PIXI from 'pixi.js'; import * as PIXI from 'pixi.js';
import { environment } from './Bastion'; import { Globals } from './Bastion';
export default abstract class GameObject { export default abstract class GameObject {
public readonly name: string = this.constructor.name; public readonly name: string = this.constructor.name;
protected _container: PIXI.Container = new PIXI.Container(); protected _container: PIXI.Container = new PIXI.Container();
// bb = bounding box
protected bb: PIXI.Rectangle = new PIXI.Rectangle();
protected _events: PIXI.EventEmitter = new PIXI.EventEmitter(); protected _events: PIXI.EventEmitter = new PIXI.EventEmitter();
public destroy() { public destroy() {
environment.GameMaster._RemoveGameObject(this); Globals.GameMaster._RemoveGameObject(this);
this._events.removeAllListeners(); this._events.removeAllListeners();
if (this._container.parent) this._container.parent.removeChild(this._container); if (this._container.parent) this._container.parent.removeChild(this._container);
this._container.destroy(); this._container.destroy();
@ -24,8 +27,4 @@ export default abstract class GameObject {
} }
public abstract update(elapsedMS): void; public abstract update(elapsedMS): void;
constructor() {
environment.GameMaster._CreateGameObject(this);
}
} }

View File

@ -1,5 +1,5 @@
import * as PIXI from 'pixi.js'; import * as PIXI from 'pixi.js';
import { environment } from './Bastion'; import { Globals } from './Bastion';
export default abstract class GuiObject { export default abstract class GuiObject {
public readonly name: string = this.constructor.name; public readonly name: string = this.constructor.name;
@ -37,7 +37,7 @@ export default abstract class GuiObject {
} }
constructor(interactive?: boolean) { constructor(interactive?: boolean) {
environment.GameMaster._CreateGuiObject(this); Globals.GameMaster._CreateGuiObject(this);
if (!interactive) return; if (!interactive) return;
this._container.interactive = true; this._container.interactive = true;
this._container.onwheel = (e) => { this._container.onwheel = (e) => {

105
src/classes/game/Grid.ts Normal file
View File

@ -0,0 +1,105 @@
import * as PIXI from 'pixi.js';
import GameObject from '../GameObject';
import { GameMapDefinition, TerrainType } from '../Definitions';
// import Creep, { CreepEvents } from './Creep';
import GameAssets from '../Assets';
import { Viewport } from 'pixi-viewport';
import { Globals } from '../Bastion';
export class Cell extends GameObject {
public type: TerrainType;
public row: number;
public column: number;
public isPath: boolean = false;
constructor(type: TerrainType, row: number, column: number, isPath: boolean) {
super();
this.type = type;
this.row = row;
this.column = column;
this.isPath = isPath;
// this.bb.x = parseFloat(environment.Grid.gridUnitsToPixels(this.column).toFixed(2));
// this.bb.y = parseFloat(environment.Grid.gridUnitsToPixels(this.row).toFixed(2));
if (column == 24 || column == 23) console.log(`col ${column} ` + Globals.Grid.gridUnitsToPixels(this.column));
this.bb.x = Globals.Grid.gridUnitsToPixels(this.column);
this.bb.y = Globals.Grid.gridUnitsToPixels(this.row);
this.bb.width = Globals.Grid.gridUnitsToPixels(1);
this.bb.height = Globals.Grid.gridUnitsToPixels(1);
Globals.Grid.container.addChild(this.container);
Globals.GameMaster._CreateGameObject(this);
let g = new PIXI.Graphics();
g.rect(0, 0, this.bb.width, this.bb.height);
switch (this.type) {
case TerrainType.Restricted:
g.fill(0xff0000);
break;
case TerrainType.Path:
g.fill(0xff00ff);
break;
case TerrainType.Buildable:
g.stroke(0x00ff00);
break;
}
this.container.addChild(g);
this.container.x = this.bb.x;
this.container.y = this.bb.y;
if (!GameAssets.DebuggingEnabled) return;
const text = new PIXI.Text({
text: `${this.row}|${this.column}`,
style: new PIXI.TextStyle({
fill: 0xffffff,
dropShadow: true,
fontSize: 16,
}),
});
this.container.addChild(text);
text.anchor.set(0.5, 0.5);
text.x = this.bb.width / 2;
text.y = this.bb.height / 2;
if (this.isPath) text.text += 'P';
}
public update() {}
}
export class Grid extends GameObject {
private gameMap: GameMapDefinition;
private cells: Cell[] = [];
// public creeps: Creep[] = [];
constructor(map: GameMapDefinition, missionIndex) {
super();
this.gameMap = map;
Globals.Grid = this;
this.container.isRenderGroup = true;
this.bb.x = 0;
this.bb.y = 110;
this.bb.width = Globals.WindowWidth - 360;
this.bb.height = Globals.WindowHeight - 110;
Globals.app.stage.addChild(this.container);
Globals.GameMaster._CreateGameObject(this);
let background = new PIXI.Sprite(GameAssets.MissionBackgrounds[missionIndex]);
background.x = 0;
background.y = 0;
this.bb.width = this.gridUnitsToPixels(1) * this.gameMap.columns;
this.bb.height = this.gridUnitsToPixels(1) * this.gameMap.rows;
background.width = this.bb.width;
background.height = this.bb.height;
this.container.addChild(background);
}
public update() {}
private getPixelScalingFactor() {
const pixelScaleX = this.bb.width / this.gameMap.columns;
const pixelScaleY = this.bb.height / this.gameMap.rows;
return pixelScaleX < pixelScaleY ? pixelScaleX : pixelScaleY;
}
public gridUnitsToPixels(amount: number): number {
return amount * this.getPixelScalingFactor();
}
public pixelsToGridUnits(pixels: number): number {
return pixels / this.getPixelScalingFactor();
}
}

View File

@ -1,6 +1,6 @@
import * as PIXI from 'pixi.js'; import * as PIXI from 'pixi.js';
import GuiObject from '../GuiObject'; import GuiObject from '../GuiObject';
import Assets from '../Assets'; import GameAssets from '../Assets';
export default class Sidebar extends GuiObject { export default class Sidebar extends GuiObject {
private bounds: PIXI.Rectangle; private bounds: PIXI.Rectangle;
@ -11,10 +11,8 @@ export default class Sidebar extends GuiObject {
this.bounds = bounds; this.bounds = bounds;
this.container.x = this.bounds.x; this.container.x = this.bounds.x;
this.container.y = this.bounds.y; this.container.y = this.bounds.y;
this.container.width = this.bounds.width;
this.container.height = this.bounds.height;
this.sidebarSprite = new PIXI.NineSliceSprite({ this.sidebarSprite = new PIXI.NineSliceSprite({
texture: Assets.Frame01Texture, texture: GameAssets.Frame01Texture,
leftWidth: 100, leftWidth: 100,
topHeight: 100, topHeight: 100,
rightWidth: 100, rightWidth: 100,

View File

@ -1,29 +0,0 @@
import * as PIXI from 'pixi.js';
import GuiObject from '../GuiObject';
import Assets from '../Assets';
export default class Topbar extends GuiObject {
private bounds: PIXI.Rectangle;
private sidebarSprite: PIXI.NineSliceSprite;
constructor(bounds: PIXI.Rectangle) {
super(false);
this.bounds = bounds;
this.container.x = this.bounds.x;
this.container.y = this.bounds.y;
this.container.width = this.bounds.width;
this.container.height = this.bounds.height;
this.sidebarSprite = new PIXI.NineSliceSprite({
texture: Assets.Frame01Texture,
leftWidth: 100,
topHeight: 100,
rightWidth: 100,
bottomHeight: 100,
});
this.sidebarSprite.x = -40;
this.sidebarSprite.y = -40;
this.sidebarSprite.width = this.bounds.width + 40;
this.sidebarSprite.height = this.bounds.height;
this.container.addChild(this.sidebarSprite);
}
}

View File

@ -1,39 +1,36 @@
import * as PIXI from 'pixi.js'; import * as PIXI from 'pixi.js';
import GameMaster, { environment } from './classes/Bastion'; import GameMaster, { Globals } from './classes/Bastion';
import Assets from './classes/Assets'; import Assets from './classes/Assets';
import { MainScene } from './scenes/Main'; import { MainScene } from './scenes/Main';
import { GameScene } from './scenes/Game'; import { GameScene } from './scenes/Game';
(async () => { (async () => {
const app = new PIXI.Application(); const app = new PIXI.Application();
const aspectRatio = environment.AspectRatio; const aspectRatio = Globals.AspectRatio;
const maxWidth = window.innerWidth; const maxWidth = window.innerWidth;
const maxHeight = window.innerHeight; const maxHeight = window.innerHeight;
const width = Math.min(maxWidth * 0.75, maxHeight * aspectRatio); const width = Math.min(maxWidth * 0.75, maxHeight * aspectRatio);
const height = width / aspectRatio; const height = width / aspectRatio;
environment.WindowWidth = width; Globals.app = app;
environment.WindowHeight = height;
environment.app = app;
await app.init({ await app.init({
width: width, width: maxWidth,
height: height, height: maxHeight,
backgroundColor: 'gray', backgroundColor: 'black',
sharedTicker: true, sharedTicker: true,
preference: 'webgl', preference: 'webgl',
}); });
const screenRatio = maxWidth / maxHeight;
const scale = screenRatio < aspectRatio ? maxWidth / width : maxHeight / height;
app.stage.scale.x = scale;
app.stage.scale.y = scale;
Globals.WindowWidth = maxWidth / scale;
Globals.WindowHeight = maxHeight / scale;
document.body.appendChild(app.canvas); document.body.appendChild(app.canvas);
await Assets.LoadAssets(); await Assets.LoadAssets();
new GameMaster(); new GameMaster();
environment.GameMaster.changeScene(new MainScene()); Globals.GameMaster.changeScene(new MainScene());
let params = new URLSearchParams(location.href); let params = new URLSearchParams(location.href);
if (params.entries().next().value[1] == 'game') environment.GameMaster.changeScene(new GameScene('Mission 1')); if (params.entries().next().value[1] == 'game') Globals.GameMaster.changeScene(new GameScene('Mission 1'));
window.addEventListener('resize', () => {
const newWidth = Math.min(window.innerWidth * 0.75, window.innerHeight * aspectRatio);
const newHeight = newWidth / aspectRatio;
environment.WindowWidth = newWidth;
environment.WindowHeight = newHeight;
app.renderer.resize(newWidth, newHeight);
});
})(); })();

View File

@ -1,24 +1,27 @@
import Assets from '../classes/Assets'; import GameAssets from '../classes/Assets';
import { environment } from '../classes/Bastion'; import { Globals } from '../classes/Bastion';
import { MissionDefinition } from '../classes/Definitions'; import { MissionDefinition } from '../classes/Definitions';
import { Grid } from '../classes/game/Grid';
import Sidebar from '../classes/gui/Sidebar'; import Sidebar from '../classes/gui/Sidebar';
import Topbar from '../classes/gui/Topbar';
import Scene from './Scene'; import Scene from './Scene';
import * as PIXI from 'pixi.js'; import * as PIXI from 'pixi.js';
export class GameScene extends Scene { export class GameScene extends Scene {
public mission: MissionDefinition; public mission: MissionDefinition;
public missionIndex: number;
constructor(name: string) { constructor(name: string) {
super(); super();
Assets.Missions.forEach((mission) => { GameAssets.Missions.forEach((mission, index) => {
if (mission.name == name) this.mission = mission; if (mission.name == name) {
this.mission = mission;
this.missionIndex = index;
}
}); });
} }
public init() { public init() {
const SidebarRect = new PIXI.Rectangle(environment.WindowWidth - 400, 0, 400, environment.WindowHeight); const SidebarRect = new PIXI.Rectangle(Globals.WindowWidth - 400, 0, 400, Globals.WindowHeight);
const TopbarRect = new PIXI.Rectangle(0, 0, environment.WindowWidth, 150);
new Topbar(TopbarRect);
new Sidebar(SidebarRect); new Sidebar(SidebarRect);
new Grid(this.mission.gameMap, this.missionIndex);
} }
} }

View File

@ -1,4 +1,4 @@
import { environment } from '../classes/Bastion'; import { Globals } from '../classes/Bastion';
import Button, { ButtonTexture } from '../classes/gui/Button'; import Button, { ButtonTexture } from '../classes/gui/Button';
import { MissionPickerScene } from './MissionPicker'; import { MissionPickerScene } from './MissionPicker';
import Scene from './Scene'; import Scene from './Scene';
@ -8,19 +8,19 @@ export class MainScene extends Scene {
public init() { public init() {
const NewGameButton = { const NewGameButton = {
caption: 'New Game', caption: 'New Game',
rect: new PIXI.Rectangle(environment.WindowWidth / 2 - 300 / 2, environment.WindowHeight / 2 - 80, 300, 60), rect: new PIXI.Rectangle(Globals.WindowWidth / 2 - 300 / 2, Globals.WindowHeight / 2 - 80, 300, 60),
texture: ButtonTexture.Button01, texture: ButtonTexture.Button01,
}; };
const SettingsButton = { const SettingsButton = {
caption: 'Settings', caption: 'Settings',
rect: new PIXI.Rectangle(environment.WindowWidth / 2 - 300 / 2, environment.WindowHeight / 2 + 20, 300, 60), rect: new PIXI.Rectangle(Globals.WindowWidth / 2 - 300 / 2, Globals.WindowHeight / 2 + 20, 300, 60),
texture: ButtonTexture.Button01, texture: ButtonTexture.Button01,
}; };
const button01 = new Button(NewGameButton.rect, NewGameButton.caption, NewGameButton.texture, true); const button01 = new Button(NewGameButton.rect, NewGameButton.caption, NewGameButton.texture, true);
button01.onClick = (e) => { button01.onClick = (e) => {
environment.GameMaster.changeScene(new MissionPickerScene()); Globals.GameMaster.changeScene(new MissionPickerScene());
}; };
new Button(SettingsButton.rect, SettingsButton.caption, SettingsButton.texture, true); new Button(SettingsButton.rect, SettingsButton.caption, SettingsButton.texture, true);

View File

@ -1,5 +1,5 @@
import Assets from '../classes/Assets'; import Assets from '../classes/Assets';
import { environment } from '../classes/Bastion'; import { Globals } from '../classes/Bastion';
import Button, { ButtonTexture } from '../classes/gui/Button'; import Button, { ButtonTexture } from '../classes/gui/Button';
import { GameScene } from './Game'; import { GameScene } from './Game';
import Scene from './Scene'; import Scene from './Scene';
@ -9,17 +9,12 @@ export class MissionPickerScene extends Scene {
public init() { public init() {
Assets.Missions.forEach((mission, index) => { Assets.Missions.forEach((mission, index) => {
const button = new Button( const button = new Button(
new PIXI.Rectangle( new PIXI.Rectangle(Globals.WindowWidth / 2 - 300 / 2, Globals.WindowHeight / 5 + index * 80, 300, 60),
environment.WindowWidth / 2 - 300 / 2,
environment.WindowHeight / 5 + index * 80,
300,
60
),
mission.name, mission.name,
ButtonTexture.Button01 ButtonTexture.Button01
); );
button.onClick = (e) => { button.onClick = (e) => {
environment.GameMaster.changeScene(new GameScene(mission.name)); Globals.GameMaster.changeScene(new GameScene(mission.name));
}; };
}); });
} }

View File

@ -10,6 +10,9 @@ export default class Scene {
public GetGuiObject(object: GuiObject) { public GetGuiObject(object: GuiObject) {
return this.gui.find((obj) => obj == object); return this.gui.find((obj) => obj == object);
} }
public GetGuiObjectByName(name: string) {
return this.gui.filter((obj) => obj.name == name);
}
public init() { public init() {
// Definitions for scene elements. // Definitions for scene elements.
} }