Add some entity garbage
This commit is contained in:
parent
09d8152c6c
commit
84eadde101
94
Engine/src/data/sprite.ts
Normal file
94
Engine/src/data/sprite.ts
Normal file
|
@ -0,0 +1,94 @@
|
|||
import * as PIXI from 'pixi.js'
|
||||
|
||||
export class Sprite {
|
||||
uuid: string
|
||||
texture: PIXI.Texture
|
||||
originX: number = 0
|
||||
originY: number = 0
|
||||
x: number = 0
|
||||
y: number = 0
|
||||
width: number = 0
|
||||
height: number = 0
|
||||
root: SpritePart
|
||||
|
||||
constructor(o: any) {
|
||||
this.uuid = o.uuid
|
||||
this.texture = PIXI.Texture.from('./Assets/Sprites/'+o.source)
|
||||
this.texture.baseTexture.scaleMode = PIXI.SCALE_MODES.NEAREST
|
||||
this.root = new SpritePart(o, {
|
||||
texture: this.texture,
|
||||
originX: 0,
|
||||
originY: 0,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
time: 0,
|
||||
source: '',
|
||||
}, this.texture)
|
||||
}
|
||||
}
|
||||
|
||||
export interface SpritePartI {
|
||||
texture: PIXI.Texture
|
||||
originX: number
|
||||
originY: number
|
||||
x: number
|
||||
y: number
|
||||
width: number
|
||||
height: number
|
||||
time: number
|
||||
source: string
|
||||
children?: Record<string, SpritePart>
|
||||
}
|
||||
|
||||
export class SpritePart {
|
||||
texture: PIXI.Texture
|
||||
originX: number = 0
|
||||
originY: number = 0
|
||||
x: number = 0
|
||||
y: number = 0
|
||||
width: number = 0
|
||||
height: number = 0
|
||||
time: number = 0
|
||||
source: string = ''
|
||||
children: Record<string, SpritePart> = {}
|
||||
frames?: SpritePart[]
|
||||
|
||||
constructor(o: any, p: SpritePartI, t: PIXI.Texture) {
|
||||
this.time = o.time ?? p.time
|
||||
this.x = o.x ?? p.x
|
||||
this.y = o.y ?? p.y
|
||||
this.width = o.width ?? p.width
|
||||
this.height = o.height ?? p.height
|
||||
this.originX = o.origin_x ?? p.originX
|
||||
this.originY = o.origin_y ?? p.originY
|
||||
if (o.source) {
|
||||
t = PIXI.Texture.from('./Assets/Sprites/'+o.source)
|
||||
t.baseTexture.scaleMode = PIXI.SCALE_MODES.NEAREST
|
||||
}
|
||||
if (this.x === p.x && this.y === p.y && this.width === p.width && this.height === p.height && o.source === p.source) {
|
||||
this.texture = p.texture
|
||||
} else {
|
||||
this.texture = new PIXI.Texture(t.baseTexture, new PIXI.Rectangle(this.x, this.y, this.width, this.height))
|
||||
}
|
||||
|
||||
if (o.animations) {
|
||||
for (let [key, value] of Object.entries(o.animations)) {
|
||||
this.children[key] = new SpritePart(value, this, t)
|
||||
}
|
||||
} else if (o.sets) {
|
||||
for (let [key, value] of Object.entries(o.sets)) {
|
||||
this.children[key] = new SpritePart(value, this, t)
|
||||
}
|
||||
} else if (o.subsets) {
|
||||
for (let [key, value] of Object.entries(o.subsets)) {
|
||||
this.children[key] = new SpritePart(value, this, t)
|
||||
}
|
||||
} else if (o.frames) {
|
||||
this.frames = o.frames.map((v: any) => {
|
||||
return new SpritePart(v, this, t)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import { MenuState } from './states/Menu'
|
|||
import { StateI } from './states/StateI'
|
||||
import { decors } from './shared/decors'
|
||||
import { segments } from './shared/segments'
|
||||
import { sprites } from './shared/sprites'
|
||||
|
||||
export class Engine {
|
||||
ctx: ContextI
|
||||
|
@ -19,6 +20,7 @@ export class Engine {
|
|||
console.log(
|
||||
decors,
|
||||
segments,
|
||||
sprites,
|
||||
)
|
||||
|
||||
// Setup
|
||||
|
|
35
Engine/src/shared/sprites.ts
Normal file
35
Engine/src/shared/sprites.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import assets from '../../../Assets/Sprites/**/*.yaml'
|
||||
import { Sprite } from '../data/sprite'
|
||||
import * as PIXI from 'pixi.js'
|
||||
|
||||
export const sprites: Record<string, Sprite> = {}
|
||||
|
||||
for (let [key, value] of Object.entries(assets)) {
|
||||
sprites[key] = new Sprite(value)
|
||||
}
|
||||
|
||||
export class SpriteInstance {
|
||||
container: PIXI.Container
|
||||
|
||||
constructor(ctor: string) {
|
||||
this.container = new PIXI.Container()
|
||||
let [spriteKey, animationKey, setKey, subsetKey, frameKey] = ctor.split('.')
|
||||
let frameIndex = Number(frameKey)
|
||||
let sprite = sprites[spriteKey]
|
||||
if (!sprite) {
|
||||
this.container.addChild(new PIXI.Text('missing sprite'))
|
||||
return
|
||||
}
|
||||
let animation = sprite.root.children[animationKey]
|
||||
let set = animation.children[setKey]
|
||||
let subset = set.children[subsetKey]
|
||||
//
|
||||
if (subset.frames) {
|
||||
let frame = subset.frames[frameIndex]
|
||||
let s = new PIXI.Sprite(frame.texture)
|
||||
s.x -= frame.originX
|
||||
s.y -= frame.originY
|
||||
this.container.addChild(s)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,14 +3,89 @@ import { segments } from "../shared/segments"
|
|||
import { StateI } from "./StateI"
|
||||
import * as PIXI from 'pixi.js'
|
||||
import { DecorationInstance } from "../shared/decors"
|
||||
import { SpriteInstance } from "../shared/sprites"
|
||||
|
||||
interface Action {
|
||||
type: string
|
||||
priority: number
|
||||
}
|
||||
|
||||
class Entity {
|
||||
sprite: SpriteInstance
|
||||
|
||||
constructor(ctor: string) {
|
||||
this.sprite = new SpriteInstance(ctor)
|
||||
}
|
||||
|
||||
update(delta: number) {
|
||||
// TODO: Update sprite.
|
||||
}
|
||||
|
||||
get x(): number {
|
||||
return this.sprite.container.x
|
||||
}
|
||||
set x(v: number) {
|
||||
this.sprite.container.x = v
|
||||
}
|
||||
get y(): number {
|
||||
return this.sprite.container.y
|
||||
}
|
||||
set y(v: number) {
|
||||
this.sprite.container.y = v
|
||||
}
|
||||
}
|
||||
|
||||
class PlayerEntity extends Entity {
|
||||
action?: Action
|
||||
constructor(ctor: string) {
|
||||
super(ctor)
|
||||
this.x = 100
|
||||
this.y = 100
|
||||
// TODO: Hooks for key state check input, perhaps?
|
||||
}
|
||||
act(actions: Action[]) {
|
||||
this.action = actions.sort((a, b) => {
|
||||
if (a.priority < b.priority) {
|
||||
return -1
|
||||
}
|
||||
if (a.priority > b.priority) {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
})[0]
|
||||
}
|
||||
update(delta: number) {
|
||||
if (this.action) {
|
||||
// FIXME: Use physics.
|
||||
switch(this.action.type) {
|
||||
case 'west':
|
||||
this.x--
|
||||
break
|
||||
case 'east':
|
||||
this.x++
|
||||
break
|
||||
case 'north':
|
||||
this.y--
|
||||
break
|
||||
case 'south':
|
||||
this.y++
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function isPlayerEntity(o: any): o is PlayerEntity {
|
||||
return o.act
|
||||
}
|
||||
|
||||
export function GameState(ctx: ContextI): StateI {
|
||||
|
||||
let rootContainer = new PIXI.Container()
|
||||
let decorations: DecorationInstance[] = []
|
||||
let entities: Entity[] = []
|
||||
|
||||
let enter = () => {
|
||||
console.log('less goooo')
|
||||
hookKeyboard()
|
||||
// Load the world segment.
|
||||
let w = segments.world
|
||||
if (!w) return ctx.pop()
|
||||
|
@ -28,7 +103,6 @@ export function GameState(ctx: ContextI): StateI {
|
|||
di.container.x = d.x
|
||||
di.container.y = d.y
|
||||
if (d.flip) {
|
||||
console.log('friggin flip it')
|
||||
di.container.pivot.y = 1
|
||||
di.container.scale.y *= -1
|
||||
di.container.position.y--
|
||||
|
@ -46,15 +120,88 @@ export function GameState(ctx: ContextI): StateI {
|
|||
rootContainer.addChild(container)
|
||||
}
|
||||
|
||||
// Add bogus entity
|
||||
addEntity(new PlayerEntity('animals.deer.animal.west.0'))
|
||||
|
||||
ctx.app.stage.addChild(rootContainer)
|
||||
}
|
||||
let leave = () => {
|
||||
unhookKeyboard()
|
||||
for (let entity of entities) {
|
||||
removeEntity(entity)
|
||||
}
|
||||
ctx.app.stage.removeChild(rootContainer)
|
||||
}
|
||||
let update = (delta: number) => {
|
||||
for (let decoration of decorations) {
|
||||
decoration.update(delta)
|
||||
}
|
||||
for (let entity of entities) {
|
||||
if (isPlayerEntity(entity)) {
|
||||
entity.act(desiredActions)
|
||||
// FIXME: This isn't the right place for this.
|
||||
rootContainer.position.set(Math.round(ctx.app.renderer.width/2), Math.round(ctx.app.renderer.height/2))
|
||||
rootContainer.pivot.set(entity.x, entity.y)
|
||||
}
|
||||
entity.update(delta)
|
||||
}
|
||||
}
|
||||
|
||||
let addEntity = (entity: Entity) => {
|
||||
if (entities.find(v=>v===entity)) return
|
||||
entities.push(entity)
|
||||
rootContainer.addChild(entity.sprite.container)
|
||||
}
|
||||
let removeEntity = (entity: Entity) => {
|
||||
entities = entities.filter(v=>v!==entity)
|
||||
rootContainer.removeChild(entity.sprite.container)
|
||||
}
|
||||
|
||||
let desiredActions: Action[] = []
|
||||
let adjustAction = (type: string, v: number) => {
|
||||
let action = desiredActions.find(v=>v.type===type)
|
||||
if (!action) {
|
||||
desiredActions.push({
|
||||
type: type,
|
||||
priority: v,
|
||||
})
|
||||
} else {
|
||||
action.priority += v
|
||||
if (action.priority <= 0) {
|
||||
desiredActions = desiredActions.filter(v=>v!==action)
|
||||
}
|
||||
}
|
||||
}
|
||||
let keyup = (e: KeyboardEvent) => {
|
||||
if (e.key === 'ArrowLeft') {
|
||||
adjustAction('west', -1)
|
||||
} else if (e.key === 'ArrowRight') {
|
||||
adjustAction('east', -1)
|
||||
} else if (e.key === 'ArrowUp') {
|
||||
adjustAction('north', -1)
|
||||
} else if (e.key === 'ArrowDown') {
|
||||
adjustAction('south', -1)
|
||||
}
|
||||
}
|
||||
let keydown = (e: KeyboardEvent) => {
|
||||
if (e.repeat) return
|
||||
if (e.key === 'ArrowLeft') {
|
||||
adjustAction('west', 1)
|
||||
} else if (e.key === 'ArrowRight') {
|
||||
adjustAction('east', 1)
|
||||
} else if (e.key === 'ArrowUp') {
|
||||
adjustAction('north', 1)
|
||||
} else if (e.key === 'ArrowDown') {
|
||||
adjustAction('south', 1)
|
||||
}
|
||||
}
|
||||
let hookKeyboard = () => {
|
||||
window.addEventListener('keyup', keyup)
|
||||
window.addEventListener('keydown', keydown)
|
||||
}
|
||||
let unhookKeyboard = () => {
|
||||
window.removeEventListener('keyup', keyup)
|
||||
window.removeEventListener('keydown', keydown)
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
Loading…
Reference in New Issue
Block a user