diff --git a/public/client.js b/public/client.js index 2fee4a5..83d28f1 100644 --- a/public/client.js +++ b/public/client.js @@ -10,6 +10,7 @@ renderer.setSize(window.innerWidth, window.innerHeight) renderer.setAnimationLoop(render) camera.position.set(5, -12, 10) camera.rotation.set((60 / 180) * Math.PI, 0, 0) +camera.layers.enable(1) const entityMaterial = new THREE.MeshToonMaterial({ color: 0xffffff }) const terrainMaterial = new THREE.MeshToonMaterial({ color: 0xffd700 }) @@ -62,7 +63,7 @@ function followCamera() { if (entity == null) { return } const offsetX = 0 - const offsetY = -15 + const offsetY = -16.5 const distanceX = Math.abs((entity.position.x + offsetX) - camera.position.x) const distanceY = Math.abs((entity.position.y + offsetY) - camera.position.y) @@ -152,11 +153,30 @@ function connectWebSocket() { entity.userData.type = 'entity' entity.userData.id = e.id scene.add(entity) + + const hpMargin = 0.4 + const maxHp = new THREE.Sprite(new THREE.SpriteMaterial({ color: 0xd03333 })) + maxHp.position.set(0, (e.radius / 100) + hpMargin, 0) + maxHp.scale.set(1.5, 0.2, 1) + maxHp.layers.set(1) + entity.add(maxHp) + + const hp = new THREE.Sprite(new THREE.SpriteMaterial({ color: 0x77ff77 })) + hp.position.set(0, 0, 0) + hp.scale.set(1, 1, 1) + hp.layers.set(1) + maxHp.add(hp) + entities[e.id] = entity } // entity.position.set(e.position.x / 100, e.position.y / 100, e.radius / 100) positionTweens[entity.id] = new Tween(entity.position).to({ x: e.position.x / 100, y: e.position.y / 100, z: e.radius / 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 } for (const t of state.terrains ?? []) { diff --git a/public/sprite.png b/public/sprite.png new file mode 100644 index 0000000..bc3ea94 Binary files /dev/null and b/public/sprite.png differ diff --git a/src/entity.js b/src/entity.js index 5a7eca5..40f1ced 100644 --- a/src/entity.js +++ b/src/entity.js @@ -7,6 +7,8 @@ export default class Entity { id = crypto.randomUUID() speed = 400 radius = 0 + health = 1 + maxHealth = 1 #position = new Vector2() #dest = null diff --git a/src/index.js b/src/index.js index 6461863..ec3ce4a 100644 --- a/src/index.js +++ b/src/index.js @@ -3,6 +3,8 @@ import { WebSocketExpress } from 'websocket-express' import Game from './game.js' import Entity from './entity.js' import Terrain from './terrain.js' +import SATX from './satx.js' +import { Vector2 } from 'three' const app = new WebSocketExpress() const port = 1280 @@ -42,29 +44,23 @@ app.ws('/ws', async (req, res) => { }) }) -app.listen(port, () => { - console.log(`Server started! Visit http://localhost:${port}`) - +function testScenario() { const entity1 = new Entity() entity1.id = '1' entity1.teleport(200, 500) entity1.radius = 50 + entity1.maxHealth = 100 + entity1.health = 80 game.spawn_entity(entity1) const entity2 = new Entity() entity2.id = '2' entity2.teleport(110, 110) entity2.radius = 50 + entity2.maxHealth = 50 + entity2.health = 50 game.spawn_entity(entity2) - // const triangle = new Terrain([ - // { x: 400, y: 200 }, - // { x: 400, y: 600 }, - // { x: 600, y: 300 }, - // ]) - // triangle.id = 'triangle' - // game.add_terrain(triangle) - const horseshoe = new Terrain([ { x: 400, y: 200 }, { x: 600, y: 200 }, @@ -119,9 +115,55 @@ app.listen(port, () => { ]) pole.id = 'pole' game.add_terrain(pole) +} - // entity1.moveAction(750, 950) - // setTimeout(() => entity1.moveAction(100, 400), 10) +function laneScenario() { + const entity1 = new Entity() + entity1.id = '1' + entity1.teleport(200, 200) + entity1.radius = 50 + entity1.maxHealth = 100 + entity1.health = 100 + game.spawn_entity(entity1) + + const entity2 = new Entity() + entity2.id = '2' + entity2.teleport(1800, 1800) + entity2.radius = 50 + entity2.maxHealth = 100 + entity2.health = 100 + game.spawn_entity(entity2) + + const midWallStart = new Vector2(400, 400) + const midWallEnd = new Vector2(1600, 1600) + const midWallMiddle = new Vector2(800, 1200) + const midWallThickness = midWallEnd.clone().sub(midWallStart).rotateAround(new Vector2(), -Math.PI / 2).normalize().multiplyScalar(50) + const midWallPoints = [ + midWallStart, + midWallMiddle, + midWallEnd, + midWallEnd.clone().add(midWallThickness), + midWallMiddle.clone().add(midWallThickness), + midWallStart.clone().add(midWallThickness), + ] + + const midNorthWallOffset = new Vector2(-200, 200) + const midNorthWallPoints = midWallPoints.map((p) => p.clone().add(midNorthWallOffset)) + const midNorthWall = new Terrain(midNorthWallPoints) + midNorthWall.id = 'midNorthWall' + game.add_terrain(midNorthWall) + + const midSouthWallOffset = new Vector2(200, -200) + const midSouthWallPoints = midWallPoints.map((p) => p.clone().add(midSouthWallOffset)) + const midSouthWall = new Terrain(midSouthWallPoints) + midSouthWall.id = 'midSouthWall' + game.add_terrain(midSouthWall) +} + +app.listen(port, () => { + console.log(`Server started! Visit http://localhost:${port}`) + + laneScenario() game.start() })