feat: collision scripts

This commit is contained in:
cha0s 2024-07-02 22:42:56 -05:00
parent 86a3367efa
commit 30033fd8e4
9 changed files with 106 additions and 7 deletions

View File

@ -11,7 +11,7 @@ export default function createEcs(Ecs) {
'PlantGrowth',
'FollowCamera',
'VisibleAabbs',
'Collliders',
'Colliders',
'ControlDirection',
'SpriteDirection',
'RunAnimations',

View File

@ -5,7 +5,7 @@ export default async function createHomestead(Ecs) {
const area = {x: 100, y: 60};
await ecs.create({
AreaSize: {x: area.x * 16, y: area.y * 16},
Engine: {},
Ticking: {},
TileLayers: {
layers: [
{
@ -19,6 +19,17 @@ export default async function createHomestead(Ecs) {
Water: {water: {}},
});
await ecs.create({
Collider: {
bodies: [
[
{x: -36, y: -16},
{x: -21, y: -16},
{x: -36, y: -1},
{x: -21, y: -1},
],
],
collisionStartScript: '/assets/shit-shack/collision-start.js',
},
Position: {x: 100, y: 100},
Sprite: {
anchor: {x: 0.5, y: 0.8},

21
app/create-house.js Normal file
View File

@ -0,0 +1,21 @@
import createEcs from './create-ecs.js';
export default async function createHouse(Ecs) {
const ecs = createEcs(Ecs);
const area = {x: 20, y: 20};
await ecs.create({
AreaSize: {x: area.x * 16, y: area.y * 16},
Ticking: {},
TileLayers: {
layers: [
{
area,
data: Array(area.x * area.y).fill(0).map(() => 5 + Math.floor(Math.random() * 2)),
source: '/assets/tileset.json',
tileSize: {x: 16, y: 16},
}
],
},
});
return ecs;
}

View File

@ -1,6 +1,16 @@
export default async function createPlayer(id) {
const player = {
Camera: {},
Collider: {
bodies: [
[
{x: -8, y: -8},
{x: 7, y: -8},
{x: -8, y: 7},
{x: 7, y: 7},
],
],
},
Controlled: {},
Direction: {direction: 2},
Ecs: {path: ['homesteads', `${id}`].join('/')},
@ -28,7 +38,7 @@ export default async function createPlayer(id) {
},
},
Health: {health: 100},
Position: {x: 368, y: 368},
Position: {x: 128, y: 128},
Speed: {speed: 100},
Sound: {},
Sprite: {

View File

@ -7,6 +7,7 @@ export default class Collider extends Component {
instanceFromSchema() {
const {ecs} = this;
return class ColliderInstance extends super.instanceFromSchema() {
collidingWith = {};
isCollidingWith(other) {
const {aabb, aabbs} = this;
const {aabb: otherAabb, aabbs: otherAabbs} = other;
@ -63,6 +64,26 @@ export default class Collider extends Component {
}
}
}
async load(instance) {
// heavy handed...
if ('undefined' !== typeof window) {
return;
}
instance.collisionEndScriptInstance = await this.ecs.readScript(
instance.collisionEndScript,
{
ecs: this.ecs,
entity: this.ecs.get(instance.entity),
},
);
instance.collisionStartScriptInstance = await this.ecs.readScript(
instance.collisionStartScript,
{
ecs: this.ecs,
entity: this.ecs.get(instance.entity),
},
);
}
static properties = {
bodies: {
type: 'array',
@ -71,5 +92,7 @@ export default class Collider extends Component {
subtype: vector2d('int16'),
},
},
collisionEndScript: {type: 'string'},
collisionStartScript: {type: 'string'},
};
}

View File

@ -1,3 +0,0 @@
import Component from '@/ecs/component.js';
export default class Engine extends Component {}

View File

@ -39,6 +39,7 @@ export default class Colliders extends System {
}
tick() {
const {Ticking} = this.ecs.get(1);
const seen = {};
for (const entity of this.ecs.changed(['Position'])) {
if (seen[entity.id]) {
@ -48,6 +49,8 @@ export default class Colliders extends System {
if (!entity.Collider) {
continue;
}
const {collidingWith: wasCollidingWith} = entity.Collider;
entity.Collider.collidingWith = {};
this.updateHash(entity);
for (const other of this.within(entity.Collider.aabb)) {
if (seen[other.id]) {
@ -57,8 +60,33 @@ export default class Colliders extends System {
if (!other.Collider) {
continue;
}
delete other.Collider.collidingWith[entity.id];
if (entity.Collider.isCollidingWith(other.Collider)) {
console.log('collide', entity, other);
entity.Collider.collidingWith[other.id] = true;
other.Collider.collidingWith[entity.id] = true;
if (!wasCollidingWith[other.id]) {
if (entity.Collider.collisionStartScriptInstance) {
entity.Collider.collisionStartScriptInstance.context.other = other;
Ticking.addTickingPromise(entity.Collider.collisionStartScriptInstance.tickingPromise());
}
if (other.Collider.collisionStartScriptInstance) {
other.Collider.collisionStartScriptInstance.context.other = entity;
Ticking.addTickingPromise(other.Collider.collisionStartScriptInstance.tickingPromise());
}
}
}
}
for (const otherId in wasCollidingWith) {
if (!entity.Collider.collidingWith[otherId]) {
const other = this.ecs.get(otherId);
if (entity.Collider.collisionEndScriptInstance) {
entity.Collider.collisionEndScriptInstance.context.other = other;
Ticking.addTickingPromise(entity.Collider.collisionEndScriptInstance.tickingPromise());
}
if (other.Collider.collisionEndScriptInstance) {
other.Collider.collisionEndScriptInstance.context.other = entity;
Ticking.addTickingPromise(other.Collider.collisionEndScriptInstance.tickingPromise());
}
}
}
}

View File

@ -8,6 +8,7 @@ import Script from '@/util/script.js';
import createEcs from './create-ecs.js';
import createHomestead from './create-homestead.js';
import createHouse from './create-house.js';
import createPlayer from './create-player.js';
export default class Engine {
@ -42,6 +43,9 @@ export default class Engine {
return chars.byteLength > 0 ? JSON.parse((new TextDecoder()).decode(chars)) : {};
}
async readScript(uri, context) {
if (!uri) {
return undefined;
}
const code = await this.readAsset(uri);
if (code.byteLength > 0) {
return Script.fromCode((new TextDecoder()).decode(code), context);
@ -160,6 +164,10 @@ export default class Engine {
['homesteads', `${id}`].join('/'),
await createHomestead(this.Ecs),
);
await this.saveEcs(
['houses', `${id}`].join('/'),
await createHouse(this.Ecs),
);
buffer = await createPlayer(id);
await this.server.writeData(
['players', `${id}`].join('/'),

View File

@ -0,0 +1 @@
console.log("I'ma warp yo azz")