123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582 |
- let canvas;
- let context;
- let username = localStorage.getItem("username");
- let userData = {
- name: "",
- coordinates: { x: 0, y: 0 },
- inventory: [],
- position: { x: 0.5, y: 0.5 },
- size: {
- width: 0.03,
- height: 0.07
- },
- speed: 0.005,
- sprite: 'medievalUnit_01.png'
- };
- let lockUserMovement = false;
- let loadingDelayTimeout;
- let showLoadingMessage;
- let otherPlayerCache = {};
- let otherPlayers = {};
- let roomData = { name: "", walls: [], tiles: [], decals: [] };
- let keys = [];
- let sendMovement = false;
- let userChanged = false;
- let atlas = new SpriteAtlas('assets', 'medievalRTS_spritesheet@2.xml');
- const apidataurl = `http://jsonapi.eyeofmidas.net/data`;
- //const websocketurl = `ws://${location.host}/ws`;
- const websocketurl = `ws://jsonapi.eyeofmidas.net:8080`;
- let webSocket;
- function ajaxGet(url) {
- return new Promise((resolve, reject) => {
- var r = new XMLHttpRequest();
- r.open("GET", url, true);
- r.onreadystatechange = function (response) {
- if (r.readyState == 4 && r.status == 200) {
- resolve(JSON.parse(r.responseText));
- }
- if (r.readyState == 4 && r.status != 200) {
- reject(JSON.parse(r.response));
- }
- return;
- }
- r.onerror = function (response) {
- console.error("onerror", response, r);
- reject(r.responseText);
- }
- r.setRequestHeader("Content-Type", "application/json");
- r.send();
- });
- }
- function ajaxPost(url, data) {
- return new Promise((resolve, reject) => {
- var r = new XMLHttpRequest();
- r.open("POST", url, true);
- r.onreadystatechange = function (response) {
- if (r.readyState == 4 && r.status == 200) {
- resolve(JSON.parse(r.responseText));
- }
- if (r.readyState == 4 && r.status != 200) {
- reject(r.responseText);
- }
- return;
- }
- r.onerror = function (response) {
- reject(r.responseText);
- }
- r.setRequestHeader("Content-Type", "application/json");
- let jsonData = JSON.stringify(data);
- r.send(jsonData);
- });
- }
- function websocketSafeSend(message) {
- //console.log("%c" + message, "color: #22FF22");
- try {
- webSocket.send(message);
- } catch (error) {
- console.error("websocket", error);
- }
- }
- function handleMessage(message) {
- //console.log("%c" + message, "color: #FF2222");
- splitMessage = message.split(" ");
- switch (splitMessage[0]) {
- case "join":
- addOtherPlayer(splitMessage[1], splitMessage[2], splitMessage[3]);
- break;
- case "leave":
- removeOtherPlayer(splitMessage[1]);
- break;
- case "move":
- moveOtherPlayer(splitMessage[1], splitMessage[2], splitMessage[3]);
- break;
- case "population":
- splitMessage.shift();
- setRoomPopulation(splitMessage);
- break;
- default:
- console.log(message);
- break;
- }
- }
- async function getPlayerData(playerKey) {
- if (otherPlayerCache[playerKey]) {
- return otherPlayerCache[playerKey];
- }
- let result = await ajaxGet(`${apidataurl}/${playerKey}`);
- otherPlayerCache[playerKey] = result;
- return otherPlayerCache[playerKey];
- }
- function addOtherPlayer(playerKey, x, y) {
- let cleanName = userData.name.replace(/\s/g, '');
- if (playerKey == `user-${cleanName}` || playerKey == "") {
- return;
- }
- otherPlayers[playerKey] = { name: "", position: { x: x, y: y }, size: { width: 0.0125, height: 0.0167 }, sprite: 'medievalUnit_01.png' };
- getPlayerData(playerKey).then((response) => {
- otherPlayers[playerKey].name = response.name;
- otherPlayers[playerKey].size.width = response.size.width;
- otherPlayers[playerKey].size.height = response.size.height;
- otherPlayers[playerKey].sprite = response.sprite;
- //TODO: populate other data
- });
- }
- function removeOtherPlayer(playerKey) {
- let cleanName = userData.name.replace(/\s/g, '');
- if (playerKey == `user-${cleanName}`) {
- return;
- }
- delete otherPlayers[playerKey];
- }
- function moveOtherPlayer(playerKey, x, y) {
- let cleanName = userData.name.replace(/\s/g, '');
- if (playerKey == `user-${cleanName}`) {
- return;
- }
- if (!otherPlayers[playerKey]) {
- addOtherPlayer(playerKey, x, y);
- }
- otherPlayers[playerKey].position.x = parseFloat(x);
- otherPlayers[playerKey].position.y = parseFloat(y);
- }
- function setRoomPopulation(otherUserData) {
- for (let i = 0; i < otherUserData.length; i += 3) {
- addOtherPlayer(otherUserData[i], otherUserData[i + 1], otherUserData[i + 2]);
- }
- }
- document.addEventListener("DOMContentLoaded", () => {
- for (let i = 0; i < 256; i++) {
- keys[i] = false;
- }
- canvas = document.getElementsByTagName("canvas")[0];
- context = canvas.getContext("2d");
- context.canvas.width = canvas.clientWidth;
- context.canvas.height = canvas.clientHeight;
- atlas.load().then(() => {
- animateLoop();
- getRoom(0, 0);
- webSocket = new WebSocket(websocketurl);
- webSocket.onmessage = function (event) {
- handleMessage(event.data);
- }
- webSocket.onopen = function (event) {
- }
- if (!username) {
- username = prompt("Please enter your username");
- }
- if (!username) {
- return;
- }
- let cleanName = username.replace(/\s/g, '');
- ajaxGet(`${apidataurl}/user-${cleanName}`).then(result => {
- userData = result;
- localStorage.setItem("username", cleanName);
- getRoom(userData.coordinates.x, userData.coordinates.y);
- }, (error) => {
- if (error.errorCode == 404) {
- userData.name = username;
- let create = confirm("Would you like to create the new user '" + userData.name + "'?");
- if (!create) {
- localStorage.removeItem("username");
- return;
- }
- let validStartingUnits = [
- 'medievalUnit_01.png',
- // 'medievalUnit_02.png',
- // 'medievalUnit_03.png',
- // 'medievalUnit_04.png',
- // 'medievalUnit_05.png',
- 'medievalUnit_06.png',
- 'medievalUnit_07.png',
- // 'medievalUnit_08.png',
- // 'medievalUnit_09.png',
- // 'medievalUnit_10.png',
- // 'medievalUnit_11.png',
- 'medievalUnit_12.png',
- 'medievalUnit_13.png',
- // 'medievalUnit_14.png',
- // 'medievalUnit_15.png',
- // 'medievalUnit_16.png',
- // 'medievalUnit_17.png',
- 'medievalUnit_18.png',
- 'medievalUnit_19.png',
- // 'medievalUnit_20.png',
- // 'medievalUnit_21.png',
- // 'medievalUnit_22.png',
- // 'medievalUnit_23.png',
- 'medievalUnit_24.png',
- ];
- userData.sprite = validStartingUnits[Math.floor(validStartingUnits.length * Math.random())];
- saveUser().then(() => {
- localStorage.setItem("username", cleanName);
- getRoom(userData.coordinates.x, userData.coordinates.y);
- });
- } else {
- console.error(error);
- }
- });
- });
- });
- let delta = { x: 0, y: 0 };
- function draw(context) {
- delta.x = 0;
- delta.y = 0;
- if (keys[38] || keys[87]) {
- delta.y = -userData.speed;
- sendMovement = true;
- }
- if (keys[37] || keys[65]) {
- delta.x = -userData.speed;
- sendMovement = true;
- }
- if (keys[40] || keys[83]) {
- delta.y = userData.speed;
- sendMovement = true;
- }
- if (keys[39] || keys[68]) {
- delta.x = +userData.speed;
- sendMovement = true;
- }
- let userCurrentBounds = {
- x: userData.position.x,
- y: userData.position.y,
- width: userData.size.width,
- height: userData.size.height,
- };
- let userFutureBounds = {
- x: userData.position.x + delta.x,
- y: userData.position.y + delta.y,
- width: userData.size.width,
- height: userData.size.height,
- };
- for (let i = 0; i < roomData.walls.length; i++) {
- let wall = roomData.walls[i];
- if (boxCollision(wall, userFutureBounds) && !boxCollision(wall, userCurrentBounds)) {
- let userFutureBoundsY = {
- x: userData.position.x,
- y: userData.position.y + delta.y,
- width: userData.size.width,
- height: userData.size.height,
- };
- let userFutureBoundsX = {
- x: userData.position.x + delta.x,
- y: userData.position.y,
- width: userData.size.width,
- height: userData.size.height,
- };
- if (boxCollision(wall, userFutureBoundsX)) {
- delta.x = 0;
- }
- if (boxCollision(wall, userFutureBoundsY)) {
- delta.y = 0;
- }
- if (delta.x == 0 && delta.y == 0) {
- sendMovement = false;
- }
- }
- }
- if (!lockUserMovement) {
- userData.position.x += delta.x;
- userData.position.y += delta.y;
- if (userData.position.x * canvas.width > canvas.width) {
- lockUserMovement = true;
- loadingDelayTimeout = setTimeout(() => { showLoadingMessage = true; }, 50);
- getRoom(userData.coordinates.x + 1, userData.coordinates.y).then(() => {
- userData.position.x = 0;
- userData.coordinates.x++;
- saveUser();
- lockUserMovement = false;
- });
- }
- if (userData.position.x * canvas.width < -userData.size.width) {
- lockUserMovement = true;
- loadingDelayTimeout = setTimeout(() => { showLoadingMessage = true; }, 50);
- getRoom(userData.coordinates.x - 1, userData.coordinates.y).then(() => {
- userData.position.x = 1 - userData.size.width;
- userData.coordinates.x--;
- saveUser();
- lockUserMovement = false;
- });
- }
- if (userData.position.y * canvas.height > canvas.height) {
- lockUserMovement = true;
- loadingDelayTimeout = setTimeout(() => { showLoadingMessage = true; }, 50);
- getRoom(userData.coordinates.x, userData.coordinates.y + 1).then(() => {
- userData.position.y = 0;
- userData.coordinates.y++;
- saveUser();
- lockUserMovement = false;
- });
- }
- if (userData.position.y * canvas.height < -userData.size.height) {
- lockUserMovement = true;
- loadingDelayTimeout = setTimeout(() => { showLoadingMessage = true; }, 50);
- getRoom(userData.coordinates.x, userData.coordinates.y - 1).then(() => {
- userData.position.y = 1 - userData.size.height;
- userData.coordinates.y--;
- saveUser();
- lockUserMovement = false;
- });
- }
- }
- context.save();
- context.translate(-0.5, -0.5);
- drawRoom(context);
- drawOtherPlayers(context);
- drawPlayer(context);
- if (showLoadingMessage) {
- context.font = "30px Arial";
- context.textAlign = "center";
- context.fillStyle = "#FFFFFF";
- context.fillText("Loading... please wait", 0.5 * canvas.width, 0.5 * canvas.height);
- } else {
- clearTimeout(loadingDelayTimeout);
- showLoadingMessage = false;
- }
- context.restore();
- if (drawEditor != undefined) {
- drawEditor(context);
- }
- }
- function boxCollision(box1, box2) {
- return box1.x < box2.x + box2.width &&
- box1.x + box1.width > box2.x &&
- box1.y < box2.y + box2.height &&
- box1.y + box1.height > box2.y;
- }
- function pointCollision(box, point) {
- return box.x < point.x && box.x + box.width > point.x &&
- box.y < point.y && box.y + box.height > point.y;
- }
- async function saveUser() {
- if (!userData.name) {
- return;
- }
- let cleanName = userData.name.replace(/\s/g, '');
- let result = await ajaxPost(`${apidataurl}/user-${cleanName}`, userData);
- userData = result;
- }
- async function getRoom(x, y) {
- try {
- let result = await ajaxGet(`${apidataurl}/room-${x},${y}`);
- roomData.name = result.name ?? "";
- roomData.walls = result.walls ?? [];
- roomData.tiles = result.tiles ?? [];
- roomData.decals = result.decals ?? [];
- } catch (error) {
- let emptyRoom = { name: `${x},${y}`, walls: [], tiles: [], decals: [] };
- addRandomTiles(emptyRoom);
- let result = await ajaxPost(`${apidataurl}/room-${x},${y}`, emptyRoom);
- roomData = result;
- }
- let cleanName = userData.name.replace(/\s/g, '');
- otherPlayers = {};
- if (userData.name) {
- websocketSafeSend(`subscribe user-${cleanName} room-${x},${y} ${userData.position.x} ${userData.position.y}`);
- }
- }
- const colors = [
- "red",
- "green",
- "blue",
- "black",
- "purple",
- "orange"
- ];
- function addRandomItems(room) {
- let items = [];
- for (let i = Math.floor(10 * Math.random()); i > 0; i--) {
- let newitem = { coordinates: { x: Math.random(), y: Math.random() }, color: colors[Math.floor(colors.length * Math.random())] };
- items.push(newitem);
- }
- room.items = items;
- }
- function addRandomTiles(room) {
- let tileSize = 8 * 5;
- room.tiles = [];
- for (let i = 0; i < tileSize; i++) {
- room.tiles.push(57 + (Math.floor(2 * Math.random())));
- }
- }
- function drawPlayer(context) {
- context.font = "14px Arial";
- context.textAlign = "center";
- let pos = inScreenSpace(userData.position);
- let size = inScreenSize(userData.size);
- let centerPos = { x: pos.x + (size.width / 2), y: pos.y + (size.height / 2) };
- atlas.drawCentered(context, userData.sprite, centerPos);
- context.fillStyle = "#000000";
- context.fillText(userData.name, centerPos.x - 1, (pos.y - 0.02 * canvas.height) - 1);
- context.fillText(userData.name, centerPos.x + 1, (pos.y - 0.02 * canvas.height) - 1);
- context.fillText(userData.name, centerPos.x - 1, (pos.y - 0.02 * canvas.height) + 1);
- context.fillText(userData.name, centerPos.x + 1, (pos.y - 0.02 * canvas.height) + 1);
- context.fillStyle = "#FFFFFF";
- context.fillText(userData.name, centerPos.x, pos.y - 0.02 * canvas.height);
- }
- function inScreenSpace(serverPosition) {
- return { x: serverPosition.x * canvas.width, y: serverPosition.y * canvas.height };
- }
- function inScreenSize(serverSize) {
- return { width: serverSize.width * canvas.width, height: serverSize.height * canvas.height };
- }
- function drawOtherPlayers(context) {
- context.font = "14px Arial";
- context.textAlign = "center";
- for (let index in otherPlayers) {
- let player = otherPlayers[index];
- let pos = inScreenSpace(player.position);
- let size = inScreenSize(player.size);
- let centerPos = { x: pos.x + (size.width / 2), y: pos.y + (size.height / 2) };
- atlas.drawCentered(context, player.sprite, centerPos);
- context.fillStyle = "#000000";
- context.fillText(player.name, centerPos.x - 1, (pos.y - 0.02 * canvas.height) - 1);
- context.fillText(player.name, centerPos.x + 1, (pos.y - 0.02 * canvas.height) - 1);
- context.fillText(player.name, centerPos.x - 1, (pos.y - 0.02 * canvas.height) + 1);
- context.fillText(player.name, centerPos.x + 1, (pos.y - 0.02 * canvas.height) + 1);
- context.fillStyle = "#FFFFFF";
- context.fillText(player.name, centerPos.x, pos.y - 0.02 * canvas.height);
- }
- }
- function drawRoom(context) {
- let width = 126;
- let height = 126;
- for (var i = 0; i < roomData.tiles.length; i++) {
- let tile = roomData.tiles[i];
- try {
- atlas.getSprite(tile);
- atlas.draw(context, tile, { x: ((i % 8) * width), y: (Math.floor(i / 8) * height) });
- } catch (e) {}
-
- if (tile < 10) {
- tile = "0" + tile;
- }
- let tileName = `medievalTile_${tile}.png`;
- try {
- atlas.getSprite(tileName);
- atlas.draw(context, tileName, { x: ((i % 8) * width), y: (Math.floor(i / 8) * height) });
- } catch (e) {
- // console.error("Room data error: tile index ", i, " is not defined");
- continue;
- }
- }
- // for (var i = 0; i < roomData.items.length; i++) {
- // let item = roomData.items[i];
- // context.beginPath();
- // context.strokeStyle = item.color;
- // context.rect(item.coordinates.x * canvas.width, item.coordinates.y * canvas.height, 10, 10);
- // context.stroke();
- // }
- // for (var i = 0; i < roomData.walls.length; i++) {
- // let wall = roomData.walls[i];
- // context.beginPath();
- // context.strokeStyle = wall.color ?? "red";
- // context.rect(wall.x * canvas.width, wall.y * canvas.height, wall.width * canvas.width, wall.height * canvas.height);
- // context.stroke();
- // }
- for (var i = 0; i < roomData.decals.length; i++) {
- let decal = roomData.decals[i];
- atlas.draw(context, decal.spriteName, { x: decal.x * canvas.width, y: decal.y * canvas.height });
- }
- context.font = "30px Arial";
- context.fillText(roomData.name, 20, 40);
- }
- function animateLoop() {
- canvas.width = canvas.width;
- draw(context);
- window.requestAnimationFrame(animateLoop);
- }
- document.addEventListener("keydown", event => {
- keys[event.keyCode] = true;
- });
- document.addEventListener("keyup", event => {
- keys[event.keyCode] = false;
- });
- setInterval(() => {
- if (!sendMovement) {
- return;
- }
- userChanged = true;
- sendMovement = false;
- let cleanName = userData.name.replace(/\s/g, '');
- websocketSafeSend(`move user-${cleanName} ${userData.position.x} ${userData.position.y}`);
- }, Math.floor(1000 / 30));
- setInterval(() => {
- if (!userChanged) {
- return;
- }
- saveUser();
- userChanged = false;
- }, Math.floor(60000));
|