import express from 'express' import { WebSocketExpress } from 'websocket-express' import Game from './game.js' import Entity from './entity.js' import Terrain from './terrain.js' import { Vector2 } from 'three' const app = new WebSocketExpress() const port = 1280 const game = new Game() app.use('/', express.static('public')) app.use('/three/', express.static('node_modules/three')) app.use('/@tweenjs/', express.static('node_modules/@tweenjs')) app.use(express.urlencoded({ extended: true })) app.ws('/ws', async (req, res) => { const websocket = await res.accept() const subscription = () => websocket.send(JSON.stringify(game.state())) game.eventEmitter.on('tick', subscription) websocket.on('close', () => { game.eventEmitter.removeListener('tick', subscription) }) websocket.on('message', (rawData) => { const message = JSON.parse(rawData) const entity = message.id != null ? game.entities.find((e) => e.id == message.id) : null if (entity == null) { console.log({ error: { reason: 'Invalid ID', message } }) return } console.log(message) // DEPRECATED: teleporting is now directly possible via Ability... if (message.action == 'teleport') { entity.teleport(new Vector2(message.x, message.y)) } if (message.action == 'attack') { entity.attackAction(message.x, message.y) } if (message.action == 'cast') { entity.castAction(message.slot, message.x, message.y) } if (message.action == 'halt') { entity.haltAction() } if (message.action == 'stop') { entity.stopAction() } if (message.action == 'move') { entity.moveAction(message.x, message.y) } }) }) function testScenario() { const entity1 = new Entity() entity1.id = '1' entity1.teleport(new Vector2(200, 500)) entity1.radius = 50 entity1.maxHealth = 100 entity1.health = 80 game.spawnEntity(entity1) const entity2 = new Entity() entity2.id = '2' entity2.teleport(new Vector2(110, 110)) entity2.radius = 50 entity2.maxHealth = 50 entity2.health = 50 game.spawnEntity(entity2) const horseshoe = new Terrain([ { x: 400, y: 200 }, { x: 600, y: 200 }, { x: 700, y: 300 }, { x: 650, y: 600 }, { x: 400, y: 600 }, { x: 400, y: 450 }, { x: 600, y: 500 }, { x: 600, y: 300 }, { x: 400, y: 300 }, ]) horseshoe.id = 'horseshoe' game.addTerrain(horseshoe) const stopsign = new Terrain([ { x: 800, y: 800 }, { x: 900, y: 900 }, { x: 900, y: 1000 }, { x: 800, y: 1100 }, { x: 800, y: 1100 }, { x: 700, y: 1100 }, { x: 600, y: 1000 }, { x: 600, y: 900 }, { x: 700, y: 800 }, ]) stopsign.id = 'stopsign' game.addTerrain(stopsign) const box = new Terrain([ { x: 1200, y: 700 }, { x: 1200, y: 800 }, { x: 1300, y: 800 }, { x: 1300, y: 700 }, ]) box.id = 'box' game.addTerrain(box) const diamond = new Terrain([ { x: 1000, y: 300 }, { x: 1100, y: 400 }, { x: 1000, y: 500 }, { x: 900, y: 400 }, ]) diamond.id = 'diamond' game.addTerrain(diamond) const pole = new Terrain([ { x: 400, y: 1000 }, { x: 410, y: 1000 }, { x: 410, y: 1010 }, { x: 400, y: 1010 }, ]) pole.id = 'pole' game.addTerrain(pole) } function laneScenario() { const entity1 = new Entity() entity1.id = '1' entity1.teleport(new Vector2(200, 200)) entity1.radius = 50 entity1.maxHealth = 100 entity1.health = 100 game.spawnEntity(entity1) const entity2 = new Entity() entity2.id = '2' entity2.teleport(new Vector2(1800, 1800)) entity2.radius = 50 entity2.maxHealth = 100 entity2.health = 100 game.spawnEntity(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.addTerrain(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.addTerrain(midSouthWall) } app.listen(port, () => { console.log(`Server started! Visit http://localhost:${port}`) laneScenario() game.entities[0].castAction(3, 2000, 2000) game.start() })