Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- var io = require('socket.io-client');
- var Canvas = require('./canvas');
- var global = require('./global');
- var color = require('./color');
- var playerNameInput = document.getElementById('playerNameInput');
- var playerKeyInput = document.getElementById('playerKeyInput');
- var socket;
- var reason;
- var angleDifference = function(sourceA, targetA) {
- let mod = function(a, n) {
- return (a % n + n) % n;
- };
- let a = targetA - sourceA;
- return mod(a + Math.PI, 2*Math.PI) - Math.PI;
- };
- if ( /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent) ) {
- global.mobile = true;
- }
- function strEncodeUTF16(str) {
- var buf = new ArrayBuffer(str.length*2);
- var bufView = new Uint16Array(buf);
- for (var i=0, strLen=str.length; i < strLen; i++) {
- bufView[i] = str.charCodeAt(i);
- }
- return bufView;
- }
- function strDecodeUTF16(arr) {
- let buf;
- if (arr.buffer == null) {
- let len = 0;
- for (let i=0; arr[i]!=null; i++) { len++; }
- buf = new Uint16Array(new ArrayBuffer(len*2));
- for (let i=0; i<len; i++) {
- buf[i] = arr[i];
- }
- } else {
- buf = new Uint16Array(arr);
- }
- return String.fromCharCode.apply(null, buf);
- }
- function submitToLocalStorage(name) {
- localStorage.setItem(name, document.getElementById(name).value);
- console.log(localStorage.getItem(name));
- return false;
- }
- function retrieveFromLocalStorage(name) {
- document.getElementById(name).value = localStorage.getItem(name);
- return false;
- }
- function startGame(type) {
- submitToLocalStorage('playerNameInput');
- submitToLocalStorage('playerKeyInput');
- global.playerName = strEncodeUTF16(playerNameInput.value);
- global.playerKey = playerKeyInput.value.replace(/(<([^>]+)>)/ig, '').substring(0, 64);
- global.playerType = type;
- global.screenWidth = window.innerWidth;
- global.screenHeight = window.innerHeight;
- document.getElementById('startMenuWrapper').style.maxHeight = '0px';
- document.getElementById('gameAreaWrapper').style.opacity = 1;
- if (!socket) {
- socket = io({query:"type=" + type});
- setupSocket(socket);
- }
- if (!global.animLoopHandle){
- animloop();
- }
- socket.emit('spawn', global.playerKey);
- window.canvas.socket = socket;
- global.socket = socket;
- }
- window.onload = function() { //Change the screen when we start play
- var btn = document.getElementById('startButton');
- retrieveFromLocalStorage('playerNameInput');
- retrieveFromLocalStorage('playerKeyInput');
- btn.onclick = function () {
- startGame('player');
- };
- playerNameInput.addEventListener('keypress', function (e) {
- var key = e.which || e.keyCode;
- if (key === global.KEY_ENTER) {
- startGame('player');
- }
- });
- };
- var config = {
- graphical: {
- screenshotMode: false,
- },
- },
- player = { //Set up the player
- id: -1,
- x: global.screenWidth / 2,
- y: global.screenHeight / 2,
- vx: 0,
- vy: 0,
- renderx: global.screenWidth / 2,
- rendery: global.screenHeight / 2,
- renderv: 1,
- slip: 0,
- view: 1,
- time: 0,
- screenWidth: global.screenWidth,
- screenHeight: global.screenHeight,
- target: {x: global.screenWidth / 2, y: global.screenHeight / 2}
- },
- entities = [],
- users = [],
- gui = {
- skills: {
- typeData:[],
- points: 0,
- },
- upgrades: [],
- score: 0,
- progress: 0,
- level: 0,
- type: "Unknown Entity"
- },
- minimap = [],
- leaderboard = [],
- leaderboardScore = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0,],
- upgradeSpin = 0,
- messages = [],
- mockups = [],
- messageFade = 0,
- newMessage = 0,
- metrics = {
- latency: 0,
- lag: 0,
- rendertime: 0,
- updatetime: 0,
- lastlag: 0,
- lastrender: 0,
- rendergap: 0,
- lastuplink: 0,
- },
- lastPing = 0,
- renderTimes = 0,
- updateTimes = 0,
- target = {x: player.x, y: player.y},
- roomSetup = [ [ 'norm'] ];
- global.target = target;
- global.player = player;
- global.canUpgrade = false;
- global.canSkill = false;
- global.messages = '';
- global.time = 0;
- window.canvas = new Canvas();
- var c = window.canvas.cv,
- ctx = c.getContext('2d'),
- c2 = document.createElement('canvas'),
- ctx2 = c2.getContext('2d');
- ctx2.imageSmoothingEnabled = false;
- function convertRawData(data) {
- function process(i) {
- return {
- id: i[0][0],
- index: i[0][1],
- x: i[0][2],
- y: i[0][3],
- vx: i[0][4],
- vy: i[0][5],
- size: i[0][6],
- realSize: i[0][7],
- fade: i[0][8],
- color: i[0][9],
- blend: {
- color: i[0][10],
- amount: i[0][11],
- },
- health: i[0][12],
- shield: i[0][13],
- coherence: i[0][14],
- facing: i[0][15],
- shape: i[0][16],
- name: i[0][17],
- score: i[0][18],
- twiggle: i[0][19],
- layer: i[0][20],
- vfacing: i[0][21],
- nameplate: i[0][22],
- guns: i[1],
- turrets: i[2].map((t) => { return process(t); }),
- };
- }
- return data.map((datum) => {
- datum = process(datum);
- let e = entities.find(x => x.id === datum.id);
- if (e != null) {
- e.render.lastx = e.x;
- e.render.lasty = e.y;
- e.render.lastvx = e.vx;
- e.render.lastvy = e.vy;
- e.render.lastf = e.facing;
- let save = e.render;
- e = datum;
- e.render = save;
- } else {
- e = datum;
- e.render = {
- x: datum.x,
- y: datum.y,
- lastx: datum.x,
- lasty: datum.y,
- lastvx: datum.vx,
- lastvy: datum.vy,
- lastf: datum.facing,
- f: datum.facing,
- h: datum.health,
- s: datum.shield,
- slip: 0,
- };
- }
- return e;
- });
- }
- function getEntityImageFromMockup(index, color = mockups[index].color) {
- let mockup = mockups[index];
- return {
- time: 0,
- index: index,
- x: mockup.x,
- y: mockup.y,
- vx: 0,
- vy: 0,
- size: mockup.size,
- realSize: mockup.realSize,
- fade: 1,
- color: color,
- blend: {
- color: '#FFFFFF',
- amount: 0,
- },
- health: 1,
- shield: 0,
- coherence: 1,
- facing: mockup.facing,
- shape: mockup.shape,
- name: mockup.name,
- score: 0,
- tiggle: 0,
- layer: mockup.layer,
- guns: mockup.guns.map(() => { return 0; }),
- turrets: mockup.turrets.map((t) => {
- let o = getEntityImageFromMockup(t.type);
- o.realSize = o.realSize / o.size * mockup.size * t.sizeFactor;
- o.size = mockup.size * t.sizeFactor;
- o.x += mockup.x + mockup.size * t.offset * Math.cos(t.direction + t.angle);
- o.y += mockup.y + mockup.size * t.offset * Math.sin(t.direction + t.angle);
- o.facing = t.direction + t.angle;
- o.layer = t.layerOverride;
- return o;
- }),
- };
- }
- function setupSocket(socket) { // Socket stuff.x`
- socket.on('disconnect', function(m) { // System disconnection
- global.disconnected = true;
- global.messages = m;
- socket.close();
- });
- socket.on('kick', function(m) { // Manual disconnection
- if (global.gameStart) global.disconnected = true;
- global.messages = m;
- });
- socket.on('welcome', function(playerSettings) { // Handle connection.
- player = playerSettings;
- player.name = global.playerName;
- player.screenWidth = global.screenWidth;
- player.screenHeight = global.screenHeight;
- player.vx = 0;
- player.vy = 0;
- player.renderx = player.x;
- player.rendery = player.y;
- player.lastx = player.x;
- player.lasty = player.y;
- player.lastvx = 0;
- player.lastvy = 0;
- player.target = window.canvas.target;
- global.player = player;
- socket.emit('gotit', player); //Say hi back to mama server
- global.gameStart = true;
- c.focus();
- });
- socket.on('gameSetup', function(data, mockupData, setup) { // Initalization call
- global.gameWidth = data.gameWidth;
- global.gameHeight = data.gameHeight;
- resize();
- mockups = mockupData;
- roomSetup = setup;
- });
- socket.on('uplink', function(camera, entityList, newGui) { // Handle updates.
- var ratio = Math.max(global.screenWidth / player.renderv, global.screenHeight / player.renderv / 9 * 16);
- socket.emit('downlink', { // Send a heartbeat back to the server
- x: window.canvas.target.x / ratio,
- y: window.canvas.target.y / ratio,
- }, Math.max(player.time, camera.time));
- if (camera.time > player.time || player.time == null) { // Don't accept out-of-date information.
- metrics.lastuplink = Date.now();
- metrics.rendergap = metrics.lastuplink - player.time;
- player.time = camera.time;
- player.lastx = player.x;
- player.lasty = player.y;
- player.x = camera.x;
- player.y = camera.y;
- player.lastvx = player.vx;
- player.lastvy = player.vy;
- player.vx = camera.vx;
- player.vy = camera.vy;
- if (isNaN(player.renderx)) { player.renderx = player.x; }
- if (isNaN(player.rendery)) { player.rendery = player.y; }
- player.view = camera.view;
- if (isNaN(player.renderv) || player.renderv === 0) { player.renderv = 2000; }
- entities = convertRawData(entityList);
- gui = newGui;
- metrics.lastlag = metrics.lag;
- } else { console.log("Old data!"); }
- updateTimes++; // metrics
- });
- socket.on('minimapUpdate', function(newMap, newLeaderboard) { // Update the minimap
- minimap = newMap;
- leaderboard = newLeaderboard;
- });
- socket.on('RIP', function() { // Death
- global.died = true;
- /*if (global.animLoopHandle) {
- window.cancelAnimationFrame(global.animLoopHandle);
- }*/
- });
- socket.on('message', function(message) { // Death
- messages.push({
- text: message,
- status: 2,
- alpha: 0,
- time: Date.now(),
- });
- });
- socket.on('pongcheck', function(t) {
- console.log('!Pong!');
- metrics.latency = global.time - t;
- });
- }
- function getColor(colorNumber) {
- switch (colorNumber) {
- case 0: return color.teal;
- case 1: return color.lgreen;
- case 2: return color.orange;
- case 3: return color.yellow;
- case 4: return color.lavender;
- case 5: return color.pink;
- case 6: return color.vlgrey;
- case 7: return color.lgrey;
- case 8: return color.guiwhite;
- case 9: return color.black;
- case 10: return color.blue;
- case 11: return color.green;
- case 12: return color.red;
- case 13: return color.gold;
- case 14: return color.purple;
- case 15: return color.magenta;
- case 16: return color.grey;
- case 17: return color.dgrey;
- case 18: return color.white;
- case 19: return color.guiblack;
- default: return '#FF0000';
- }
- }
- function getColorDark(colorNumber) {
- return color.black;
- }
- function getZoneColor(cell, real) {
- switch (cell) {
- case 'bas1': return color.blue;
- case 'bas2': return color.pink;
- case 'bas3': return color.red;
- case 'bas4': return color.green;
- case 'nest': return (real) ? color.purple : color.lavender;
- default: return (real) ? color.white : color.lgrey;
- }
- }
- function mixColors(color_2, color_1, weight = 0.5) {
- /** https://gist.github.com/jedfoster/7939513 **/
- function d2h(d) { return d.toString(16); } // convert a decimal value to hex
- function h2d(h) { return parseInt(h, 16); } // convert a hex value to decimal
- if (weight === 1) return color_1;
- if (weight === 0) return color_2;
- var color = "#";
- for(var i = 1; i <= 6; i += 2) { // loop through each of the 3 hex pairs—red, green, and blue, skip the '#'
- var v1 = h2d(color_1.substr(i, 2)), // extract the current pairs
- v2 = h2d(color_2.substr(i, 2)),
- // combine the current pairs from each source color, according to the specified weight
- val = d2h(Math.floor(v2 + (v1 - v2) * weight));
- while(val.length < 2) { val = '0' + val; } // prepend a '0' if val results in a single digit
- color += val; // concatenate val to our new color string
- }
- return color; // PROFIT!
- }
- function clearScreen(clearColor, alpha) {
- ctx.fillStyle = clearColor;
- ctx.globalAlpha = alpha;
- ctx.fillRect(0, 0, global.screenWidth, global.screenHeight);
- ctx.globalAlpha = 1;
- }
- function drawText(text, x, y, size, fillColor, angle = 0){
- ctx.lineWidth = Math.max(3, size/5);
- if (angle) {
- ctx.save();
- ctx.translate(x, y);
- ctx.rotate(-angle * Math.PI / 180);
- ctx.strokeStyle = color.black;
- ctx.fillStyle = fillColor;
- ctx.font = 'bold ' + size + 'px Ubuntu';
- ctx.strokeText(text, x, y);
- ctx.fillText(text, x, y);
- ctx.restore();
- } else {
- ctx.strokeStyle = color.black;
- ctx.fillStyle = fillColor;
- ctx.font = 'bold ' + size + 'px Ubuntu';
- ctx.strokeText(text, x, y);
- ctx.fillText(text, x, y);
- }
- }
- function measureText(text, size) {
- ctx.font = 'bold ' + size + 'px Ubuntu';
- return ctx.measureText(text).width;
- }
- function drawCircle(context, centerX, centerY, radius, sides, angle = 0, fill = true) {
- let theta;
- let x = 0;
- let y = 0;
- angle += (sides % 2) ? 0 : Math.PI / sides;
- context.beginPath();
- if (sides < 0) {
- let dip = 1 - ( 6 / sides / sides);
- sides = -2 * sides;
- let appliedDip = 1;
- context.lineJoin = 'miter';
- for (let i=0; i < sides; i++) {
- theta = (i / sides) * 2 * Math.PI;
- x = centerX + radius * appliedDip * Math.cos(theta + angle);
- y = centerY + radius * appliedDip * Math.sin(theta + angle);
- if (appliedDip === 1) { appliedDip = dip; } else { appliedDip = 1; }
- context.lineTo(x, y);
- }
- } else {
- for (let i=0; i < sides; i++) {
- theta = (i / sides) * 2 * Math.PI;
- x = centerX + radius * Math.cos(theta + angle);
- y = centerY + radius * Math.sin(theta + angle);
- context.lineTo(x, y);
- }
- }
- context.closePath();
- context.stroke();
- context.lineJoin = 'round';
- if (fill) { context.fill(); }
- }
- function drawTrapezoid(context, x, y, length, height, aspect, angle) {
- let h = [];
- h = (aspect > 0) ?
- [ height * aspect, height ] :
- [ height, -height * aspect ];
- let r = [
- Math.atan2(h[0], length),
- Math.atan2(h[1], length)
- ];
- let l = [
- Math.sqrt(length * length + h[0] * h[0]),
- Math.sqrt(length * length + h[1] * h[1])
- ];
- context.beginPath();
- context.lineTo(x + l[0] * Math.cos(angle + r[0]), y + l[0] * Math.sin(angle + r[0]));
- context.lineTo(x + l[1] * Math.cos(angle + Math.PI - r[1]), y + l[1] * Math.sin(angle + Math.PI - r[1]));
- context.lineTo(x + l[1] * Math.cos(angle + Math.PI + r[1]), y + l[1] * Math.sin(angle + Math.PI + r[1]));
- context.lineTo(x + l[0] * Math.cos(angle - r[0]), y + l[0] * Math.sin(angle - r[0]));
- context.closePath();
- context.stroke();
- context.fill();
- }
- function drawGuiRect(x, y, length, height, stroke = false) {
- switch (stroke) {
- case true: ctx.strokeRect(Math.round(x) + 0.5, Math.round(y) + 0.5, Math.round(length), Math.round(height)); break;
- case false: ctx.fillRect(Math.round(x) + 0.5, Math.round(y) + 0.5, Math.round(length), Math.round(height)); break;
- }
- }
- function drawGuiLine(x1, y1, x2, y2) {
- ctx.beginPath();
- ctx.lineTo(Math.round(x1) + 0.5, Math.round(y1) + 0.5);
- ctx.lineTo(Math.round(x2) + 0.5, Math.round(y2) + 0.5);
- ctx.closePath();
- ctx.stroke();
- }
- function drawEntity(x, y, instance, ratio, scale=1, rot=0, turretsObeyRot=1, assignedContext=false) {
- let drawSize = scale * ratio * instance.size * (1 + 0.5 * (1 - instance.fade));
- let m = mockups[instance.index];
- context = (assignedContext) ? assignedContext : ctx;
- let xx = x, yy = y;
- if (assignedContext != ctx2 && instance.fade !== 1) {
- context = ctx2;
- context.canvas.width = drawSize * m.position.axis + ratio * 10;
- context.canvas.height = drawSize * m.position.axis + ratio * 10;
- xx = context.canvas.width / 2 - drawSize * m.position.axis * m.position.middle.x * Math.cos(rot) / 4;
- yy = context.canvas.height / 2 - drawSize * m.position.axis * m.position.middle.x * Math.sin(rot) / 4;
- }
- // Draw guns
- context.lineWidth = Math.max(2, ratio*4);
- context.fillStyle = mixColors(color.grey, instance.blend.color, instance.blend.amount);
- context.strokeStyle = color.black;
- if (instance.guns.length === m.guns.length) {
- for (let i=0; i<m.guns.length; i++) {
- let g = m.guns[i],
- position = instance.guns[i],
- gx =
- g.offset * Math.cos(g.direction + g.angle + rot) +
- (g.length - position) / 2 * Math.cos(g.angle + rot),
- gy =
- g.offset * Math.sin(g.direction + g.angle + rot) +
- (g.length - position) / 2 * Math.sin(g.angle + rot);
- drawTrapezoid(
- context,
- xx + drawSize * gx,
- yy + drawSize * gy,
- drawSize * g.length / 2,
- drawSize * g.width / 2,
- g.aspect,
- g.angle + rot
- );
- }
- } else { throw ("Mismatch gun number with mockup."); }
- // Draw turrets beneath us
- instance.turrets.forEach((t) => {
- if (t.layer === 0) {
- if (turretsObeyRot*rot) {
- let ang = Math.atan2(t.y, t.x) + turretsObeyRot*rot,
- len = Math.sqrt(t.y * t.y + t.x * t.x) * drawSize / instance.size;
- drawEntity(xx + len * Math.cos(ang), yy + len * Math.sin(ang), t, ratio, scale, turretsObeyRot*rot + t.facing, turretsObeyRot, context);
- } else {
- drawEntity(xx + scale * ratio * t.x, yy + scale * ratio * t.y, t, ratio, scale, turretsObeyRot*rot + t.facing, turretsObeyRot, context);
- }
- }
- });
- // Draw body
- let sides = (instance.shape) ? instance.shape : 25; // Default sides for a circle shall be 30.
- context.fillStyle = mixColors(getColor(instance.color), instance.blend.color, instance.blend.amount);
- context.strokeStyle = getColorDark(instance.color);
- drawCircle(context, xx, yy, drawSize / instance.size * instance.realSize, sides, rot);
- // Draw turrets above us
- instance.turrets.forEach((t) => {
- if (t.layer === 1) {
- if (turretsObeyRot*rot) {
- let ang = Math.atan2(t.y, t.x) + turretsObeyRot*rot,
- len = Math.sqrt(t.y * t.y + t.x * t.x) * scale*ratio;
- drawEntity(xx + len * Math.cos(ang), yy + len * Math.sin(ang), t, ratio, scale, turretsObeyRot*rot + t.facing, turretsObeyRot, context);
- } else {
- drawEntity(xx + scale*ratio * t.x, yy + scale*ratio * t.y, t, ratio, scale, turretsObeyRot*rot + t.facing, turretsObeyRot, context);
- }
- }
- });
- if (assignedContext == false && context != ctx) {
- ctx.globalAlpha = instance.fade;
- ctx.imageSmoothingEnabled = false;
- //ctx.globalCompositeOperation = "overlay";
- ctx.drawImage(context.canvas, x - xx, y - yy);
- ctx.globalAlpha = 1;
- ctx.imageSmoothingEnabled = true;
- //ctx.globalCompositeOperation = "source-over";
- }
- }
- function handleLargeNumber(a, cullZeroes = false) {
- if (cullZeroes && a == 0) {
- return '';
- }
- if (a < Math.pow(10, 3)) {
- return '' + a.toFixed(0);
- }
- if (a < Math.pow(10, 6)) {
- return (a / Math.pow(10, 3)).toFixed(2) + "k";
- }
- if (a < Math.pow(10, 9)) {
- return (a / Math.pow(10, 6)).toFixed(2) + "m";
- }
- if (a < Math.pow(10, 12)) {
- return (a / Math.pow(10, 9)).toFixed(2) + "b";
- }
- if (a < Math.pow(10, 15)) {
- return (a / Math.pow(10, 12)).toFixed(2) + "t";
- }
- return (a / Math.pow(10, 15)).toFixed(2) + "q";
- }
- function drawBar(x1, x2, y, width, color) {
- ctx.beginPath();
- ctx.lineTo(x1, y);
- ctx.lineTo(x2, y);
- ctx.lineWidth = width;
- ctx.strokeStyle = color;
- ctx.closePath();
- ctx.stroke();
- }
- function drawHealth(x, y, instance, ratio) {
- // Draw health bar
- let alpha = instance.fade * instance.fade;
- ctx.globalAlpha = alpha;
- let size = instance.size * ratio;
- let realSize = instance.realSize * ratio;
- if (instance.health < 0.99 || instance.shield < 0.99) {
- let yy = y + 1.1*realSize + 15;
- drawBar(x-size, x+size, yy, 6, color.black);
- drawBar(x-size, x-size+2*size*instance.health, yy, 3, color.lgreen);
- ctx.globalAlpha = instance.coherence*0.9;
- drawBar(x-size, x-size+2*size*instance.shield, yy, 3, color.teal);
- }
- ctx.globalAlpha = 1;
- // Draw label
- if (instance.nameplate) {
- ctx.lineWidth = 3;
- ctx.textAlign = 'center';
- drawText(strDecodeUTF16(instance.name), x, y - realSize - 24, 16, color.guiwhite);
- drawText(handleLargeNumber(instance.score, true), x, y - realSize - 10, 8, color.guiwhite);
- }
- }
- window.requestAnimFrame = (function() {
- return window.requestAnimationFrame ||
- window.webkitRequestAnimationFrame ||
- window.mozRequestAnimationFrame ||
- window.msRequestAnimationFrame ||
- function( callback ) {
- //window.setTimeout(callback, 1000 / 60);
- };
- })();
- window.cancelAnimFrame = (function(handle) {
- return window.cancelAnimationFrame ||
- window.mozCancelAnimationFrame;
- })();
- function gameDraw(ratio) { // Draws the game environment and the gui above that
- ctx.lineCap = 'round';
- ctx.lineJoin = 'round';
- renderGap = (global.time - metrics.lastrender);
- renderTimes++;
- try {
- interpolateMotion = (v1, v2, t) => {
- let tt = 1 + t / metrics.rendergap;
- return (Math.abs(v1 + v2) < 0.001) ? tt : tt * (v1 + 0.5 * tt * (v2 - v1)) / (v1 + 0.5 * (v2 - v1));
- };
- extrapolateMotion = (v1, v2, t) => {
- let wubt = t, // (t <= 1000) ? t : 10 * Math.log(1 + (t - 1000) / 10) + 1000,
- tt = 30 * wubt / 1000,
- drop = Math.min(1, Math.max(0, 1.5 - t / 1000));
- return (v2 + wubt / metrics.rendergap * (v2 - v1)) * tt * drop;
- };
- let t = gui.fps * (global.time - player.time - Math.max(metrics.rendergap, 50));
- { // Move the camera
- player.renderx = (t >= 0) ?
- player.x + extrapolateMotion(player.lastvx, player.vx, t) :
- player.lastx + (player.x - player.lastx) * interpolateMotion(player.lastvx, player.vx, t);
- player.rendery = (t >= 0) ?
- player.y + extrapolateMotion(player.lastvy, player.vy, t) :
- player.lasty + (player.y - player.lasty) * interpolateMotion(player.lastvy, player.vy, t);
- px = ratio * player.renderx;
- py = ratio * player.rendery;
- }
- { // Clear the background + draw grid
- clearScreen(color.white, 1);
- clearScreen(color.guiblack, 0.1);
- let W = roomSetup[0].length, H = roomSetup.length, i = 0;
- roomSetup.forEach((row) => {
- let j = 0;
- row.forEach((cell) => {
- let left = Math.max(0, ratio*i*global.gameWidth/W - px + global.screenWidth / 2),
- top = Math.max(0, ratio*j*global.gameHeight/H - py + global.screenHeight / 2),
- right = Math.min(global.screenWidth, (ratio*(i+1)*global.gameWidth/W - px) + global.screenWidth / 2),
- bottom = Math.min(global.screenHeight, (ratio*(j+1)*global.gameHeight/H - py) + global.screenHeight / 2);
- ctx.globalAlpha = 1;
- ctx.fillStyle = (config.graphical.screenshotMode) ? color.guiwhite : color.white;
- ctx.fillRect(left, top, right-left, bottom-top);
- ctx.globalAlpha = 0.2;
- ctx.fillStyle = (config.graphical.screenshotMode) ? color.guiwhite : getZoneColor(cell, true);
- ctx.fillRect(left, top, right-left, bottom-top);
- j++;
- });
- i++;
- });
- ctx.lineWidth = 1;
- ctx.strokeStyle = (config.graphical.screenshotMode) ? color.guiwhite : color.guiblack;
- ctx.globalAlpha = 0.05;
- ctx.beginPath();
- let gridsize = 20*ratio;
- for (let x=(global.screenWidth/2-px)%gridsize; x < global.screenWidth; x += gridsize) {
- ctx.moveTo(x, 0);
- ctx.lineTo(x, global.screenHeight);
- }
- for (let y=(global.screenHeight/2-py)%gridsize; y < global.screenHeight; y += gridsize) {
- ctx.moveTo(0, y);
- ctx.lineTo(global.screenWidth, y);
- }
- ctx.stroke();
- ctx.globalAlpha = 1;
- }
- { // Draw things
- entities.forEach(function(instance) {
- instance.render.x = (t >= 0) ?
- instance.x + extrapolateMotion(instance.render.lastvx, instance.vx, t) :
- instance.render.lastx + (instance.x - instance.render.lastx) * interpolateMotion(instance.render.lastvx, instance.vx, t);
- instance.render.y = (t >= 0) ?
- instance.y + extrapolateMotion(instance.render.lastvy, instance.vy, t) :
- instance.render.lasty + (instance.y - instance.render.lasty) * interpolateMotion(instance.render.lastvy, instance.vy, t);
- instance.render.f = (instance.twiggle) ?
- Math.atan2(target.y, target.x) :
- instance.render.f = instance.render.lastf + (1 + t / metrics.rendergap) * angleDifference(instance.render.lastf, instance.facing);
- let x = (instance.twiggle) ? 0 : ratio * instance.render.x - px,
- y = (instance.twiggle) ? 0 : ratio * instance.render.y - py;
- x += global.screenWidth / 2;
- y += global.screenHeight / 2;
- drawEntity(x, y, instance, ratio, 1.1, instance.render.f, false);
- });
- if (!config.graphical.screenshotMode) {
- entities.forEach(function(instance) {
- let x = (instance.twiggle) ? 0 : ratio * instance.render.x - px,
- y = (instance.twiggle) ? 0 : ratio * instance.render.y - py;
- x += global.screenWidth / 2;
- y += global.screenHeight / 2;
- drawHealth(x, y, instance, ratio);
- });
- }
- }
- // Draw GUI
- let alcoveSize = 200/Math.max(global.screenWidth, global.screenHeight * 16 / 9);
- let spacing = 20;
- let max = (leaderboard[0] == null) ? 1 : leaderboard[0].score;
- { // Draw messages
- let vspacing = 4;
- let len = 0;
- let height = 18;
- let x = global.screenWidth/2;
- let y = spacing;
- for (let i=messages.length-1; i>=0; i--) {
- let msg = messages[i],
- txt = strDecodeUTF16(msg.text),
- text = txt;//txt[0].toUpperCase() + txt.substring(1);
- len = measureText(text, height-4);
- ctx.globalAlpha = 0.5 * msg.alpha;
- drawBar(x-len/2, x+len/2, y+height/2, height, color.black);
- ctx.globalAlpha = Math.min(1, msg.alpha);
- ctx.textAlign = 'center';
- drawText(text, x, y + height-4, height-4, color.guiwhite);
- y += (vspacing + height);
- if (msg.status > 1) {
- y -= (vspacing + height) * (1 - Math.sqrt(msg.alpha));
- }
- if (msg.status > 1) {
- messages[i].status -= 0.05;
- messages[i].alpha += 0.05;
- } else if (i === 0 && (messages.length > 5 || Date.now() - msg.time > 10000)) {
- messages[i].status -= 0.05;
- messages[i].alpha -= 0.05;
- if (messages[i].alpha <= 0) {
- messages.splice(0, 1);
- }
- }
- }
- ctx.globalAlpha = 1;
- }
- { // Draw skill bars
- global.canSkill = gui.skills.points;
- let vspacing = 4;
- let len = alcoveSize * global.screenWidth; // The 30 is for the value modifiers
- let save = len;
- let height = 15;
- let x = spacing;
- let y = global.screenHeight - spacing - height;
- let ticker = 11;
- gui.skills.typeData.forEach(function(skill) { // Individual skill bars
- ticker--;
- let name = skill[0],
- level = skill[1],
- col = skill[2],
- value = skill[3],
- cap = skill[4],
- maxLevel = skill[5] + 1;
- if (cap) {
- len = save;
- let max = 10,
- extension = cap > max,
- blocking = cap < maxLevel;
- if (extension) {
- len = len * (cap + 1) / max;
- max = cap + 1;
- }
- drawBar(x+height/2, x-height/2+len, y+height/2, height, color.black);
- drawBar(x+height/2, x+height/2+(len-height)*(cap/max), y+height/2, height-3, color.grey);
- drawBar(x+height/2, x+height/2+(len-height)*(level/max), y+height/2, height-3.5, getColor(col));
- if (blocking) { // Blocked-off area
- ctx.lineWidth = 1;
- ctx.strokeStyle = color.grey;
- for (let j=cap+1; j<max; j++) {
- drawGuiLine(
- x + (len-height) * j / max, y+1.5 ,
- x + (len-height) * j / max, y-3 + height
- );
- }
- }
- ctx.strokeStyle = color.black; // Vertical dividers
- ctx.lineWidth = 1;
- for (let j=1; j<level+1; j++) {
- drawGuiLine(
- x + (len-height) * j / max, y+1.5,
- x + (len-height) * j / max, y-3 + height
- );
- }
- ctx.textAlign = 'center'; // Skill name
- ctx.lineWidth = 2;
- let textcolor = (level == max) ? getColor(col) : (!gui.skills.points || (cap !== maxLevel-1 && level == cap)) ? color.grey : color.guiwhite;
- drawText(name, Math.round(x + len / 2) + 0.5, Math.round(y + height - 5) + 0.5, height - 5, textcolor);
- ctx.textAlign = 'right'; // Skill key
- drawText('[' + (ticker % 10) + ']', Math.round(x + len - height*0.25) - 0.5, Math.round(y + height - 6) + 0.5, height - 5, textcolor);
- ctx.textAlign = 'left'; // Skill value
- drawText(value, Math.round(x + len + 4) + 0.5, Math.round(y + height - 5) + 0.5, height - 3, getColor(col));
- y -= height + vspacing;
- }
- });
- if (gui.skills.points !== 0) { // Draw skillpoints to spend
- ctx.lineWidth = 4;
- ctx.textAlign = 'bottom'; ctx.textAlign = 'right';
- drawText('x' + gui.skills.points, Math.round(x + len - 2) + 0.5, Math.round(y + height - 4) + 0.5, 20, color.guiwhite);
- }
- }
- { // Draw name, exp and score bar
- let vspacing = 4;
- let len = 2 * alcoveSize * global.screenWidth;
- let height = 25;
- let x = (global.screenWidth - len) / 2;
- let y = global.screenHeight - spacing - height;
- ctx.lineWidth = 1;
- drawBar(x, x+len, y+height/2, height, color.black);
- drawBar(x, x+len, y+height/2, height-3, color.grey);
- drawBar(x, x+len*gui.progress, y+height/2, height-3.5, color.gold);
- ctx.lineWidth = 2;
- ctx.textAlign = 'center';
- drawText(
- 'Level ' + gui.level + ' ' + gui.type,
- Math.round(x + len/2) + 0.5, Math.round(y + height - 6) + 0.5,
- height - 4, color.guiwhite
- );
- height = 14;
- y -= height + vspacing;
- drawBar(x, x+len, y+height/2, height, color.black);
- drawBar(x, x+len, y+height/2, height-3, color.grey);
- let scoreFactor = (max) ? Math.min(1, gui.score/max) : 1;
- drawBar(x, x+len*scoreFactor, y+height/2, height-3.5, color.green);
- ctx.lineWidth = 2;
- ctx.textAlign = 'center';
- drawText(
- 'Score: ' + handleLargeNumber(gui.score),
- Math.round(x + len/2) + 0.5, Math.round(y + height - 4) + 0.5,
- height - 2, color.guiwhite
- );
- ctx.lineWidth = 4;
- drawText(
- strDecodeUTF16(player.name),
- Math.round(x + len/2) + 0.5, Math.round(y - 10 - vspacing) + 0.5,
- 32, color.guiwhite
- );
- }
- { // Draw minimap and FPS monitors
- let len = alcoveSize * global.screenWidth;
- let height = len;
- let x = global.screenWidth - len - spacing;
- let y = global.screenHeight - height - spacing;
- ctx.globalAlpha = 0.5;
- let W = roomSetup[0].length, H = roomSetup.length, i = 0;
- roomSetup.forEach((row) => {
- let j = 0;
- row.forEach((cell) => {
- ctx.fillStyle = getZoneColor(cell, false);
- drawGuiRect(x + i*len/W, y + (j++)*height/H, len/W, height/H);
- });
- i++;
- });
- ctx.fillStyle = color.grey;
- drawGuiRect(x, y, len, height);
- ctx.globalAlpha = 0.8;
- minimap.forEach(function (o) {
- ctx.fillStyle = mixColors(getColor(o[2]), color.black, 0.5);
- drawGuiRect(x + (o[0]/global.gameWidth) * len, y + (o[1]/global.gameHeight) * height, 1, 1);
- });
- ctx.globalAlpha = 1;
- ctx.lineWidth = 1;
- ctx.strokeStyle = color.black;
- drawGuiRect( // My position
- x + (player.x/global.gameWidth) * len - 1,
- y + (player.y/global.gameWidth) * height - 1,
- 3, 3, true);
- ctx.lineWidth = 3;
- drawGuiRect(x, y, len, height, true); // Border
- ctx.textAlign = 'right';
- drawText(
- 'Update Rate: ' + metrics.updatetime + 'Hz',
- x + len, y - 52,
- 10, color.guiwhite
- );
- drawText(
- 'Latency: ' + metrics.latency + 'ms',
- x + len, y - 38,
- 10, color.guiwhite
- );
- drawText(
- 'Client FPS: ' + metrics.rendertime,
- x + len, y - 24,
- 10, color.guiwhite
- );
- drawText(
- 'Server Speed: ' + (100 * gui.fps).toFixed(2) + '%',
- x + len, y - 10,
- 10, color.guiwhite
- );
- }
- { // Draw leaderboard
- let vspacing = 4;
- let len = alcoveSize * global.screenWidth;
- let height = 14;
- let x = global.screenWidth - len - spacing;
- let y = spacing + height + 7;
- ctx.lineWidth = 4;
- ctx.textAlign = 'center';
- drawText('Leaderboard:', Math.round(x + len / 2) + 0.5, Math.round(y - 6) + 0.5, height + 4, color.guiwhite);
- let i = 0;
- leaderboard.forEach(function(entry) {
- leaderboardScore[i] += (entry.score - leaderboardScore[i]) / 20;
- drawBar(x, x+len, y+height/2, height, color.black);
- drawBar(x, x+len, y+height/2, height-3, color.grey);
- let shift = Math.min(1, entry.score / max);
- drawBar(x, x+len*shift, y+height/2, height-3.5, getColor(entry.bar));
- // Leadboard name + score
- ctx.textAlign = 'center';
- ctx.lineWidth = 2;
- let dash = '',
- txt = strDecodeUTF16(entry.name),
- lab = (txt === '') ? entry.label : ' - ' + entry.label;
- drawText(txt + lab + ': ' + handleLargeNumber(Math.round(leaderboardScore[i++])), Math.round(x + len / 2) + 0.5, Math.round(y + height - 5) + 0.5, height - 5, color.guiwhite);
- let picture = getEntityImageFromMockup(entry.index, entry.color),
- position = mockups[entry.index].position,
- scale = height / position.axis,
- xx = x - 1.5 * height - scale * position.middle.x * 0.707,
- yy = y + 0.5 * height + scale * position.middle.x * 0.707;
- drawEntity(xx, yy, picture, 1 / scale, scale * scale / picture.realSize, -Math.PI/4);
- y += vspacing+height;
- });
- }
- { // Draw upgrade menu
- if (gui.upgrades.length > 0) {
- global.canUpgrade = true;
- var getClassUpgradeKey = function(number) {
- switch (number) {
- case 0: return 'y';
- case 1: return 'h';
- case 2: return 'u';
- case 3: return 'j';
- case 4: return 'i';
- case 5: return 'k';
- case 6: return 'o';
- case 7: return 'l';
- }
- };
- let internalSpacing = 8;
- let len = alcoveSize * global.screenWidth/2 * 1;
- let height = len;
- let x = spacing;
- let y = spacing;
- let ticker = 0;
- upgradeSpin += 0.01;
- let colorIndex = 10;
- gui.upgrades.forEach(function(model) {
- ctx.globalAlpha = 0.5;
- ctx.fillStyle = getColor(colorIndex);
- drawGuiRect(x, y, len, height);
- ctx.globalAlpha = 0.1;
- ctx.fillStyle = getColor(-10 + colorIndex++);
- drawGuiRect(x, y, len, height*0.6);
- ctx.fillStyle = color.black;
- drawGuiRect(x, y+height*0.6, len, height*0.4);
- ctx.globalAlpha = 1;
- // Find offset location with rotation
- let picture = getEntityImageFromMockup(model[0], model[1]),
- position = mockups[model[0]].position,
- scale = 0.6 * len / position.axis,
- xx = x + 0.5 * len - scale * position.middle.x * Math.cos(upgradeSpin),
- yy = y + 0.5 * height - scale * position.middle.x * Math.sin(upgradeSpin);
- drawEntity(xx, yy, picture, 1, scale / picture.realSize, upgradeSpin);
- ctx.textAlign = 'center'; // Tank name
- ctx.lineWidth = 2;
- drawText(picture.name, Math.round(x + 0.9*len/2) + 0.5, Math.round(y + height - 6) + 0.5, height/8 - 3, color.guiwhite);
- ctx.textAlign = 'right'; // Upgrade key
- drawText('[' + getClassUpgradeKey(ticker) + ']', Math.round(x + len - 4) + 0.5, Math.round(y + height - 6) + 0.5, height/8 - 3, color.guiwhite);
- ctx.strokeStyle = color.black; // Already incremented, see above
- ctx.globalAlpha = 1;
- ctx.lineWidth = 3;
- drawGuiRect(x, y, len, height, true); // Border
- if (ticker++ % 2) {
- y -= height + internalSpacing;
- x += len + internalSpacing;
- } else {
- y += height + internalSpacing;
- }
- });
- } else {
- global.canUpgrade = false;
- }
- }
- metrics.lastrender = global.time;
- } catch(error) {
- console.log(error);
- }
- }
- function gameDrawDead() {
- clearScreen(color.black, 0.5);
- ctx.textAlign = 'center';
- ctx.lineWidth = 4;
- drawText('lol you died', global.screenWidth / 2, global.screenHeight / 2 - 40, 16, color.guiwhite);
- drawText('Final score: ' + gui.score, global.screenWidth / 2, global.screenHeight / 2, 48, color.guiwhite);
- drawText('Reload to play again.', global.screenWidth / 2, global.screenHeight / 2 + 40, 16, color.guiwhite);
- }
- function gameDrawBeforeStart() {
- clearScreen(color.white, 0.5);
- ctx.textAlign = 'center';
- ctx.lineWidth = 4;
- drawText('Trying to connect...', global.screenWidth / 2, global.screenHeight / 2, 30, color.guiwhite);
- drawText(global.messages, global.screenWidth / 2, global.screenHeight / 2 + 30, 15, color.red);
- }
- function gameDrawDisconnected() {
- clearScreen(color.black, 0.5);
- ctx.textAlign = 'center';
- ctx.lineWidth = 4;
- drawText('Disconnected.', global.screenWidth / 2, global.screenHeight / 2, 30, color.guiwhite);
- drawText(global.messages, global.screenWidth / 2, global.screenHeight / 2 + 30, 15, color.red);
- }
- function animloop() {
- global.animLoopHandle = window.requestAnimFrame(animloop);
- player.renderv += (player.view - player.renderv) / 30;
- var ratio = (config.graphical.screenshotMode) ? 2 : Math.max(global.screenWidth / player.renderv, global.screenHeight / player.renderv / 9 * 16);
- // Draw the game
- if (!global.disconnected) {
- if (global.gameStart) {
- global.time = Date.now();
- if (global.time - lastPing > 1000) { // Latency
- // Do ping.
- socket.emit('pingcheck', global.time);
- lastPing = global.time;
- // Do rendering speed.
- metrics.rendertime = renderTimes;
- renderTimes = 0;
- // Do update rate.
- metrics.updatetime = updateTimes;
- updateTimes = 0;
- }
- metrics.lag = global.time - player.time;
- gameDraw(ratio);
- } else {
- gameDrawBeforeStart();
- }
- if (global.died) {
- gameDrawDead();
- }
- } else {
- gameDraw(ratio);
- gameDrawDisconnected();
- }
- global.time = (new Date()).getTime();
- }
- window.addEventListener('resize', resize);
- function resize() {
- if (!socket) return;
- player.screenWidth = c.width = global.screenWidth = global.playerType == 'player' ? window.innerWidth : global.gameWidth;
- player.screenHeight = c.height = global.screenHeight = global.playerType == 'player' ? window.innerHeight : global.gameHeight;
- socket.emit('windowResized', { screenWidth: global.screenWidth, screenHeight: global.screenHeight });
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement