different UI for player inspection and adventure planning
also tons of tiny linter changes I guess
BIN
Assets/AdventureButtons.aseprite
Normal file
BIN
Assets/ExampleFace.aseprite
Normal file
BIN
Assets/Sprite-0001.aseprite
Normal file
1
Credits.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
Fonts by Chevy Ray (licensed) https://chevyray.itch.io/pixel-fonts
|
||||
99
Program/assets/AdventureButtons.json
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
{ "frames": {
|
||||
"Clear": {
|
||||
"frame": { "x": 0, "y": 0, "w": 18, "h": 18 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 18, "h": 18 },
|
||||
"sourceSize": { "w": 18, "h": 18 },
|
||||
"duration": 100
|
||||
},
|
||||
"New": {
|
||||
"frame": { "x": 18, "y": 0, "w": 18, "h": 18 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 18, "h": 18 },
|
||||
"sourceSize": { "w": 18, "h": 18 },
|
||||
"duration": 100
|
||||
},
|
||||
"People": {
|
||||
"frame": { "x": 36, "y": 0, "w": 18, "h": 18 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 18, "h": 18 },
|
||||
"sourceSize": { "w": 18, "h": 18 },
|
||||
"duration": 100
|
||||
},
|
||||
"Dir": {
|
||||
"frame": { "x": 54, "y": 0, "w": 18, "h": 18 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 18, "h": 18 },
|
||||
"sourceSize": { "w": 18, "h": 18 },
|
||||
"duration": 100
|
||||
},
|
||||
"Items": {
|
||||
"frame": { "x": 72, "y": 0, "w": 18, "h": 18 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 18, "h": 18 },
|
||||
"sourceSize": { "w": 18, "h": 18 },
|
||||
"duration": 100
|
||||
},
|
||||
"Go": {
|
||||
"frame": { "x": 90, "y": 0, "w": 18, "h": 18 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 18, "h": 18 },
|
||||
"sourceSize": { "w": 18, "h": 18 },
|
||||
"duration": 100
|
||||
},
|
||||
"": {
|
||||
"frame": { "x": 108, "y": 0, "w": 18, "h": 18 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 18, "h": 18 },
|
||||
"sourceSize": { "w": 18, "h": 18 },
|
||||
"duration": 100
|
||||
},
|
||||
"": {
|
||||
"frame": { "x": 126, "y": 0, "w": 18, "h": 18 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 18, "h": 18 },
|
||||
"sourceSize": { "w": 18, "h": 18 },
|
||||
"duration": 100
|
||||
},
|
||||
"": {
|
||||
"frame": { "x": 144, "y": 0, "w": 18, "h": 18 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 18, "h": 18 },
|
||||
"sourceSize": { "w": 18, "h": 18 },
|
||||
"duration": 100
|
||||
},
|
||||
"": {
|
||||
"frame": { "x": 162, "y": 0, "w": 18, "h": 18 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 18, "h": 18 },
|
||||
"sourceSize": { "w": 18, "h": 18 },
|
||||
"duration": 100
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"app": "http://www.aseprite.org/",
|
||||
"version": "1.2.17-x64",
|
||||
"image": "AdventureButtons.png",
|
||||
"format": "RGBA8888",
|
||||
"size": { "w": 180, "h": 18 },
|
||||
"scale": "1",
|
||||
"frameTags": [
|
||||
{ "name": "Clear", "from": 0, "to": 0, "direction": "forward" },
|
||||
{ "name": "New", "from": 1, "to": 1, "direction": "forward" },
|
||||
{ "name": "People", "from": 2, "to": 2, "direction": "forward" },
|
||||
{ "name": "Dir", "from": 3, "to": 3, "direction": "forward" },
|
||||
{ "name": "Items", "from": 4, "to": 4, "direction": "forward" },
|
||||
{ "name": "Go", "from": 5, "to": 5, "direction": "forward" }
|
||||
]
|
||||
}
|
||||
}
|
||||
BIN
Program/assets/AdventureButtons.png
Normal file
|
After Width: | Height: | Size: 536 B |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
|
@ -1,20 +1,20 @@
|
|||
{ "frames": [
|
||||
{
|
||||
"filename": "Door 0",
|
||||
"frame": { "x": 0, "y": 0, "w": 21, "h": 23 },
|
||||
"frame": { "x": 0, "y": 0, "w": 42, "h": 46 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 21, "h": 23 },
|
||||
"sourceSize": { "w": 21, "h": 23 },
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 42, "h": 46 },
|
||||
"sourceSize": { "w": 42, "h": 46 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "Door 1",
|
||||
"frame": { "x": 21, "y": 0, "w": 21, "h": 23 },
|
||||
"frame": { "x": 42, "y": 0, "w": 42, "h": 46 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 21, "h": 23 },
|
||||
"sourceSize": { "w": 21, "h": 23 },
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 42, "h": 46 },
|
||||
"sourceSize": { "w": 42, "h": 46 },
|
||||
"duration": 100
|
||||
}
|
||||
],
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
"version": "1.2.16.3-x64",
|
||||
"image": "Door.png",
|
||||
"format": "RGBA8888",
|
||||
"size": { "w": 42, "h": 23 },
|
||||
"size": { "w": 84, "h": 46 },
|
||||
"scale": "1",
|
||||
"frameTags": [
|
||||
],
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 409 B After Width: | Height: | Size: 696 B |
BIN
Program/assets/ExampleFace.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 278 B After Width: | Height: | Size: 529 B |
|
|
@ -4,16 +4,16 @@
|
|||
"build": "rm -rf dist && webpack --config ./webpack.config.js --mode production --progress --colors"
|
||||
},
|
||||
"dependencies": {
|
||||
"ecsy": "^0.2.2",
|
||||
"ecsy": "^0.2.3",
|
||||
"pixi.js": "^5.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"circular-dependency-plugin": "^5.2.0",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"ts-loader": "^6.2.1",
|
||||
"typescript": "^3.7.5",
|
||||
"webpack": "^4.41.5",
|
||||
"webpack-cli": "^3.3.10",
|
||||
"webpack-dev-server": "^3.10.2",
|
||||
"circular-dependency-plugin": "^5.2.0"
|
||||
"webpack-dev-server": "^3.10.2"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,18 +2,15 @@ import { Component, Entity } from "ecsy"
|
|||
|
||||
// Door component
|
||||
export class Adventure extends Component {
|
||||
members: Entity[]
|
||||
arrivalTime: Date
|
||||
|
||||
copy(values: any){
|
||||
if(values.members)
|
||||
this.members = values.members
|
||||
if(values.arrivalTime)
|
||||
this.arrivalTime = values.arrivalTime
|
||||
}
|
||||
active: boolean = false
|
||||
members: Entity[] = []
|
||||
resources: Entity[] = []
|
||||
arrivalTime: Date = null
|
||||
|
||||
reset() {
|
||||
this.members = []
|
||||
this.arrivalTime = new Date()
|
||||
this.resources = []
|
||||
this.arrivalTime = null
|
||||
this.active = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { Texture } from "pixi.js"
|
||||
import { Component } from "ecsy"
|
||||
import { Vector } from "../Datatypes/vector"
|
||||
|
||||
import { Vector } from "../Datatypes/MathTypes/vector"
|
||||
|
||||
// Door component
|
||||
export class Door extends Component {
|
||||
|
|
@ -16,10 +15,10 @@ export class Door extends Component {
|
|||
reset() {
|
||||
this.open = false
|
||||
|
||||
this.openOffset = new Vector(0,0)
|
||||
this.closedOffset = new Vector(0,0)
|
||||
this.openOffset = new Vector(0, 0)
|
||||
this.closedOffset = new Vector(0, 0)
|
||||
|
||||
this.openTex = null
|
||||
this.closedTex = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import { Component } from "ecsy"
|
||||
import { Component, Entity } from "ecsy"
|
||||
|
||||
// Door component
|
||||
export class Human extends Component {
|
||||
|
||||
diaryEntries: Entity[]
|
||||
adventureCount = 0
|
||||
|
||||
reset() {
|
||||
this.diaryEntries = []
|
||||
this.adventureCount = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
import { Component } from "ecsy";
|
||||
import { Path } from "../Datatypes/path";
|
||||
|
||||
import { Component } from "ecsy"
|
||||
import { Path } from "../Datatypes/MathTypes/path"
|
||||
|
||||
export class PathWalker extends Component {
|
||||
path: Path
|
||||
progress: number = 0
|
||||
speed: number = 10 //speed in pixels per second
|
||||
|
||||
reset(){
|
||||
reset() {
|
||||
this.path = null
|
||||
this.progress = 0
|
||||
this.speed = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Point } from "../Datatypes/point"
|
||||
import { Point } from "../Datatypes/MathTypes/point"
|
||||
import { Component } from "ecsy"
|
||||
|
||||
// Position component
|
||||
|
|
@ -7,11 +7,11 @@ export class Position extends Component {
|
|||
|
||||
//position is used so often copy is performance sensitive I assume???
|
||||
//this can crash with wrong values, but I trust my code enough to pass ONE variable
|
||||
copy(values:any){
|
||||
copy(values: any) {
|
||||
this.value = values.value
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.value = new Point(0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
import { Component } from "ecsy";
|
||||
import { Point } from "../../Datatypes/point";
|
||||
import { Component } from "ecsy"
|
||||
import { Point } from "../../Datatypes/MathTypes/point"
|
||||
|
||||
|
||||
export class DebugLine extends Component{
|
||||
color = 0xFF0000
|
||||
export class DebugLine extends Component {
|
||||
color = 0xff0000
|
||||
from: Point
|
||||
to: Point
|
||||
|
||||
reset(){
|
||||
this.color = 0xFF0000
|
||||
reset() {
|
||||
this.color = 0xff0000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
import { Component } from "ecsy";
|
||||
import { AABB } from "../../Datatypes/aabb";
|
||||
import { Component } from "ecsy"
|
||||
import { AABB } from "../../Datatypes/MathTypes/aabb"
|
||||
|
||||
|
||||
export class DebugRect extends Component{
|
||||
color = 0xFF0000
|
||||
export class DebugRect extends Component {
|
||||
color = 0xff0000
|
||||
rect: AABB
|
||||
|
||||
reset(){
|
||||
this.color = 0xFF0000
|
||||
reset() {
|
||||
this.color = 0xff0000
|
||||
this.rect = new AABB(0, 0, 0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,13 @@
|
|||
import { Texture } from "pixi.js";
|
||||
import { Component } from "ecsy";
|
||||
import { Vector } from "../../Datatypes/vector";
|
||||
import { Texture } from "pixi.js"
|
||||
import { Component } from "ecsy"
|
||||
import { Vector } from "../../Datatypes/MathTypes/vector"
|
||||
|
||||
//todo: consider making this a systemstatecomponent so system order isn't as critical for removing sprites
|
||||
export class SpriteRenderer extends Component{
|
||||
export class SpriteRenderer extends Component {
|
||||
texture = <Texture>null
|
||||
offset = new Vector(0)
|
||||
scale = 1 //todo: remove when all textures have the correct size!
|
||||
|
||||
reset() :void {
|
||||
reset(): void {
|
||||
this.texture = null
|
||||
this.offset = new Vector(0, 0)
|
||||
this.scale = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,34 +6,33 @@ import { InCabin } from "../Components/inCabin"
|
|||
export class AdventureReturnSystem extends System {
|
||||
priority = -100
|
||||
// This method will get called on every frame by default
|
||||
execute(delta : number) {
|
||||
execute(delta: number) {
|
||||
//TODO: consider only executing this every few seconds?
|
||||
let now = Date.now()
|
||||
// Iterate through all the entities on the query
|
||||
this.queries.adventures.results.forEach((entity: Entity) => {
|
||||
let adventure = entity.getComponent(Adventure)
|
||||
if(adventure.arrivalTime.getTime() < now)
|
||||
if (adventure.active && adventure.arrivalTime.getTime() < now)
|
||||
this.arriveAdventure(entity, adventure)
|
||||
})
|
||||
}
|
||||
|
||||
arriveAdventure(entity: Entity, adventure?: Adventure){
|
||||
if(!adventure)
|
||||
adventure = entity.getComponent(Adventure)
|
||||
|
||||
arriveAdventure(entity: Entity, adventure?: Adventure) {
|
||||
if (!adventure) adventure = entity.getComponent(Adventure)
|
||||
|
||||
//TODO: resource management
|
||||
|
||||
adventure.members.forEach((member: Entity) => {
|
||||
member.addComponent(InCabin)
|
||||
});
|
||||
})
|
||||
|
||||
entity.remove()
|
||||
}
|
||||
|
||||
static queries = {
|
||||
adventures: {
|
||||
components: [ Adventure ]
|
||||
components: [Adventure],
|
||||
},
|
||||
}
|
||||
queries: any
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,65 +1,61 @@
|
|||
import { System, Entity, Not } from "ecsy"
|
||||
import { PixiRepresentation } from "../Components/rendering/pixiRepresentation";
|
||||
import { Clickable } from "../Components/clickable";
|
||||
import { InitializedClickable } from "../Components/initializedClickable";
|
||||
import globals from "../globals";
|
||||
import { interaction } from "pixi.js";
|
||||
|
||||
import { PixiRepresentation } from "../Components/rendering/pixiRepresentation"
|
||||
import { Clickable } from "../Components/clickable"
|
||||
import { InitializedClickable } from "../Components/initializedClickable"
|
||||
import globals from "../globals"
|
||||
import { interaction } from "pixi.js"
|
||||
|
||||
export class ClickableSystem extends System {
|
||||
priority = 80
|
||||
|
||||
init(){
|
||||
init() {
|
||||
globals.app.stage.interactive = true
|
||||
globals.app.stage.on("click",
|
||||
(event:interaction.InteractionEvent) => {
|
||||
if(event.target == event.currentTarget)
|
||||
globals.selected.set(null)
|
||||
})
|
||||
|
||||
globals.app.stage.on("click", (event: interaction.InteractionEvent) => {
|
||||
if (event.target == event.currentTarget) globals.selected.set(null)
|
||||
})
|
||||
}
|
||||
|
||||
// This method will get called on every frame by default
|
||||
execute(delta : number) {
|
||||
execute(delta: number) {
|
||||
// Iterate through all the entities on the query
|
||||
this.queries.newClickables.results.forEach((entity: Entity) => {
|
||||
let object = entity.getComponent(PixiRepresentation).value
|
||||
let clickable = entity.getComponent(Clickable)
|
||||
object.interactive = true
|
||||
for(let action in clickable.actions){
|
||||
for (let action in clickable.actions) {
|
||||
object.on(action, clickable.actions[action])
|
||||
}
|
||||
entity.addComponent(InitializedClickable)
|
||||
});
|
||||
})
|
||||
|
||||
this.queries.changedClickables.changed.forEach((entity: Entity) => {
|
||||
let object = entity.getComponent(PixiRepresentation).value
|
||||
let clickable = entity.getComponent(Clickable)
|
||||
object.removeAllListeners()
|
||||
for(let action in clickable.actions){
|
||||
for (let action in clickable.actions) {
|
||||
object.on(action, clickable.actions[action])
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
this.queries.invisibleClickables.results.forEach((entity: Entity) => {
|
||||
//remove init clickable tag so it gets initialized again as soon as a pixirepresentation exists again
|
||||
entity.removeComponent(InitializedClickable)
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
static queries = {
|
||||
newClickables: {
|
||||
components: [ PixiRepresentation, Clickable, Not(InitializedClickable) ]
|
||||
components: [PixiRepresentation, Clickable, Not(InitializedClickable)],
|
||||
},
|
||||
changedClickables: {
|
||||
components: [ PixiRepresentation, Clickable, InitializedClickable ],
|
||||
components: [PixiRepresentation, Clickable, InitializedClickable],
|
||||
listen: {
|
||||
changed: [Clickable]
|
||||
}
|
||||
changed: [Clickable],
|
||||
},
|
||||
},
|
||||
invisibleClickables: {
|
||||
components: [ Clickable, InitializedClickable, Not(PixiRepresentation) ],
|
||||
}
|
||||
components: [InitializedClickable, Not(PixiRepresentation)],
|
||||
},
|
||||
}
|
||||
queries: any
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,23 @@
|
|||
import { System, Entity, Not } from "ecsy"
|
||||
import { Position } from "../Components/position";
|
||||
import { Door } from "../Components/door";
|
||||
import { SpriteRenderer } from "../Components/rendering/spriteRenderer";
|
||||
import { IPoint, Texture } from "pixi.js";
|
||||
import { Position } from "../Components/position"
|
||||
import { Door } from "../Components/door"
|
||||
import { SpriteRenderer } from "../Components/rendering/spriteRenderer"
|
||||
import { IPoint, Texture } from "pixi.js"
|
||||
|
||||
// MovableSystem
|
||||
export class DoorSystem extends System {
|
||||
// This method will get called on every frame by default
|
||||
execute(delta : number) {
|
||||
execute(delta: number) {
|
||||
// Iterate through all the entities on the query
|
||||
this.queries.newDoors.results.forEach((entity: Entity) => {
|
||||
let door = entity.getComponent(Door)
|
||||
|
||||
let doorOffset: IPoint = door.open ? door.openOffset : door.closedOffset
|
||||
let doorTex: Texture = door.open ? door.openTex : door.closedTex
|
||||
entity.addComponent(SpriteRenderer, <SpriteRenderer>{texture: doorTex, offset: doorOffset, scale:2})
|
||||
entity.addComponent(SpriteRenderer, <SpriteRenderer>{
|
||||
texture: doorTex,
|
||||
offset: doorOffset
|
||||
})
|
||||
})
|
||||
|
||||
this.queries.changedDoors.changed.forEach((entity: Entity) => {
|
||||
|
|
@ -28,14 +31,14 @@ export class DoorSystem extends System {
|
|||
|
||||
static queries = {
|
||||
newDoors: {
|
||||
components: [ Door, Not(SpriteRenderer)]
|
||||
components: [Door, Not(SpriteRenderer)]
|
||||
},
|
||||
changedDoors: {
|
||||
components: [ Door, Position, SpriteRenderer ],
|
||||
components: [Door, Position, SpriteRenderer],
|
||||
listen: {
|
||||
changed: [ Door ],
|
||||
changed: [Door]
|
||||
}
|
||||
}
|
||||
}
|
||||
queries: any;
|
||||
}
|
||||
queries: any
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,17 @@
|
|||
import { Container, DisplayObject, Text } from "pixi.js"
|
||||
import { AABB } from "../Datatypes/aabb"
|
||||
import { Container, DisplayObject } from "pixi.js"
|
||||
import { AABB } from "../Datatypes/MathTypes/aabb"
|
||||
import { System, Entity } from "ecsy"
|
||||
import globals from "../globals"
|
||||
import { Name } from "../Components/name"
|
||||
import { Adventure } from "../Components/adventure"
|
||||
import { InfoMenu } from "../UI/InfoMenu"
|
||||
import { PlanningMenu } from "../UI/PlanningMenu"
|
||||
|
||||
enum InfoState {
|
||||
None,
|
||||
Planning,
|
||||
Arriving,
|
||||
Info,
|
||||
}
|
||||
|
||||
// MovableSystem
|
||||
export class InfoSystem extends System {
|
||||
|
|
@ -11,32 +20,68 @@ export class InfoSystem extends System {
|
|||
root: Container
|
||||
elements: { [id: string]: DisplayObject } = {}
|
||||
|
||||
state = InfoState.Info
|
||||
creatingAdventure: Entity
|
||||
|
||||
infoMenu: InfoMenu
|
||||
planningMenu: PlanningMenu
|
||||
arrivalMenu: Container
|
||||
|
||||
init() {
|
||||
//todo: make this more flexible for other resolutions
|
||||
let bounds = new AABB(0, 162, 162, 126)
|
||||
|
||||
this.root = globals.app.stage.addChild(new Container())
|
||||
this.root.position = bounds.min()
|
||||
|
||||
let name = new Text("Name: ", {
|
||||
fontFamily: "babyblocks",
|
||||
fontSize: 8,
|
||||
fill: 0xffffff
|
||||
})
|
||||
name.x = 1
|
||||
this.root.addChild(name)
|
||||
this.elements.name = name
|
||||
this.infoMenu = new InfoMenu(this)
|
||||
this.planningMenu = new PlanningMenu(this)
|
||||
this.root.addChild(this.infoMenu, this.planningMenu)
|
||||
|
||||
globals.selected.onChange(selected => this.select(selected))
|
||||
globals.selected.onChange((selected) => this.select(selected))
|
||||
|
||||
this.infoMenu.visible = true
|
||||
}
|
||||
|
||||
setState(newState: InfoState) {
|
||||
let previousStateMenu = this.getStateMenu(this.state)
|
||||
let nextStateMenu = this.getStateMenu(newState)
|
||||
if (previousStateMenu) previousStateMenu.visible = false
|
||||
if (nextStateMenu) nextStateMenu.visible = true
|
||||
this.state = newState
|
||||
}
|
||||
|
||||
getStateMenu(state: InfoState): Container {
|
||||
switch (state) {
|
||||
case InfoState.Info:
|
||||
return this.infoMenu
|
||||
case InfoState.Planning:
|
||||
return this.planningMenu
|
||||
case InfoState.Arriving:
|
||||
return this.arrivalMenu
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
createAdventure() {
|
||||
let adventureEntity = globals.world.createEntity().addComponent(Adventure)
|
||||
this.creatingAdventure = adventureEntity
|
||||
this.setState(InfoState.Planning)
|
||||
}
|
||||
|
||||
abortPlans() {
|
||||
this.creatingAdventure.remove()
|
||||
this.setState(InfoState.Info)
|
||||
}
|
||||
|
||||
select(entity: Entity) {
|
||||
; (this.elements.name as Text).text = `Name: ${entity
|
||||
?.getComponent(Name)
|
||||
?.fullName() || "-"}`
|
||||
if (this.state === InfoState.Info) {
|
||||
this.infoMenu.select(entity)
|
||||
}
|
||||
if (this.state === InfoState.Planning) {
|
||||
}
|
||||
}
|
||||
|
||||
execute(delta: number) { }
|
||||
execute(delta: number) {}
|
||||
|
||||
static queries = {}
|
||||
queries: any
|
||||
|
|
|
|||
|
|
@ -1,28 +1,27 @@
|
|||
import { System, Entity, Not } from "ecsy"
|
||||
import { PathWalker } from "../Components/pathWalker"
|
||||
import { Position } from "../Components/position";
|
||||
import { WalkRandomly } from "../Components/walkRandomly";
|
||||
import { roomBounds } from "../constants";
|
||||
import { Path } from "../Datatypes/path";
|
||||
|
||||
import { Position } from "../Components/position"
|
||||
import { WalkRandomly } from "../Components/walkRandomly"
|
||||
import { roomBounds } from "../constants"
|
||||
import { Path } from "../Datatypes/MathTypes/path"
|
||||
|
||||
export class RandomWalkSystem extends System {
|
||||
priority = 0
|
||||
// This method will get called on every frame by default
|
||||
execute(delta : number) {
|
||||
execute(delta: number) {
|
||||
// Iterate through all the entities on the query
|
||||
this.queries.walkers.results.forEach((entity: Entity) => {
|
||||
var pos = entity.getComponent(Position).value
|
||||
var target = roomBounds.randomPoint()
|
||||
var path = new Path(pos, target)
|
||||
entity.addComponent(PathWalker, <PathWalker>{path: path, speed: 10})
|
||||
});
|
||||
entity.addComponent(PathWalker, <PathWalker>{ path: path, speed: 10 })
|
||||
})
|
||||
}
|
||||
|
||||
static queries = {
|
||||
walkers: {
|
||||
components: [ WalkRandomly, Position, Not(PathWalker) ]
|
||||
}
|
||||
components: [WalkRandomly, Position, Not(PathWalker)],
|
||||
},
|
||||
}
|
||||
queries: any
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +1,50 @@
|
|||
import { Human } from "../Components/human";
|
||||
import { Name } from "../Components/name";
|
||||
import { Appearance } from "../Components/appearance";
|
||||
import { Loader } from "pixi.js";
|
||||
import { InCabin } from "../Components/inCabin";
|
||||
import { Position } from "../Components/position";
|
||||
import { OrderZ } from "../Components/rendering/orderZ";
|
||||
import { AABB } from "../Datatypes/aabb";
|
||||
import { System, Entity } from "ecsy";
|
||||
import globals from "../globals";
|
||||
import { Human } from "../Components/human"
|
||||
import { Name } from "../Components/name"
|
||||
import { Appearance } from "../Components/appearance"
|
||||
import { Loader } from "pixi.js"
|
||||
import { InCabin } from "../Components/inCabin"
|
||||
import { Position } from "../Components/position"
|
||||
import { OrderZ } from "../Components/rendering/orderZ"
|
||||
import { AABB } from "../Datatypes/MathTypes/aabb"
|
||||
import { System, Entity } from "ecsy"
|
||||
import globals from "../globals"
|
||||
|
||||
// MovableSystem
|
||||
export class TestSystem extends System {
|
||||
priority = -100
|
||||
// This method will get called on every frame by default
|
||||
execute(delta : number) {
|
||||
execute(delta: number) {
|
||||
//this.removeHumans(this.queries.humans, 2)
|
||||
//this.addHumans(2)
|
||||
}
|
||||
|
||||
removeHumans(query: {results: Entity[]}, amount: number): void{
|
||||
for(let i=0;i<amount;i++){
|
||||
removeHumans(query: { results: Entity[] }, amount: number): void {
|
||||
for (let i = 0; i < amount; i++) {
|
||||
let ent = query.results[i]
|
||||
ent.remove()
|
||||
}
|
||||
}
|
||||
addHumans(amount: number): void{
|
||||
addHumans(amount: number): void {
|
||||
let roomBounds = new AABB(10, 17, 62, 56)
|
||||
let resources = Loader.shared.resources
|
||||
for(let i=0;i<amount;i++){
|
||||
globals.world.createEntity()
|
||||
for (let i = 0; i < amount; i++) {
|
||||
globals.world
|
||||
.createEntity()
|
||||
.addComponent(Human)
|
||||
.addComponent(Name, <Name>{first: "Sarah", last:"Lee"})
|
||||
.addComponent(Appearance, <Appearance>{idleTexture: resources["Human"].texture}) //Todo: generate appearance from body traits instead?
|
||||
.addComponent(Name, <Name>{ first: "Sarah", last: "Lee" })
|
||||
.addComponent(Appearance, <Appearance>{
|
||||
idleTexture: resources["Human"].texture,
|
||||
}) //Todo: generate appearance from body traits instead?
|
||||
.addComponent(InCabin)
|
||||
.addComponent(Position, <Position>{value: roomBounds.randomPoint()})
|
||||
.addComponent(Position, <Position>{ value: roomBounds.randomPoint() })
|
||||
.addComponent(OrderZ)
|
||||
}
|
||||
}
|
||||
|
||||
static queries = {
|
||||
humans: {
|
||||
components: [ Human ]
|
||||
components: [Human],
|
||||
},
|
||||
}
|
||||
queries: any;
|
||||
}
|
||||
queries: any
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { Appearance } from "../Components/appearance"
|
|||
import { InCabin } from "../Components/inCabin"
|
||||
import { Position } from "../Components/position"
|
||||
import { SpriteRenderer } from "../Components/rendering/spriteRenderer"
|
||||
import { Vector } from "../Datatypes/vector"
|
||||
import { Vector } from "../Datatypes/MathTypes/vector"
|
||||
|
||||
// MovableSystem
|
||||
export class VisibleHumanSystem extends System {
|
||||
|
|
@ -17,7 +17,6 @@ export class VisibleHumanSystem extends System {
|
|||
entity.addComponent(SpriteRenderer, <SpriteRenderer>{
|
||||
texture: texture,
|
||||
offset: new Vector(-texture.width / 2, -texture.height),
|
||||
scale: 2
|
||||
})
|
||||
})
|
||||
//update sprite texture
|
||||
|
|
@ -29,14 +28,14 @@ export class VisibleHumanSystem extends System {
|
|||
|
||||
static queries = {
|
||||
newHumans: {
|
||||
components: [Human, Appearance, InCabin, Position, Not(SpriteRenderer)]
|
||||
components: [Human, Appearance, InCabin, Position, Not(SpriteRenderer)],
|
||||
},
|
||||
visibleHumans: {
|
||||
components: [Human, Appearance, InCabin, Position, SpriteRenderer],
|
||||
listen: {
|
||||
changed: [Appearance]
|
||||
}
|
||||
}
|
||||
changed: [Appearance],
|
||||
},
|
||||
},
|
||||
}
|
||||
queries: any
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import { Sprite, DisplayObject } from "pixi.js"
|
|||
import { PixiRepresentation } from "../../Components/rendering/pixiRepresentation"
|
||||
import { addOrSetComponent } from "../../util"
|
||||
import globals from "../../globals"
|
||||
import { Point } from "../../Datatypes/point"
|
||||
|
||||
// MovableSystem
|
||||
export class SpriteSystem extends System {
|
||||
|
|
@ -20,8 +19,7 @@ export class SpriteSystem extends System {
|
|||
let renderer = entity.getComponent(SpriteRenderer)
|
||||
let pos = entity.getComponent(Position)
|
||||
let sprite = new Sprite(renderer.texture)
|
||||
sprite.scale = new Point(renderer.scale)
|
||||
sprite.position = pos.value.add(renderer.offset.scale(renderer.scale))
|
||||
sprite.position = pos.value.add(renderer.offset)
|
||||
globals.app.stage.addChild(sprite)
|
||||
addOrSetComponent(entity, PixiRepresentation, <PixiRepresentation>{
|
||||
value: <DisplayObject>sprite
|
||||
|
|
@ -34,7 +32,7 @@ export class SpriteSystem extends System {
|
|||
let pos = entity.getComponent(Position)
|
||||
let object = entity.getComponent(PixiRepresentation).value as Sprite
|
||||
object.texture = renderer.texture
|
||||
object.position = pos.value.add(renderer.offset.scale(renderer.scale))
|
||||
object.position = pos.value.add(renderer.offset)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
3
Program/src/UI/Button.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import { Sprite } from "pixi.js"
|
||||
|
||||
export class Button extends Sprite {}
|
||||
83
Program/src/UI/InfoMenu.ts
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
import { Container, Text, Sprite, Loader, Texture, interaction } from "pixi.js"
|
||||
|
||||
import { Point } from "../Datatypes/MathTypes/point"
|
||||
import { InfoSystem } from "../Systems/InfoSystem"
|
||||
import { Name } from "../Components/name"
|
||||
import { Entity } from "ecsy"
|
||||
|
||||
export class InfoMenu extends Container {
|
||||
system: InfoSystem
|
||||
|
||||
nameField: Text
|
||||
portrait: Sprite
|
||||
|
||||
constructor(system: InfoSystem) {
|
||||
super()
|
||||
|
||||
this.system = system
|
||||
|
||||
this.setupName()
|
||||
this.setupPortrait()
|
||||
this.setupButtons()
|
||||
|
||||
this.visible = false
|
||||
}
|
||||
|
||||
setupName() {
|
||||
let name = new Text("-", {
|
||||
fontFamily: "babyblocks",
|
||||
fontSize: 16,
|
||||
fill: 0xffffff,
|
||||
})
|
||||
name.position = new Point(64 + 2, 1)
|
||||
this.addChild(name)
|
||||
this.nameField = name
|
||||
}
|
||||
|
||||
setupPortrait() {
|
||||
let portait = new Sprite(null)
|
||||
portait.position = new Point(0, 0)
|
||||
this.addChild(portait)
|
||||
this.portrait = portait
|
||||
}
|
||||
|
||||
setupButtons() {
|
||||
let buttons = Loader.shared.resources["AdventureButtons"].textures
|
||||
let buttonDef: {
|
||||
texture: Texture
|
||||
action?: (event: interaction.InteractionEvent) => void
|
||||
context?: any
|
||||
}[] = [
|
||||
{
|
||||
texture: buttons["New"],
|
||||
action: this.system.createAdventure,
|
||||
context: this.system,
|
||||
},
|
||||
]
|
||||
|
||||
let container = new Container()
|
||||
this.addChild(container)
|
||||
container.position = new Point(0, 126 - 18)
|
||||
|
||||
for (let i = 0; i < buttonDef.length; i++) {
|
||||
let def = buttonDef[i]
|
||||
let button = new Sprite(def.texture)
|
||||
|
||||
if (def.action) {
|
||||
button.on("click", def.action, def.context)
|
||||
button.interactive = true
|
||||
}
|
||||
|
||||
container.addChild(button)
|
||||
button.position = new Point(i * 18, 0)
|
||||
}
|
||||
}
|
||||
|
||||
select(entity: Entity) {
|
||||
let name = entity?.getComponent(Name)?.fullName() || "-"
|
||||
this.nameField.text = name
|
||||
|
||||
let face = entity ? Loader.shared.resources["Face"].texture : null
|
||||
this.portrait.texture = face
|
||||
}
|
||||
}
|
||||
56
Program/src/UI/PlanningMenu.ts
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import { Container, Text, Sprite, Loader, Texture, interaction } from "pixi.js"
|
||||
|
||||
import { Point } from "../Datatypes/MathTypes/point"
|
||||
import { InfoSystem } from "../Systems/InfoSystem"
|
||||
|
||||
export class PlanningMenu extends Container {
|
||||
system: InfoSystem
|
||||
|
||||
nameField: Text
|
||||
portrait: Sprite
|
||||
|
||||
constructor(system: InfoSystem) {
|
||||
super()
|
||||
|
||||
this.system = system
|
||||
|
||||
this.setupButtons()
|
||||
this.visible = false
|
||||
}
|
||||
|
||||
setupButtons() {
|
||||
let buttons = Loader.shared.resources["AdventureButtons"].textures
|
||||
let buttonDef: {
|
||||
texture: Texture
|
||||
action?: (event: interaction.InteractionEvent) => void
|
||||
context?: any
|
||||
}[] = [
|
||||
{
|
||||
texture: buttons["Clear"],
|
||||
action: this.system.abortPlans,
|
||||
context: this.system,
|
||||
},
|
||||
{ texture: buttons["People"] },
|
||||
{ texture: buttons["Items"] },
|
||||
{ texture: buttons["Dir"] },
|
||||
{ texture: buttons["Go"] },
|
||||
{ texture: null },
|
||||
{ texture: null },
|
||||
]
|
||||
|
||||
let container = new Container()
|
||||
this.addChild(container)
|
||||
container.position = new Point(0, 126 - 18)
|
||||
|
||||
for (let i = 0; i < buttonDef.length; i++) {
|
||||
let def = buttonDef[i]
|
||||
let button = new Sprite(def.texture)
|
||||
if (def.action) {
|
||||
button.on("click", def.action, def.context)
|
||||
button.interactive = true
|
||||
}
|
||||
container.addChild(button)
|
||||
button.position = new Point(i * 18, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import { AABB } from "./Datatypes/aabb"
|
||||
import { AABB } from "./Datatypes/MathTypes/aabb"
|
||||
|
||||
export const canvasWidth = 162
|
||||
export const canvasHeight = 288
|
||||
|
||||
export const roomBounds = new AABB(19, 34, 125, 113)
|
||||
export const roomBounds = new AABB(18, 33, 127, 115)
|
||||
|
||||
export const FirstNames = ["Jules", "Levi", "Sarah", "Simon", "Ronja", "Marko"]
|
||||
|
||||
|
|
@ -33,5 +33,5 @@ export const LastNames = [
|
|||
"White",
|
||||
"Xiang",
|
||||
"Yakub",
|
||||
"Zafar"
|
||||
"Zafar",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,17 +1,16 @@
|
|||
import { Application, settings, SCALE_MODES, Ticker } from "pixi.js";
|
||||
import globals from "./globals";
|
||||
import { canvasWidth, canvasHeight } from "./constants";
|
||||
import { loadResources } from "./resources";
|
||||
import { setup } from "./setup";
|
||||
|
||||
import { Application, settings, SCALE_MODES, Ticker } from "pixi.js"
|
||||
import globals from "./globals"
|
||||
import { canvasWidth, canvasHeight } from "./constants"
|
||||
import { loadResources } from "./resources"
|
||||
import { setup } from "./setup"
|
||||
|
||||
// Initialize pixi
|
||||
globals.app = new Application({
|
||||
width: canvasWidth,
|
||||
height: canvasHeight,
|
||||
backgroundColor: 0x10101010,
|
||||
width: canvasWidth,
|
||||
height: canvasHeight,
|
||||
backgroundColor: 0x10101010,
|
||||
resolution: 1,
|
||||
antialias: false,
|
||||
antialias: false
|
||||
})
|
||||
document.body.appendChild(globals.app.view)
|
||||
|
||||
|
|
@ -20,24 +19,26 @@ settings.ROUND_PIXELS = true
|
|||
|
||||
recalculateSize()
|
||||
|
||||
window.addEventListener( 'resize', recalculateSize, false )
|
||||
window.addEventListener("resize", recalculateSize)
|
||||
|
||||
function recalculateSize(){
|
||||
let multiplier = Math.min((window.innerWidth/canvasWidth)|0, (window.innerHeight/canvasHeight)|0)
|
||||
function recalculateSize() {
|
||||
let multiplier = Math.min(
|
||||
(window.innerWidth / canvasWidth) | 0,
|
||||
(window.innerHeight / canvasHeight) | 0
|
||||
)
|
||||
globals.app.view.style.width = canvasWidth * multiplier + "px"
|
||||
globals.app.view.style.height = canvasHeight * multiplier + "px"
|
||||
}
|
||||
|
||||
|
||||
loadResources(init)
|
||||
|
||||
function init(){
|
||||
function init() {
|
||||
setup()
|
||||
|
||||
// Run!
|
||||
Ticker.shared.add((delta : number) => {
|
||||
Ticker.shared.add((delta: number) => {
|
||||
let time = performance.now()
|
||||
// Run all the systems
|
||||
globals.world.execute(delta/100, time)
|
||||
});
|
||||
globals.world.execute(delta / 100, time)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
import { Loader, } from "pixi.js"
|
||||
import { Loader } from "pixi.js"
|
||||
|
||||
|
||||
export function loadResources(init: Function){
|
||||
Loader.shared.add("Door", "assets/Door.json")
|
||||
export function loadResources(init: Function) {
|
||||
Loader.shared
|
||||
.add("Door", "assets/Door.json")
|
||||
.add("AdventureButtons", "assets/AdventureButtons.json")
|
||||
.add("Background", "assets/Background.png")
|
||||
.add("Human", "assets/Human.png")
|
||||
.add("pixelfont_fnt","assets/Fonts/Visitor2.fnt")
|
||||
.add("Face", "assets/ExampleFace.png")
|
||||
.add("pixelfont_fnt", "assets/Fonts/Visitor2.fnt")
|
||||
.load(setup)
|
||||
|
||||
function setup(loader: Loader){
|
||||
function setup(loader: Loader) {
|
||||
init()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { roomBounds } from "./constants"
|
|||
import globals from "./globals"
|
||||
import { createRandomHuman } from "./util"
|
||||
import { Position } from "./Components/position"
|
||||
import { Point } from "./Datatypes/point"
|
||||
import { Point } from "./Datatypes/MathTypes/point"
|
||||
import { World } from "ecsy"
|
||||
import { TestSystem } from "./Systems/TestSystem"
|
||||
import { AdventureReturnSystem } from "./Systems/AdventureReturnSystem"
|
||||
|
|
@ -20,7 +20,7 @@ import { DebugRenderSystem } from "./Systems/rendering/DebugRenderSystem"
|
|||
import { ZOrderSystem } from "./Systems/rendering/ZOrderSystem"
|
||||
import { PixiCleanupSystem } from "./Systems/rendering/PixiCleanupSystem"
|
||||
import { RenderSystem } from "./Systems/rendering/RenderSystem"
|
||||
import { Vector } from "./Datatypes/vector"
|
||||
import { Vector } from "./Datatypes/MathTypes/vector"
|
||||
|
||||
export function setup() {
|
||||
// Create world and register the systems on it
|
||||
|
|
@ -45,7 +45,6 @@ export function setup() {
|
|||
|
||||
//base sprites without entity representation
|
||||
const bgTex = new Sprite(resources["Background"].texture)
|
||||
bgTex.scale = new Point(2) //TODO make texture of correct size
|
||||
globals.app.stage.addChild(bgTex)
|
||||
|
||||
//start entities
|
||||
|
|
@ -59,7 +58,7 @@ export function setup() {
|
|||
openOffset: new Vector(0),
|
||||
openTex: resources["Door"].spritesheet.textures[0],
|
||||
closedOffset: new Vector(0),
|
||||
closedTex: resources["Door"].spritesheet.textures[1]
|
||||
closedTex: resources["Door"].spritesheet.textures[1],
|
||||
})
|
||||
|
||||
//debug room bounds
|
||||
|
|
@ -69,5 +68,5 @@ export function setup() {
|
|||
|
||||
//example humans
|
||||
//TODO delete those
|
||||
for (let i = 0; i < 10; i++) createRandomHuman(globals.world)
|
||||
for (let i = 0; i < 5; i++) createRandomHuman(globals.world)
|
||||
}
|
||||
|
|
|
|||