diff --git a/app/ecs/components/collider.js b/app/ecs/components/collider.js index ec7e672..9c989ab 100644 --- a/app/ecs/components/collider.js +++ b/app/ecs/components/collider.js @@ -142,6 +142,7 @@ export default class Collider extends Component { type: 'array', subtype: {type: 'string'}, }, + unstoppable: {type: 'uint8'}, }, }, }, diff --git a/app/ecs/systems/colliders.js b/app/ecs/systems/colliders.js index 068792a..e5e72ce 100644 --- a/app/ecs/systems/colliders.js +++ b/app/ecs/systems/colliders.js @@ -89,8 +89,9 @@ export default class Colliders extends System { } for (const i in intersections) { const [body, otherBody] = intersections[i]; + const {unstoppable} = body; const {impassable} = otherBody; - if (impassable) { + if (!unstoppable && impassable) { const j = entity.Collider.bodies.indexOf(body); const oj = other.Collider.bodies.indexOf(otherBody); const aabb = entity.Collider.$$aabbs[j]; diff --git a/app/server/create/player.js b/app/server/create/player.js index c3f63e3..c6954ea 100644 --- a/app/server/create/player.js +++ b/app/server/create/player.js @@ -26,6 +26,10 @@ export default async function createPlayer(id) { qty: 100, source: '/assets/potion/potion.json', }, + 2: { + qty: 1, + source: '/assets/magic-swords/magic-swords.json', + }, }, }, Health: {health: 100}, diff --git a/public/assets/magic-swords/icon.png b/public/assets/magic-swords/icon.png new file mode 100644 index 0000000..26b5ad4 Binary files /dev/null and b/public/assets/magic-swords/icon.png differ diff --git a/public/assets/magic-swords/magic-sword-shot.json b/public/assets/magic-swords/magic-sword-shot.json new file mode 100644 index 0000000..6331ddc --- /dev/null +++ b/public/assets/magic-swords/magic-sword-shot.json @@ -0,0 +1 @@ +{"frames":{"":{"frame":{"x":0,"y":0,"w":22,"h":22},"spriteSourceSize":{"x":0,"y":0,"w":22,"h":22},"sourceSize":{"w":22,"h":22}}},"meta":{"format":"RGBA8888","image":"./magic-sword-shot.png","rotation":2.356194490192345,"scale":1,"size":{"w":22,"h":22}}} \ No newline at end of file diff --git a/public/assets/magic-swords/magic-sword-shot.png b/public/assets/magic-swords/magic-sword-shot.png new file mode 100644 index 0000000..a82d149 Binary files /dev/null and b/public/assets/magic-swords/magic-sword-shot.png differ diff --git a/public/assets/magic-swords/magic-swords.json b/public/assets/magic-swords/magic-swords.json new file mode 100644 index 0000000..238ad41 --- /dev/null +++ b/public/assets/magic-swords/magic-swords.json @@ -0,0 +1,5 @@ +{ + "icon": "/assets/magic-swords/icon.png", + "label": "Magic swords", + "start": "/assets/magic-swords/start.js" +} \ No newline at end of file diff --git a/public/assets/magic-swords/start.js b/public/assets/magic-swords/start.js new file mode 100644 index 0000000..c13a94f --- /dev/null +++ b/public/assets/magic-swords/start.js @@ -0,0 +1,87 @@ +const {Position} = wielder; + +const shots = []; + +const EVERY = 0.03; +const N = 14; +const SPREAD = 1; + +const creating = []; +const promises = [] + +for (let i = 0; i < N; ++i) { + promises.push(ecs.create({ + Collider: { + bodies: [ + { + points: [ + {x: -3, y: -2}, + {x: 12, y: -2}, + {x: 12, y: 2}, + {x: -3, y: 2}, + ], + unstoppable: 1, + }, + ], + }, + Controlled: {}, + Direction: {direction: Math.TAU * (i / N)}, + Forces: {}, + Position: {x: Position.x, y: Position.y}, + Speed: {}, + Sprite: { + alpha: 0, + source: '/assets/magic-swords/magic-sword-shot.json', + }, + Ticking: {}, + VisibleAabb: {}, + })); +} + +for (const id of await Promise.all(promises)) { + creating.push(ecs.get(id)); +} + +const accumulated = {}; +const shot = creating.shift(); +shot.Sprite.alpha = 1; +accumulated[shot.id] = 0; +shots.push(shot) + +let spawner = 0; +while (shots.length > 0) { + spawner += elapsed; + if (creating.length > 0 && spawner >= EVERY) { + const shot = creating.shift(); + shot.Sprite.alpha = 1; + accumulated[shot.id] = 0; + shots.push(shot) + spawner -= EVERY; + } + const destroying = []; + for (const shot of shots) { + accumulated[shot.id] += elapsed; + if (accumulated[shot.id] <= SPREAD) { + shot.Speed.speed = 100 * (1 - (accumulated[shot.id] / SPREAD)) + } + else { + const toward = Math.atan2( + where.y - shot.Position.y, + where.x - shot.Position.x, + ) + shot.Speed.speed = 400; + shot.Direction.direction = (Math.TAU + toward) % Math.TAU; + if (Math.distance(where, shot.Position) < 4) { + delete accumulated[shot.id]; + destroying.push(shot); + } + } + shot.Controlled.directionMove(shot.Direction.direction); + } + for (let i = 0; i < destroying.length; ++i) { + shots.splice(shots.indexOf(destroying[i]), 1); + destroying[i] = destroying[i].id; + } + ecs.destroyMany(destroying); + await wait(0) +}