feat: basic magnetism

This commit is contained in:
cha0s 2019-07-23 00:29:07 -05:00
parent 766e6b3e0c
commit 2eb97d2723
4 changed files with 129 additions and 4 deletions

View File

@ -0,0 +1,84 @@
import {behaviorItemFromJSON, createContext} from '@avocado/behavior';
import {compose, Property} from '@avocado/core';
import {StateProperty, Trait} from '@avocado/entity';
import {Rectangle, Vector} from '@avocado/math';
import {TraitPlantPacket} from './trait-plant.packet';
const decorate = compose(
StateProperty('attraction', {
track: true,
}),
);
export class Magnetic extends decorate(Trait) {
static defaultParams() {
return {
isAttractor: false,
};
}
static defaultState() {
return {
attraction: 0,
};
}
static type() {
return 'magnetic';
}
constructor(entity, params, state) {
super(entity, params, state);
}
get isAttracted() {
return !this.params.isAttractor;
}
get isAttractor() {
return !!this.params.isAttractor;
}
tick(elapsed) {
if (!this.params.isAttractor) {
return;
}
const attraction = this.entity.attraction;
if (0 === attraction) {
return;
}
const layer = this.entity.layer;
if (!layer) {
return;
}
const query = Rectangle.compose(
Vector.sub(this.entity.position, [32, 32]),
[64, 64],
);
const entities = layer.visibleEntities(query);
for (let i = 0; i < entities.length; ++i) {
const entity = entities[i];
if (!entity.is('magnetic') || !entity.isAttracted) {
continue;
}
if (!entity.is('positioned') || !entity.is('mobile')) {
continue;
}
const distance = Vector.distance(
this.entity.position,
entity.position,
);
if (distance > attraction) {
continue;
}
const difference = Vector.sub(this.entity.position, entity.position);
const unit = Vector.normalize(difference);
const rdiff = 1 - (distance / attraction);
const magnitude = 50 * rdiff;
entity.applyMovement(Vector.scale(unit, magnitude));
}
}
}

View File

@ -47,6 +47,11 @@ export function createEntityForConnection(socket) {
informed: {},
layered: {},
listed: {},
magnetic: {
params: {
isAttractor: true,
},
},
mobile: {
state: {
speed: 100,

View File

@ -61,12 +61,15 @@ export function kittyFireJSON() {
roomJSON.layers[0].entities.push(positionedEntityJSON(uri, position));
}
for (let i = 0; i < 20; ++i) {
addEntityWithRandomPosition('/rock.entity.json');
}
// for (let i = 0; i < 20; ++i) {
// addEntityWithRandomPosition('/flower-barrel.entity.json');
// }
for (let i = 0; i < 3; ++i) {
addEntityWithRandomPosition('/mama-kitty-spawner.entity.json');
}
// for (let i = 0; i < 3; ++i) {
// addEntityWithRandomPosition('/mama-kitty-spawner.entity.json');
// }
// for (let i = 0; i < 5; ++i) {
// addEntityWithRandomPosition('/fire.entity.json');
// }

View File

@ -30,6 +30,11 @@ export function rockJSON() {
);
return {
traits: {
collider: {
params: {
isSensor: true,
},
},
existent: {
state: {
name: 'Rock',
@ -51,6 +56,33 @@ export function rockJSON() {
},
},
},
layered: {},
listed: {},
magnetic: {},
mobile: {},
physical: {},
pictured: {
params: {
images: {
initial: {
offset: [0, 0],
size: [12, 12], // Derive?
uri: '/rock.png',
},
}
},
},
positioned: {},
roomed: {},
shaped: {
params: {
shape: {
type: 'rectangle',
position: [0, 0],
size: [12, 12],
},
},
},
spawner: {
params: {
spawns: {
@ -59,7 +91,8 @@ export function rockJSON() {
},
},
},
}
},
visible: {},
},
};
}