From 0b949683a6df3bf14c991f69e7e0147a3812996b Mon Sep 17 00:00:00 2001 From: Thayol Date: Sat, 18 Jan 2025 21:02:04 +0900 Subject: [PATCH] add 3D casting indicator --- public/client.js | 36 ++++++++++++++++++++++++++---------- src/entity.js | 9 +++++++++ src/index.js | 12 ------------ 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/public/client.js b/public/client.js index 2290772..9deab32 100644 --- a/public/client.js +++ b/public/client.js @@ -308,16 +308,28 @@ function connectWebSocket() { buffMarker.visible = false entity.add(buffMarker) - if (e.id == playerId) { - const rangeMaterial = teamMaterials['range'] - const rangeSize = (state.abilities.find((it) => it.id == e.abilities?.a)?.range ?? 0) + e.radius - const rangeMarker = new THREE.Mesh(new THREE.CylinderGeometry((rangeSize) / 100, (rangeSize) / 100, 1), rangeMaterial) - const rangeMarkerSize = 4000 - rangeMarker.scale.y = e.height / rangeMarkerSize - rangeMarker.position.y = (e.height / (rangeMarkerSize * 2)) - (e.height / 100) - rangeMarker.layers.set(1) - entity.add(rangeMarker) - } + const rotationBase = new THREE.Object3D() + entity.add(rotationBase) + + const castingMaterial = new THREE.MeshToonMaterial({ color: 0x10dde0, transparent: true, opacity: 0.4 }) + const castingMarker = new THREE.Mesh(new THREE.CylinderGeometry((e.height * 0.9) / 100, (e.height * 0.9) / 100, 1), castingMaterial) + const castingMarkerSize = 800 + castingMarker.rotation.z = Math.PI / 2 + castingMarker.position.x = (e.radius) / 100 + castingMarker.scale.y = e.height / castingMarkerSize + castingMarker.layers.set(1) + buffMarker.visible = false + rotationBase.add(castingMarker) + + const rangeMaterial = teamMaterials['range'] + const rangeSize = (state.abilities.find((it) => it.id == e.abilities?.a)?.range ?? 0) + e.radius + const rangeMarker = new THREE.Mesh(new THREE.CylinderGeometry((rangeSize) / 100, (rangeSize) / 100, 1), rangeMaterial) + const rangeMarkerSize = 4000 + rangeMarker.scale.y = e.height / rangeMarkerSize + rangeMarker.position.y = (e.height / (rangeMarkerSize * 2)) - (e.height / 100) + rangeMarker.layers.set(1) + buffMarker.visible = false + entity.add(rangeMarker) entities[e.id] = entity } @@ -325,12 +337,16 @@ function connectWebSocket() { entity.children.at(2).visible = e.buffs.some((it) => it.id == 'exposed') // TODO: only works for Exposed now entity.userData.flaggedForRemoval = false + entity.children.at(3).rotation.y = e.rotation positionTweens[entity.id] = new Tween(entity.position).to({ x: e.position.x / 100, y: e.position.y / 100, z: e.height / 100 }, tweenDuration).start() const hp = entity.children.at(0).children.at(0) const percentageHp = e.health / e.maxHealth hp.scale.x = percentageHp hp.position.x = -(1 - percentageHp) / 2 + + entity.children.at(4).visible = e.id == playerId + entity.children.at(3).children.at(0).visible = e.casting != null } for (const e of Object.values(entities)) { diff --git a/src/entity.js b/src/entity.js index 48c0c9e..bf1dbbd 100644 --- a/src/entity.js +++ b/src/entity.js @@ -18,6 +18,7 @@ export default class Entity { memory = {} // TODO: hide from reports but keep public position = null radius = 0 + rotation = 0 speed = 400 team = Team.neutral visualRadius = null @@ -102,6 +103,11 @@ export default class Entity { this.#moving = false } + const targetPosition = (cursor instanceof Vector2) ? cursor : this.game?.entities.find((it) => it.id == cursor)?.position + if (targetPosition instanceof Vector2) { + this.rotation = targetPosition.clone().sub(this.position).angle() + } + const cooldown = this.game?.secToTick(ability.cooldown) ?? 0 const lastCast = this.cooldowns[ability.id] const timestamp = this.game?.currentTick ?? 0 @@ -399,10 +405,13 @@ export default class Entity { const direction = difference.clone().normalize() const stepTaken = this.position.clone().add(direction.multiplyScalar(speed)) const position = distance <= speed ? destination : stepTaken + const rotation = direction.angle() const collider = Entity.collider(position.x, position.y, this.radius) const isColliding = SATX.collideObjects(collider, this.collidables()) + this.rotation = rotation + if (!isColliding) { this.position.copy(position) } diff --git a/src/index.js b/src/index.js index d038350..f63c14a 100644 --- a/src/index.js +++ b/src/index.js @@ -123,18 +123,6 @@ function laneScenario() { } } game.logic = gameLogic - - // player2.teleport(new Vector2(100, 100)) - // player2.logic = function patrolLogic() { - // const entity = this - // if (entity.position.x < 100) { entity.memory.patrolReverse = false } - // if (entity.position.x > 1900) { entity.memory.patrolReverse = true } - // const goal = entity.memory.patrolReverse ? new Vector2(50, 100) : new Vector2(1950, 100) - - // entity.moveAction(goal) - // } - - // player1.abilities[0] = 'melee_attack' } app.listen(port, () => {