fun: kittehs
This commit is contained in:
parent
ed8c07a88f
commit
a1d1c35565
46
app/ecs/components/behaving.js
Normal file
46
app/ecs/components/behaving.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
import Component from '@/ecs/component.js';
|
||||
|
||||
export default class Behaving extends Component {
|
||||
instanceFromSchema() {
|
||||
return class BehavingInstance extends super.instanceFromSchema() {
|
||||
$$routineInstances = {};
|
||||
tick(elapsed) {
|
||||
const routine = this.$$routineInstances[this.currentRoutine];
|
||||
if (routine) {
|
||||
routine.tick(elapsed);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
async load(instance) {
|
||||
// heavy handed...
|
||||
if ('undefined' !== typeof window) {
|
||||
return;
|
||||
}
|
||||
const promises = [];
|
||||
for (const key in instance.routines) {
|
||||
promises.push(
|
||||
this.ecs.readScript(
|
||||
instance.routines[key],
|
||||
{
|
||||
entity: this.ecs.get(instance.entity),
|
||||
},
|
||||
)
|
||||
.then((script) => {
|
||||
instance.$$routineInstances[key] = script;
|
||||
}),
|
||||
);
|
||||
}
|
||||
await Promise.all(promises);
|
||||
}
|
||||
static properties = {
|
||||
currentRoutine: {defaultValue: 'initial', type: 'string'},
|
||||
isBehaving: {defaultValue: 1, type: 'uint8'},
|
||||
routines: {
|
||||
type: 'map',
|
||||
value: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
|
@ -3,9 +3,33 @@ import Component from '@/ecs/component.js';
|
|||
export default class Sprite extends Component {
|
||||
instanceFromSchema() {
|
||||
return class SpriteInstance extends super.instanceFromSchema() {
|
||||
$$sourceJson = {};
|
||||
get anchor() {
|
||||
return {x: this.anchorX, y: this.anchorY};
|
||||
}
|
||||
get animation() {
|
||||
return super.animation;
|
||||
}
|
||||
set animation(animation) {
|
||||
super.animation = animation;
|
||||
// eslint-disable-next-line no-self-assign
|
||||
this.frame = this.frame;
|
||||
}
|
||||
get frame() {
|
||||
return super.frame;
|
||||
}
|
||||
set frame(frame) {
|
||||
super.frame = this.frames ? frame % this.frames : 0;
|
||||
}
|
||||
get frames() {
|
||||
return this.animation
|
||||
? (
|
||||
this.$$sourceJson.animations
|
||||
? this.$$sourceJson.animations[this.animation].length
|
||||
: 0
|
||||
)
|
||||
: 0;
|
||||
}
|
||||
get scale() {
|
||||
return {x: this.scaleX, y: this.scaleY};
|
||||
}
|
||||
|
@ -31,7 +55,7 @@ export default class Sprite extends Component {
|
|||
animation: {type: 'string'},
|
||||
elapsed: {type: 'float32'},
|
||||
frame: {type: 'uint16'},
|
||||
frames: {type: 'uint16'},
|
||||
isAnimating: {defaultValue: 1, type: 'uint8'},
|
||||
scaleX: {defaultValue: 1, type: 'float32'},
|
||||
scaleY: {defaultValue: 1, type: 'float32'},
|
||||
source: {type: 'string'},
|
||||
|
|
17
app/ecs/systems/behave.js
Normal file
17
app/ecs/systems/behave.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
import {System} from '@/ecs/index.js';
|
||||
|
||||
export default class Behave extends System {
|
||||
|
||||
static queries() {
|
||||
return {
|
||||
default: ['Behaving'],
|
||||
};
|
||||
}
|
||||
|
||||
tick(elapsed) {
|
||||
for (const {Behaving} of this.select('default')) {
|
||||
Behaving.tick(elapsed);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import {System} from '@/ecs/index.js';
|
||||
|
||||
export default class ControlMovement extends System {
|
||||
export default class RunAnimations extends System {
|
||||
|
||||
static queries() {
|
||||
return {
|
||||
|
@ -10,13 +10,13 @@ export default class ControlMovement extends System {
|
|||
|
||||
tick(elapsed) {
|
||||
for (const {Sprite} of this.select('default')) {
|
||||
if (0 === Sprite.speed) {
|
||||
if (0 === Sprite.speed || !Sprite.isAnimating) {
|
||||
continue;
|
||||
}
|
||||
Sprite.elapsed += elapsed / Sprite.speed;
|
||||
while (Sprite.elapsed > 1) {
|
||||
Sprite.elapsed -= 1;
|
||||
Sprite.frame = (Sprite.frame + 1) % Sprite.frames;
|
||||
Sprite.frame += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import Systems from '@/ecs/systems/index.js';
|
|||
export default function createEcs(Ecs) {
|
||||
const ecs = new Ecs({Components, Systems});
|
||||
const defaultSystems = [
|
||||
'Behave',
|
||||
'PassTime',
|
||||
'Attract',
|
||||
'ResetForces',
|
||||
|
|
|
@ -94,5 +94,40 @@ export default async function createHomestead(id) {
|
|||
Ticking: {},
|
||||
VisibleAabb: {},
|
||||
});
|
||||
const kitty = {
|
||||
Behaving: {
|
||||
routines: {
|
||||
initial: '/assets/kitty/initial.js',
|
||||
},
|
||||
},
|
||||
Collider: {
|
||||
bodies: [
|
||||
{
|
||||
points: [
|
||||
{x: -4, y: -4},
|
||||
{x: 3, y: -4},
|
||||
{x: 3, y: 3},
|
||||
{x: -4, y: 3},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
Controlled: {},
|
||||
Direction: {direction: 2},
|
||||
Forces: {},
|
||||
Position: {x: 250, y: 250},
|
||||
Speed: {speed: 20},
|
||||
Sprite: {
|
||||
anchorX: 0.5,
|
||||
anchorY: 0.7,
|
||||
source: '/assets/kitty/kitty.json',
|
||||
speed: 0.115,
|
||||
},
|
||||
Ticking: {},
|
||||
VisibleAabb: {},
|
||||
};
|
||||
for (let i = 0; i < 10; ++i) {
|
||||
entities.push(kitty);
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
|
|
@ -52,7 +52,6 @@ export default async function createPlayer(id) {
|
|||
anchorY: 0.8,
|
||||
animation: 'moving:down',
|
||||
frame: 0,
|
||||
frames: 8,
|
||||
source: '/assets/dude/dude.json',
|
||||
speed: 0.115,
|
||||
},
|
||||
|
|
|
@ -121,6 +121,13 @@ export function createRandom(seed = 0) {
|
|||
return alea(seed);
|
||||
}
|
||||
|
||||
export const directionToVector = [
|
||||
{x: 0, y: -1},
|
||||
{x: 1, y: 0},
|
||||
{x: 0, y: 1},
|
||||
{x: -1, y: 0},
|
||||
];
|
||||
|
||||
export function distance({x: lx, y: ly}, {x: rx, y: ry}) {
|
||||
const xd = lx - rx;
|
||||
const yd = ly - ry;
|
||||
|
@ -246,13 +253,6 @@ export function isCollinear({x: ax, y: ay}, {x: bx, y: by}, {x: cx, y: cy}) {
|
|||
return (ay - by) * (ax - cx) === (ay - cy) * (ax - bx);
|
||||
}
|
||||
|
||||
export const directionToVector = [
|
||||
{x: 0, y: -1},
|
||||
{x: 1, y: 0},
|
||||
{x: 0, y: 1},
|
||||
{x: -1, y: 0},
|
||||
];
|
||||
|
||||
export function ortho(points, k = {x: 1, y: 1}) {
|
||||
if (points.length < 4) {
|
||||
throw new TypeError('Math.ortho(): points.length < 4');
|
||||
|
|
|
@ -106,10 +106,12 @@ export default class Script {
|
|||
if (async) {
|
||||
this.promise = value;
|
||||
value
|
||||
.catch(reject)
|
||||
.catch(reject ? reject : () => {})
|
||||
.then(() => {
|
||||
if (done) {
|
||||
resolve();
|
||||
if (resolve) {
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -118,7 +120,9 @@ export default class Script {
|
|||
break;
|
||||
}
|
||||
if (done) {
|
||||
resolve();
|
||||
if (resolve) {
|
||||
resolve();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
16
public/assets/kitty/initial.js
Normal file
16
public/assets/kitty/initial.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
entity.Direction.direction = Math.floor(Math.random() * 4);
|
||||
|
||||
const map = {0: 'moveUp', 1: 'moveRight', 2: 'moveDown', 3: 'moveLeft'};
|
||||
entity.Controlled[map[entity.Direction.direction]] = 1;
|
||||
await wait(0.25 + Math.random() * 2.25);
|
||||
entity.Controlled[map[entity.Direction.direction]] = 0;
|
||||
|
||||
entity.Sprite.isAnimating = 0;
|
||||
|
||||
await wait(1 + Math.random() * 3);
|
||||
|
||||
entity.Direction.direction = Math.floor(Math.random() * 4);
|
||||
|
||||
await wait(0.5 + Math.random() * 2.5);
|
||||
|
||||
entity.Sprite.isAnimating = 1;
|
263
public/assets/kitty/kitty.json
Normal file
263
public/assets/kitty/kitty.json
Normal file
|
@ -0,0 +1,263 @@
|
|||
{
|
||||
"animations": {
|
||||
"idle:up": [
|
||||
"kitty/0"
|
||||
],
|
||||
"idle:right": [
|
||||
"kitty/3"
|
||||
],
|
||||
"idle:down": [
|
||||
"kitty/6"
|
||||
],
|
||||
"idle:left": [
|
||||
"kitty/9"
|
||||
],
|
||||
"moving:up": [
|
||||
"kitty/0",
|
||||
"kitty/1",
|
||||
"kitty/2"
|
||||
],
|
||||
"moving:right": [
|
||||
"kitty/3",
|
||||
"kitty/4",
|
||||
"kitty/5"
|
||||
],
|
||||
"moving:down": [
|
||||
"kitty/6",
|
||||
"kitty/7",
|
||||
"kitty/8"
|
||||
],
|
||||
"moving:left": [
|
||||
"kitty/9",
|
||||
"kitty/10",
|
||||
"kitty/11"
|
||||
]
|
||||
},
|
||||
"frames": {
|
||||
"kitty/0": {
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"sourceSize": {
|
||||
"w": 16,
|
||||
"h": 16
|
||||
}
|
||||
},
|
||||
"kitty/1": {
|
||||
"frame": {
|
||||
"x": 16,
|
||||
"y": 0,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"sourceSize": {
|
||||
"w": 16,
|
||||
"h": 16
|
||||
}
|
||||
},
|
||||
"kitty/2": {
|
||||
"frame": {
|
||||
"x": 32,
|
||||
"y": 0,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"sourceSize": {
|
||||
"w": 16,
|
||||
"h": 16
|
||||
}
|
||||
},
|
||||
"kitty/3": {
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 16,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"sourceSize": {
|
||||
"w": 16,
|
||||
"h": 16
|
||||
}
|
||||
},
|
||||
"kitty/4": {
|
||||
"frame": {
|
||||
"x": 16,
|
||||
"y": 16,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"sourceSize": {
|
||||
"w": 16,
|
||||
"h": 16
|
||||
}
|
||||
},
|
||||
"kitty/5": {
|
||||
"frame": {
|
||||
"x": 32,
|
||||
"y": 16,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"sourceSize": {
|
||||
"w": 16,
|
||||
"h": 16
|
||||
}
|
||||
},
|
||||
"kitty/6": {
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 32,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"sourceSize": {
|
||||
"w": 16,
|
||||
"h": 16
|
||||
}
|
||||
},
|
||||
"kitty/7": {
|
||||
"frame": {
|
||||
"x": 16,
|
||||
"y": 32,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"sourceSize": {
|
||||
"w": 16,
|
||||
"h": 16
|
||||
}
|
||||
},
|
||||
"kitty/8": {
|
||||
"frame": {
|
||||
"x": 32,
|
||||
"y": 32,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"sourceSize": {
|
||||
"w": 16,
|
||||
"h": 16
|
||||
}
|
||||
},
|
||||
"kitty/9": {
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 48,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"sourceSize": {
|
||||
"w": 16,
|
||||
"h": 16
|
||||
}
|
||||
},
|
||||
"kitty/10": {
|
||||
"frame": {
|
||||
"x": 16,
|
||||
"y": 48,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"sourceSize": {
|
||||
"w": 16,
|
||||
"h": 16
|
||||
}
|
||||
},
|
||||
"kitty/11": {
|
||||
"frame": {
|
||||
"x": 32,
|
||||
"y": 48,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 16,
|
||||
"h": 16
|
||||
},
|
||||
"sourceSize": {
|
||||
"w": 16,
|
||||
"h": 16
|
||||
}
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"format": "RGBA8888",
|
||||
"image": "./kitty.png",
|
||||
"scale": 1,
|
||||
"size": {
|
||||
"w": 48,
|
||||
"h": 64
|
||||
}
|
||||
}
|
||||
}
|
BIN
public/assets/kitty/kitty.png
Normal file
BIN
public/assets/kitty/kitty.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 884 B |
Loading…
Reference in New Issue
Block a user