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 {
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() {
return {};
}

View File

@ -1,7 +1,18 @@
import Component from '@/ecs/component.js';
import {HALF_PI, TAU} from '@/util/math.js';
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 = {
direction: {type: 'uint8'},
direction: {defaultValue: HALF_PI, type: 'float32'},
};
}

View File

@ -1,16 +1,6 @@
import Component from '@/ecs/component.js';
export default class Emitter extends Component {
mergeDiff(original, update) {
const merged = {};
if (update.emit) {
merged.emit = {
...original.emit,
...update.emit,
}
}
return merged;
}
instanceFromSchema() {
const Component = this;
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);
let x0 = Position.x - 8;
let y0 = Position.y - 8;
if (0 === Direction.direction) {
y0 -= 12
}
if (1 === Direction.direction) {
const direction = Direction.quantize(4);
if (0 === direction) {
x0 += 12
}
if (2 === Direction.direction) {
if (1 === direction) {
y0 += 12
}
if (3 === Direction.direction) {
if (2 === direction) {
x0 -= 12
}
if (3 === direction) {
y0 -= 12
}
return {x0, x1: x0 + 15, y0, y1: y0 + 15};
}
toJSON() {

View File

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

View File

@ -1,4 +1,5 @@
import {System} from '@/ecs/index.js';
import {HALF_PI} from '@/util/math.js';
export default class ControlDirection extends System {
@ -9,16 +10,16 @@ export default class ControlDirection extends System {
continue;
}
if (moveUp > 0) {
Direction.direction = 0;
Direction.direction = HALF_PI * 3;
}
if (moveDown > 0) {
Direction.direction = 2;
Direction.direction = HALF_PI * 1;
}
if (moveLeft > 0) {
Direction.direction = 3;
Direction.direction = HALF_PI * 2;
}
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) {
const name = {
0: 'up',
1: 'right',
2: 'down',
3: 'left',
0: 'right',
1: 'down',
2: 'left',
3: 'up',
};
parts.push(name[Direction.direction]);
parts.push(name[Direction.quantize(4)]);
}
if (parts.length > 0) {
Sprite.animation = parts.join(':');

View File

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

View File

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

View File

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

View File

@ -45,7 +45,12 @@ export const {
SQRT2,
} = 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 PI_180 = Math.PI / 180;
export function bresenham({x: x1, y: y1}, {x: x2, y: y2}) {
const points = [];

View File

@ -1,5 +1,5 @@
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) {
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);
entity.Controlled[map[entity.Direction.direction]] = 0;
entity.Controlled.stop();
entity.Sprite.isAnimating = 0;
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);

View File

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

View File

@ -1,5 +1,5 @@
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) {
const {Controlled, Emitter, Sound, Sprite} = wielder