var fps = 30; var server_fps = 1; var server; var player; var hud = new Object(); var keys_pressed = { "KeyW": false, "KeyA": false, "KeyS": false, "KeyD": false } var mouse_position = new vector(0, 0); var rotation_offset = 0; var player_speed = 1; var update_server_tick; var username; //set name from URL try { let URL = window.location.search; let params = new URLSearchParams(URL); username = params.get("name"); //this will get foo from ?name=foo if (username === null) { username = "Anonymous"; } } catch(err) { console.error("Failed to get username from URL parameters", err); } var server_url; try { let URL = window.location.search; params = new URLSearchParams(URL); server_url = "ws://" + params.get("server_url"); if (server_url === "ws://null"/*Javascript why*/) { server_url = "ws://" + "localhost:8080"; } } catch(err) { console.error("Failed to get server from URL parameters", err); } var game_data = { "character": { "variants": [ load_image("img/character/character.svg") ], "radius": 40 }, "world": { "biome": { "forest": { "ground": { "img": load_image("img/world/biome/forest/grass.svg") }, "tree": { "img": load_image("img/world/biome/forest/tree.svg"), "radius": 50, "size": 180 }, "boulder": { "img": load_image("img/world/biome/forest/boulder.svg"), "radius": 60, "size": 130 } } } } } function game_init() { init_player(); open_socket(); load_hud(); game_ready(); } function load_hud() { hud.health = document.getElementById("health_bar"); hud.energy = document.getElementById("energy_bar"); document.getElementById("player_username").innerText = username; } function update_hud() { hud.health.style.width = `${player.health}%`; hud.energy.style.width = `${player.stamina}%`; document.getElementById("player_username").innerText = username; } function key_down(e) { if (e.code in keys_pressed) { if (keys_pressed[e.code] === false) { keys_pressed[e.code] = true; } } } function key_up(e) { if (e.code in keys_pressed) { if (keys_pressed[e.code] === true) { keys_pressed[e.code] = false; } } } function init_player() { let player_vector = new vector(0, 0); player = new character(player_vector, 0, 0, username); } function message(type, data) { //incoming message if (type === "position_update") { if ("position" in data) { player.position.x = data.position.x; player.position.y = data.position.y; } if ("rotation" in data) { player.rotation = data.rotation; } } else if (type === "other_players") { let char_array = Array.from(characters); for (let other_player_num in data) { let other_player = data[other_player_num]; let exists = false; for (let existing_character_num in char_array) { let existing_character = char_array[existing_character_num]; if (existing_character != player) { //console.log("not the same"); if (existing_character.id === other_player.id) { exists = true; existing_character.position.x = other_player.position.x; existing_character.position.y = other_player.position.y; existing_character.rotation = other_player.rotation; existing_character.username = other_player.username; existing_character.health = other_player.health; existing_character.stamina = other_player.stamina; } } else { //console.log("the same"); } } if (!exists) { let new_character = new character(new vector(other_player.position.x, other_player.position.y), other_player.rotation, other_player.variant, other_player.username); new_character.id = other_player.id; } } //remove players for (let exiting_character_num in char_array) { let existing_character = char_array[exiting_character_num]; let exists = false; for (let other_player_num in data) { let other_player = data[other_player_num]; if (other_player.id === existing_character.id) { exists = true; } } if (!exists) { if (existing_character != player) { existing_character.destroy(); } } } } else if (type === "world") { nodes = new Set(); data.forEach(function(itr, idx) { let this_node = new node(new vector(itr.position.x, itr.position.y), itr.rotation, itr.radius, itr.size, itr.type); }); } else if (type === "server_data") { if ("fps" in data) { server_fps = data.fps; clearInterval(update_server_tick); update_server_tick = setInterval(send_position_to_server, server_fps); } } else { console.log("Unknown packet"); } } function do_collisions() { nodes.forEach(function(itr, idx) { collide(itr, player); }); } function do_movement(delta) { if (keys_pressed["KeyW"]) { player.position.y -= player_speed * (delta/8); } if (keys_pressed["KeyS"]) { player.position.y += player_speed * (delta/8); } if (keys_pressed["KeyA"]) { player.position.x -= player_speed * (delta/8); } if (keys_pressed["KeyD"]) { player.position.x += player_speed * (delta/8); } //rotation player.rotation = canvas_center.rotation_to(mouse_position) + rotation_offset; if (mouse_down && !punching) { interact(); } } document.onmousemove = function(e) { //console.log(e); //position.rot = point_towards([xenter, yenter], e) + rotate_offset; mouse_position.x = e.pageX; mouse_position.y = e.pageY; } function game_tick(delta) { //calculations do_movement(delta); do_collisions(); move_camera(); //rendering render_background(); render_characters(); render_nodes(); render_usernames(); } function render_characters() { let ctx = canvas.getContext("2d"); characters.forEach(function(itr, idx) { ctx.save(); let character_position = global_to_canvas(itr.position); ctx.translate(character_position.x, character_position.y); ctx.rotate(itr.rotation); let image = game_data.character.variants[itr.variant]; ctx.drawImage(image, -50, -50, dwidth = 100, dheight = 100); ctx.restore(); }); } function render_usernames() { let ctx = canvas.getContext("2d"); characters.forEach(function(itr, idx) { ctx.save(); let character_position = global_to_canvas(itr.position); ctx.translate(character_position.x, character_position.y-80); //measure text ctx.font = "15px Arial"; let size = ctx.measureText(itr.username); //draw name plate round_rect(ctx, -((size.width/2)+12), -20, size.width+24, 30, 4, "#555555aa", undefined); //draw name ctx.font = "15px Arial"; ctx.textAlign = "center"; ctx.fillStyle = "white"; ctx.fillText(itr.username, 0, 0); ctx.restore(); }); } function render_background() { let ctx = canvas.getContext("2d"); let image = game_data.world.biome.forest.ground.img; for (let i = -2500; i < 5000; i += image.width) { for (let j = -2500; j < 5000; j += image.height) { ctx.save(); let where_this_ground = global_to_canvas(new vector(i, j)); ctx.translate(where_this_ground.x, where_this_ground.y); ctx.drawImage(image, 0, 0); ctx.restore(); } } } function render_nodes() { let ctx = canvas.getContext("2d"); nodes.forEach(function(itr, idx) { ctx.save(); let position = global_to_canvas(itr.position); let rotation = itr.rotation; let image = game_data.world.biome.forest[itr.type].img; ctx.translate(position.x, position.y); ctx.rotate(rotation); ctx.drawImage(image, -itr.size/2, -itr.size/2, dwidth=itr.size, dheight=itr.size); ctx.restore(); }); } function move_camera() { camera.x = player.position.x; camera.y = player.position.y; } function open_socket() { server = new WebSocket(server_url); server.onopen = function() { server.send(JSON.stringify({ "type": "init", "data": { "username": player.username, "variant": player.variant } })); update_server_tick = setInterval(send_position_to_server, 1000/20); } server.onmessage = function(thing) { let thingp = JSON.parse(thing.data); message(thingp.type, thingp.data); } } function send_position_to_server() { let data = { "type": "movement", "data": { "position": player.position, "rotation": player.rotation } } server.send(JSON.stringify(data)); if (server.readyState != 1) { clearInterval(update_server_tick); console.log("disconnected from server"); } } //interaction var interact_interval; var punching = false; var mouse_down = false; document.body.onmousedown = function() { mouse_down = true; } document.body.onmouseup = function() { mouse_down = false; } function interact() { if (!punching) { punching = true; interact_interval = setInterval(interaction_animation, 1000/fps, Date.now()); server.send(JSON.stringify({ "type": "interact", "data": undefined })); } } function inter_anim_curve(x) { return -15*Math.pow(x-0.25, 2)+1; } function interaction_animation(start_time) { let now = Date.now(); let x = (now - start_time)/1000; //console.log(inter_anim_curve(x)); rotation_offset = inter_anim_curve(x)/2; if (x >= 0.5) { clearInterval(interact_interval); rotation_offset = 0; punching = false; } }