refactor: continuous direction

This commit is contained in:
cha0s 2024-07-24 09:28:35 -05:00
parent cbe5f473a6
commit 3eb94f2ef8
15 changed files with 97 additions and 51 deletions

View File

@ -3,6 +3,32 @@ import Component from '@/ecs/component.js';
export default class Controlled extends Component { export default class Controlled extends Component {
instanceFromSchema() { instanceFromSchema() {
return class ControlledInstance extends super.instanceFromSchema() { return class ControlledInstance extends super.instanceFromSchema() {
directionMove(direction) {
const x = Math.cos(direction);
if (x > 0) {
this.moveLeft = 0;
this.moveRight = x;
}
else {
this.moveLeft = -x;
this.moveRight = 0;
}
const y = Math.sin(direction);
if (y > 0) {
this.moveUp = 0;
this.moveDown = y;
}
else {
this.moveUp = -y;
this.moveDown = 0;
}
}
stop() {
this.moveRight = 0;
this.moveDown = 0;
this.moveLeft = 0;
this.moveUp = 0;
}
toJSON() { toJSON() {
return {}; return {};
} }

View File

@ -1,7 +1,18 @@
import Component from '@/ecs/component.js'; import Component from '@/ecs/component.js';
import {HALF_PI, TAU} from '@/util/math.js';
export default class Direction extends Component { export default class Direction extends Component {
instanceFromSchema() {
return class DirectionInstance extends super.instanceFromSchema() {
static quantize(d, n) {
return Math.floor(((d + (TAU / (n * 2))) % TAU) / (TAU / n));
}
quantize(n) {
return this.constructor.quantize(this.direction, n);
}
};
}
static properties = { static properties = {
direction: {type: 'uint8'}, direction: {defaultValue: HALF_PI, type: 'float32'},
}; };
} }

View File

@ -1,16 +1,6 @@
import Component from '@/ecs/component.js'; import Component from '@/ecs/component.js';
export default class Emitter extends Component { export default class Emitter extends Component {
mergeDiff(original, update) {
const merged = {};
if (update.emit) {
merged.emit = {
...original.emit,
...update.emit,
}
}
return merged;
}
instanceFromSchema() { instanceFromSchema() {
const Component = this; const Component = this;
return class EmitterInstance extends super.instanceFromSchema() { return class EmitterInstance extends super.instanceFromSchema() {
@ -21,4 +11,14 @@ export default class Emitter extends Component {
} }
}; };
} }
} mergeDiff(original, update) {
const merged = {};
if (update.emit) {
merged.emit = {
...original.emit,
...update.emit,
}
}
return merged;
}
}

View File

@ -8,18 +8,19 @@ export default class Interacts extends Component {
const {Direction, Position} = ecs.get(this.entity); const {Direction, Position} = ecs.get(this.entity);
let x0 = Position.x - 8; let x0 = Position.x - 8;
let y0 = Position.y - 8; let y0 = Position.y - 8;
if (0 === Direction.direction) { const direction = Direction.quantize(4);
y0 -= 12 if (0 === direction) {
}
if (1 === Direction.direction) {
x0 += 12 x0 += 12
} }
if (2 === Direction.direction) { if (1 === direction) {
y0 += 12 y0 += 12
} }
if (3 === Direction.direction) { if (2 === direction) {
x0 -= 12 x0 -= 12
} }
if (3 === direction) {
y0 -= 12
}
return {x0, x1: x0 + 15, y0, y1: y0 + 15}; return {x0, x1: x0 + 15, y0, y1: y0 + 15};
} }
toJSON() { toJSON() {

View File

@ -33,21 +33,21 @@ class ItemProxy {
let startY = position.y; let startY = position.y;
switch (direction) { switch (direction) {
case 0: case 0:
startX += projection.distance[1];
startY -= projection.distance[0];
break;
case 1:
startX += projection.distance[0]; startX += projection.distance[0];
startY += projection.distance[1]; startY += projection.distance[1];
break; break;
case 2: case 1:
startX -= projection.distance[1]; startX -= projection.distance[1];
startY += projection.distance[0]; startY += projection.distance[0];
break; break;
case 3: case 2:
startX -= projection.distance[0]; startX -= projection.distance[0];
startY -= projection.distance[1]; startY -= projection.distance[1];
break; break;
case 3:
startX += projection.distance[1];
startY -= projection.distance[0];
break;
} }
const projected = []; const projected = [];
for (const row in projection.grid) { for (const row in projection.grid) {
@ -58,17 +58,17 @@ class ItemProxy {
let axe; let axe;
switch (direction) { switch (direction) {
case 0: case 0:
axe = [column, row];
break;
case 1:
axe = [-row, column]; axe = [-row, column];
break; break;
case 2: case 1:
axe = [-column, -row]; axe = [-column, -row];
break; break;
case 3: case 2:
axe = [row, -column]; axe = [row, -column];
break; break;
case 3:
axe = [column, row];
break;
} }
const x = startX + parseInt(axe[0]); const x = startX + parseInt(axe[0]);
const y = startY + parseInt(axe[1]); const y = startY + parseInt(axe[1]);

View File

@ -1,4 +1,5 @@
import {System} from '@/ecs/index.js'; import {System} from '@/ecs/index.js';
import {HALF_PI} from '@/util/math.js';
export default class ControlDirection extends System { export default class ControlDirection extends System {
@ -9,16 +10,16 @@ export default class ControlDirection extends System {
continue; continue;
} }
if (moveUp > 0) { if (moveUp > 0) {
Direction.direction = 0; Direction.direction = HALF_PI * 3;
} }
if (moveDown > 0) { if (moveDown > 0) {
Direction.direction = 2; Direction.direction = HALF_PI * 1;
} }
if (moveLeft > 0) { if (moveLeft > 0) {
Direction.direction = 3; Direction.direction = HALF_PI * 2;
} }
if (moveRight > 0) { if (moveRight > 0) {
Direction.direction = 1; Direction.direction = HALF_PI * 0;
} }
} }
} }

View File

@ -25,12 +25,12 @@ export default class SpriteDirection extends System {
} }
if (Direction) { if (Direction) {
const name = { const name = {
0: 'up', 0: 'right',
1: 'right', 1: 'down',
2: 'down', 2: 'left',
3: 'left', 3: 'up',
}; };
parts.push(name[Direction.direction]); parts.push(name[Direction.quantize(4)]);
} }
if (parts.length > 0) { if (parts.length > 0) {
Sprite.animation = parts.join(':'); Sprite.animation = parts.join(':');

View File

@ -108,7 +108,7 @@ export default function Ecs({applyFilters, camera, monopolizers, scale}) {
if (entity) { if (entity) {
const {Direction, Position, Wielder} = entity; const {Direction, Position, Wielder} = entity;
setPosition(Position.toJSON()); setPosition(Position.toJSON());
setProjected(Wielder.activeItem()?.project(Position.tile, Direction.direction)); setProjected(Wielder.activeItem()?.project(Position.tile, Direction.quantize(4)));
} }
}, [ecs, mainEntity, scale]); }, [ecs, mainEntity, scale]);
useEffect(() => { useEffect(() => {

View File

@ -116,7 +116,7 @@ export default async function createHomestead(id) {
], ],
}, },
Controlled: {}, Controlled: {},
Direction: {direction: 2}, Direction: {},
Emitter: {}, Emitter: {},
Forces: {}, Forces: {},
Interactive: { Interactive: {

View File

@ -14,7 +14,7 @@ export default async function createPlayer(id) {
], ],
}, },
Controlled: {}, Controlled: {},
Direction: {direction: 2}, Direction: {},
Ecs: {path: ['homesteads', `${id}`].join('/')}, Ecs: {path: ['homesteads', `${id}`].join('/')},
Emitter: {}, Emitter: {},
Forces: {}, Forces: {},

View File

@ -45,7 +45,12 @@ export const {
SQRT2, SQRT2,
} = Math; } = Math;
export const SQRT_2_2 = Math.sqrt(2) / 2;
export const EIGHTH_PI = Math.PI / 8;
export const QUARTER_PI = Math.PI / 4;
export const HALF_PI = Math.PI / 2;
export const TAU = Math.PI * 2; export const TAU = Math.PI * 2;
export const PI_180 = Math.PI / 180;
export function bresenham({x: x1, y: y1}, {x: x2, y: y2}) { export function bresenham({x: x1, y: y1}, {x: x2, y: y2}) {
const points = []; const points = [];

View File

@ -1,5 +1,5 @@
const {Direction, Position, Wielder} = wielder const {Direction, Position, Wielder} = wielder
const projected = Wielder.activeItem()?.project(Position.tile, Direction.direction) const projected = Wielder.activeItem()?.project(Position.tile, Direction.quantize(4))
if (projected?.length > 0) { if (projected?.length > 0) {
const {Controlled, Emitter, Sound, Sprite} = wielder const {Controlled, Emitter, Sound, Sprite} = wielder

View File

@ -1,15 +1,16 @@
entity.Direction.direction = Math.floor(Math.random() * 4); entity.Direction.direction = Math.random() * Math.TAU;
entity.Controlled.directionMove(entity.Direction.direction);
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); await wait(0.25 + Math.random() * 2.25);
entity.Controlled[map[entity.Direction.direction]] = 0;
entity.Controlled.stop();
entity.Sprite.isAnimating = 0; entity.Sprite.isAnimating = 0;
await wait(1 + Math.random() * 3); await wait(1 + Math.random() * 3);
entity.Direction.direction = Math.floor(Math.random() * 4); entity.Direction.direction = Math.random() * Math.TAU;
await wait(0.5 + Math.random() * 2.5); await wait(0.5 + Math.random() * 2.5);

View File

@ -1,5 +1,5 @@
const {Direction, Position, Wielder} = wielder const {Direction, Position, Wielder} = wielder
const projected = Wielder.activeItem()?.project(Position.tile, Direction.direction) const projected = Wielder.activeItem()?.project(Position.tile, Direction.quantize(4))
if (projected?.length > 0) { if (projected?.length > 0) {
const {Controlled, Emitter, Sound, Sprite} = wielder const {Controlled, Emitter, Sound, Sprite} = wielder
const {TileLayers} = ecs.get(1) const {TileLayers} = ecs.get(1)
@ -120,9 +120,10 @@ if (projected?.length > 0) {
Sound.play('/assets/sow.wav'); Sound.play('/assets/sow.wav');
Sprite.animation = ['moving', direction].join(':'); Sprite.animation = ['moving', direction].join(':');
const directionMap = {0: 'right', 1: 'down', 2: 'left', 3: 'up'};
for (let i = 0; i < 6; ++i) { for (let i = 0; i < 6; ++i) {
Direction.direction = Math.floor(Math.random() * 4); Direction.direction = Math.HALF_PI * Math.floor(Math.random() * 4);
Sprite.animation = ['moving', 0 === Direction.direction ? 'up' : (1 === Direction.direction ? 'right' : (2 === Direction.direction ? 'down' : 'left'))].join(':'); Sprite.animation = ['moving', directionMap[Direction.quantize(4)]].join(':');
await wait(0.125); await wait(0.125);
} }

View File

@ -1,5 +1,5 @@
const {Direction, Position, Wielder} = wielder const {Direction, Position, Wielder} = wielder
const projected = Wielder.activeItem()?.project(Position.tile, Direction.direction) const projected = Wielder.activeItem()?.project(Position.tile, Direction.quantize(4))
if (projected?.length > 0) { if (projected?.length > 0) {
const {Controlled, Emitter, Sound, Sprite} = wielder const {Controlled, Emitter, Sound, Sprite} = wielder