diff --git a/common/player.js b/common/player.js index 8e6825b..8d288fb 100644 --- a/common/player.js +++ b/common/player.js @@ -50,76 +50,77 @@ class Player extends Entity { player.ticks = 0; } + handleInt(target) { + if (target.you == this.you) return; + + let dist = distF(this, target); + + let dp = (Math.sin(this.rot) * (this.pos.x - target.pos.x)) + - (Math.cos(this.rot) * (this.pos.y - target.pos.y)); + + dp /= Math.sqrt(dist + 0.1); + + if (!(Math.sqrt(dist) < 128 && 1 / dp < -0.2)) return; + + let velness = Math.sqrt(this.vel.x ** 2 + this.vel.y ** 2); + + if (target.type == 'NPC' && velness > 0.2 && this.ticks >= 15) { + this.isMenu = true; + this.rot = 1.2; + } + + if (target.type == 'Shooter') { + this.health -= 1; + } + + if (target.immortal) return; + + let oldHealth = target.health + + let dmg = Math.floor((dp - 0.001) * 10); + + target.health += Math.floor((dp - 0.001) * 10); + + target.vel.x += (target.pos.x - this.pos.x) * 0.1; + target.vel.y += (target.pos.y - this.pos.y) * 0.1; + + if (target.health <= 0 && oldHealth > 0) { + console.log(`Player ${target.you} died to a player ${this.you}`); + this.health -= dmg; + if (this.health > 100) this.health = 100; + this.headCount += 500; + } + } handleTick(game) { - let { entities, width, height } = game; - let ent = this; - ent.headCount += 1/200; + this.headCount += 1 / 200; - ent.headCount = Math.round(ent.headCount * 1000) / 1000; + this.headCount = Math.round(this.headCount * 1000) / 1000; - if (ent.health <= 0) return; + if (this.health <= 0) return; - ent.pos.x += ent.vel.x; - ent.pos.y += ent.vel.y; + this.pos.x += this.vel.x; + this.pos.y += this.vel.y; - ent.pos.x = Math.max(Math.min(ent.pos.x, width / 2), - width / 2); - ent.pos.y = Math.max(Math.min(ent.pos.y, height / 2), - height / 2); + this.pos.x = Math.max(Math.min(this.pos.x, width / 2), - width / 2); + this.pos.y = Math.max(Math.min(this.pos.y, height / 2), - height / 2); - ent.bounce(game); + this.bounce(game); - ent.vel.x *= 0.9; - ent.vel.y *= 0.9; + this.vel.x *= 0.9; + this.vel.y *= 0.9; - ent.rot += 0.03 * ent.dir; - ent.rot = ent.rot % (Math.PI * 10); + this.rot += 0.03 * this.dir; + this.rot = this.rot % (Math.PI * 10); - ent.camera.x = -ent.pos.x * 0.1 + ent.camera.x * 0.9; - ent.camera.y = -ent.pos.y * 0.1 + ent.camera.y * 0.9; + this.camera.x = -this.pos.x * 0.1 + this.camera.x * 0.9; + this.camera.y = -this.pos.y * 0.1 + this.camera.y * 0.9; - ent.ticks++; - - let velness = Math.sqrt(ent.vel.x ** 2 + ent.vel.y ** 2); + this.ticks++; for (let target of entities) { - if (target.you == ent.you) continue; - - let dist = distF(ent, target); - - let dp = (Math.sin(ent.rot) * (ent.pos.x - target.pos.x)) - - (Math.cos(ent.rot) * (ent.pos.y - target.pos.y)); - - dp /= Math.sqrt(dist + 0.1); - - if (Math.sqrt(dist) < 128 && 1 / dp < -0.2) { - if (target.type == 'NPC' && velness > 0.2 && ent.ticks >= 15) { - ent.isMenu = true; - ent.rot = 1.2; - } - - if (target.type == 'Shooter') { - this.health -= 1; - } - - if (target.immortal) continue; - - let oldHealth = target.health - - let dmg = Math.floor((dp - 0.001) * 10); - - target.health += Math.floor((dp - 0.001) * 10); - - target.vel.x += (target.pos.x - ent.pos.x) * 0.1; - target.vel.y += (target.pos.y - ent.pos.y) * 0.1; - - if (target.health <= 0 && oldHealth > 0) { - console.log(`Player ${target.you} died to a player ${ent.you}`); - ent.health -= dmg; - if (ent.health > 100) ent.health = 100; - ent.headCount += 500; - } - } + this.handleInt(target); } } } diff --git a/game.js b/game.js index 043a6fa..fb7b54c 100644 --- a/game.js +++ b/game.js @@ -1,6 +1,7 @@ import GameBasic from "./common/game_basic.js"; import NPC from "./common/npc.js"; import Shooter from "./common/shooter.js"; +import fetch from "node-fetch"; import initDb from './db.js'; @@ -115,6 +116,40 @@ class Game extends GameBasic { setInterval(function () { that.sync(false) }, 1000 / 10); setInterval(function () { that.sync(true) }, 1000); + setInterval(function () { that.clean() }, 1000); + } + + clean() { + for (let ent in this.entities) { + let x = this.entities[ent]; + if ( x.health > 0 || x.type != 'Player') return; + this.entites[ent] = false; + } + } + + async authUser(ws, data) { + ws.token = data; + + let f = new FormData(); + f.append('token', ws.token); + + let j = await fetch("https://bg.xuyezo.net/api/form/auth_api/", + { + "method": "post", + "body": f + } + ); + j = await j.json(); + + if (j.username == '!nobody' || !j.username) return; + + if (this.ws.findIndex(x => x.username == j.username && x.ent.health > 0) != -1) { + console.log(`Player ${ws.ent.you} uses username ${j.username} illegally`) + return; + } + ws.ent.username = ws.username = j.username; + + console.log(`Player ${ws.ent.you} uses username ${ws.username}`) } } diff --git a/index.js b/index.js index 4aea6d5..1d590ba 100644 --- a/index.js +++ b/index.js @@ -3,7 +3,6 @@ import expressW from "express-ws"; import Game from "./game.js"; import NPC from "./common/npc.js"; import Player from "./common/player.js"; -import fetch from "node-fetch"; import initDb from "./db.js"; @@ -13,7 +12,6 @@ var app = express(); expressW(app); var game = new Game(); - game.init(); app.use('/crypto.js', express.static('./common/crypto.js')); @@ -49,27 +47,7 @@ app.ws('/', function (ws, req) { let type = data[0]; if (type == 'AUTH') { - ws.token = data[1]; - - let f = new FormData(); - f.append('token', ws.token); - - (async function () { - let j = await fetch("https://bg.xuyezo.net/api/form/auth_api/", - { - "method": "post", - "body": f - } - ); - j = await j.json(); - if (game.ws.findIndex(x => x.username == j.username && x.health >= 0) != -1) { - console.log(`Player ${player.you} uses username ${x.username} illegally`) - return; - } - ws.ent.username = ws.username = j.username; - - console.log(`Player ${player.you} uses username ${ws.username}`) - })() + game.authUser(ws,data[1]); return; } diff --git a/static/js/index.js b/static/js/index.js index 09bfacb..4a7eff7 100644 --- a/static/js/index.js +++ b/static/js/index.js @@ -51,6 +51,51 @@ class Game extends GameBasic { this.ctx = canvas.getContext("2d"); this.assetsIn = assetsIn; } + renderEnt(ent, textArgs) { + let { ctx, assetsIn } = this; + + if (ent.health <= 0) return; + + if (ent.type == 'Player') { + ctx.save(); + + ctx.translate(ent.pos.x, ent.pos.y); + ctx.rotate(ent.rot); + ctx.drawImage(assetsIn[1], -64 / 2, -128, 64, 128); + + ctx.restore(); + + if (ent.playing) { + ctx.strokeStyle = 'white'; + ctx.lineWidth = "20"; + ctx.beginPath(); + ctx.arc(ent.pos.x, ent.pos.y, 32, 0, 2 * Math.PI); + ctx.stroke(); + } + + ctx.fillStyle = ent.you.split('-')[0]; + + ctx.beginPath(); + ctx.arc(ent.pos.x, ent.pos.y, 32, 0, 2 * Math.PI); + ctx.fill(); + } + + let a = assetsIn[bodies[ent.type]] + ctx.drawImage(a, ent.pos.x - 64 / 2, ent.pos.y - 64 / 2, 64, 64); + + if (ent.type != 'Player') return; + + Object.assign(textArgs, [`HP: ${ent.health} PT: ${ent.headCount}`, ent.pos.x, ent.pos.y - 64 / 2]); + + ctx.strokeText(...textArgs); + ctx.fillText(...textArgs); + + ctx.textBaseline = "top"; + Object.assign(textArgs, [`${ent.username || 'Guest'}`, ent.pos.x, ent.pos.y + 64 / 2]); + + ctx.strokeText(...textArgs); + ctx.fillText(...textArgs); + } render() { let { ctx, assetsIn, entities, player, width, height } = this; @@ -63,7 +108,7 @@ class Game extends GameBasic { ctx.lineCap = "round"; ctx.lineJoin = "round"; ctx.font = "bold 16px sans-serif"; - + ctx.save(); ctx.translate(player.camera.x + cs / 2, player.camera.y + cs / 2); @@ -73,47 +118,7 @@ class Game extends GameBasic { let textArgs = []; for (let ent of entities) { - if (ent.health <= 0) continue; - - if (ent.type == 'Player') { - ctx.save(); - - ctx.translate(ent.pos.x, ent.pos.y); - ctx.rotate(ent.rot); - ctx.drawImage(assetsIn[1], -64 / 2, -128, 64, 128); - - ctx.restore(); - - if (ent.playing) { - ctx.strokeStyle = 'white'; - ctx.lineWidth = "20"; - ctx.beginPath(); - ctx.arc(ent.pos.x, ent.pos.y, 32, 0, 2 * Math.PI); - ctx.stroke(); - } - - ctx.fillStyle = ent.you.split('-')[0]; - - ctx.beginPath(); - ctx.arc(ent.pos.x, ent.pos.y, 32, 0, 2 * Math.PI); - ctx.fill(); - } - - let a = assetsIn[bodies[ent.type]] - ctx.drawImage(a, ent.pos.x - 64 / 2, ent.pos.y - 64 / 2, 64, 64); - - if (ent.type != 'Player') continue; - - textArgs = [`HP: ${ent.health} PT: ${ent.headCount}`, ent.pos.x, ent.pos.y - 64 / 2]; - - ctx.strokeText(...textArgs); - ctx.fillText(...textArgs); - - ctx.textBaseline = "top"; - textArgs = [`${ent.username || 'Guest'}`, ent.pos.x, ent.pos.y + 64 / 2]; - - ctx.strokeText(...textArgs); - ctx.fillText(...textArgs); + this.renderEnt(ent, textArgs); } ctx.restore(); @@ -122,7 +127,7 @@ class Game extends GameBasic { ctx.textBaseline = "top"; ctx.font = "bold 32px sans-serif"; - textArgs = [`XY: ${-Math.round(player.camera.x)}, ${-Math.round(player.camera.y)}`,25,25]; + textArgs = [`XY: ${-Math.round(player.camera.x)}, ${-Math.round(player.camera.y)}`, 25, 25]; ctx.strokeText(...textArgs); ctx.fillText(...textArgs); @@ -179,6 +184,51 @@ class Game extends GameBasic { this.ws.send(JSON.stringify(p)); } + entMapper(j, i, entList) { + let that = this; + + let { player } = this; + let you = player.you; + + if (i == entList.length - 1) { + that.width = j[0]; + that.height = j[1]; + return undefined; + } + + if (!j) return undefined; + + let y = j; //(typeof j == 'string') ? JSON.parse(j) : j; + + let type = (Object.keys(legalTypes).indexOf(y[0]) == -1) ? Player : legalTypes[y[0]]; + + let props = new type().serverProps; + + let x = {}; + + for (let i in props) { + x[props[i]] = y[i]; + } + + let { handleTick, bounce, handleInt } = type.prototype; + Object.assign(x, { handleTick, bounce, handleInt }); + x.bounce = type.prototype.bounce; + if (x.r != 1 && type == Player) { + let a = new Audio(`sfx/${emojis[x.r]}.wav`); + a.addEventListener('ended', () => { + if (x.you == you) { + that.player.playing = false; + that.sync(); + } + a.remove(); + }) + if (you != x.you) { + x.r = 1; + } + a.play(); + } + return x; + } recv({ data }) { let { player } = this; let you = player.you; @@ -186,45 +236,7 @@ class Game extends GameBasic { let that = this; let entList = JSON.parse(data); - entList = entList.map((j, i) => { - if (i == entList.length - 1) { - that.width = j[0]; - that.height = j[1]; - return undefined; - } - - if (!j) return undefined; - - let y = j; //(typeof j == 'string') ? JSON.parse(j) : j; - - let type = (Object.keys(legalTypes).indexOf(y[0]) == -1) ? Player : legalTypes[y[0]]; - - let props = new type().serverProps; - - let x = {}; - - for (let i in props) { - x[props[i]] = y[i]; - } - - x.handleTick = type.prototype.handleTick; - x.bounce = type.prototype.bounce; - if (x.r != 1 && type == Player) { - let a = new Audio(`sfx/${emojis[x.r]}.wav`); - a.addEventListener('ended', () => { - if (x.you == you) { - that.player.playing = false; - that.sync(); - } - a.remove(); - }) - if (you != x.you) { - x.r = 1; - } - a.play(); - } - return x; - }) + entList = entList.map((j, i) => that.entMapper(j, i, entList)) entList = entList.filter(x => x); @@ -246,11 +258,11 @@ class Game extends GameBasic { if (this.entities.length == 0) this.entities = [this.player]; } - async init() { + init() { let u = new URL(window.location); let tok = u.searchParams.get('token'); if (!tok) tok = window.localStorage.getItem('tok'); - window.localStorage.setItem('tok',tok); + window.localStorage.setItem('tok', tok); window.history.replaceState(null, '', window.location.pathname); super.init(); @@ -266,7 +278,7 @@ class Game extends GameBasic { } setInterval(function () { that.sync() }, 1000 / 5); - that.ws.addEventListener('message', function (e) { that.recv(e) }); + that.ws.addEventListener('message', function (e) { that.recv(e) }); }; this.ws.addEventListener('open', () => this.opener(that)) @@ -275,7 +287,11 @@ class Game extends GameBasic { game.canvas.onclick = () => that.click(); - let jason = await (fetch('/leaderboard').then(x => x.json())) + this.handleScores(); + } + + async handleScores() { + let jason = await(fetch('/leaderboard').then(x => x.json())) let scores = {}; @@ -287,7 +303,7 @@ class Game extends GameBasic { for (let score in scores) { let s = scores[score]; scores[score] = Math.round(Math.sqrt(s)); - } + } scores = Object.entries(scores).sort((a, b) => b[1] - a[1]);