ferencd@0: const pic_size = 64; // The size of 1 cell in the maze ferencd@0: ferencd@0: // initial position of the player is always: (0,0) ie. 12px 12px considering the wall size the the top and left ferencd@0: let x = 12; ferencd@0: let y = 12; ferencd@0: ferencd@0: // moving direction of the player ferencd@0: var x_delta = 0; ferencd@0: var y_delta = 0; ferencd@0: ferencd@0: // player location in grid ferencd@0: var col = 0; // The column in the maze where the player is ferencd@0: var row = 0; // The row in the maze where the player is ferencd@0: ferencd@0: // Prepare the canvas ferencd@0: var canvas = document.getElementById("canvas"); ferencd@0: var canvas_container = document.getElementById("canvasdiv"); ferencd@0: var context = canvas.getContext('2d'); ferencd@0: ferencd@0: // canvas size calculation ferencd@0: var canvas_calc_width = w * pic_size ; ferencd@0: var canvas_calc_height = h * pic_size; ferencd@0: ferencd@0: canvas.style.width = canvas_calc_width + "px"; ferencd@0: canvas.style.height = canvas_calc_height + "px"; ferencd@0: ferencd@0: canvas.width = canvas_calc_width; ferencd@0: canvas.height = canvas_calc_height; ferencd@0: ferencd@0: // Approximates the last row/col drawn for the canvas scrolling ferencd@0: var last_row_drawn = canvas_container.offsetHeight / pic_size; ferencd@0: var first_row_drawn = 0; ferencd@0: var last_col_drawn = canvas_container.offsetWidth / pic_size; ferencd@0: var first_col_drawn = 0; ferencd@0: ferencd@0: // fill the canvas with black ferencd@0: context.fillStyle = "black"; ferencd@0: context.fillRect(0, 0, canvas.width, canvas.height); ferencd@0: ferencd@0: // constants for direction checking ferencd@0: const N = 1; ferencd@0: const S = 2; ferencd@0: const E = 4; ferencd@0: const W = 8; ferencd@0: ferencd@0: // Corner constants, to know where to put a torch ferencd@0: const TOP_LEFT = 1; ferencd@0: const TOP_RIGHT = 2; ferencd@0: const BOTTOM_LEFT = 4; ferencd@0: const BOTTOM_RIGHT = 8; ferencd@0: ferencd@0: // How far must we be from the maze edge to trigger scrolling ferencd@0: const MAZE_EDGE_DISTANCE_SCROLL_TRIGGER = 4; ferencd@0: ferencd@0: // How much we can see from the maze ferencd@0: var LIGHT_RADIUS = 3; ferencd@0: ferencd@0: // how the maze looks ferencd@0: const FULL_FOG = 0; ferencd@0: const FULL_DRAWN = 1; ferencd@0: const FOG_DRAWN = 2; ferencd@0: ferencd@0: // indexes of the various directions the player can go ferencd@0: const MOVE_IDX_LEFT = 0; ferencd@0: const MOVE_IDX_UP = 1; ferencd@0: const MOVE_IDX_RIGHT = 2; ferencd@0: const MOVE_IDX_DOWN = 3; ferencd@0: ferencd@0: // Player state: Dead/Alive ferencd@0: const PLAYER_ALIVE = 1; ferencd@0: const PLAYER_DIED = 2; ferencd@0: var player_state = PLAYER_ALIVE; ferencd@0: ferencd@0: // Player weapon ferencd@0: const WEAPON_NONE = -1; ferencd@0: const WEAPON_SPEAR = 0; ferencd@0: ferencd@0: var player_weapon = WEAPON_NONE; ferencd@0: ferencd@0: // Player armor ferencd@0: const ARMOR_NONE = -1; ferencd@0: const ARMOR_CHAINMAIL = 1; ferencd@0: const SHOES = 2; ferencd@0: const RING = 3; ferencd@0: var player_armor = ARMOR_NONE; ferencd@0: ferencd@0: // whether we remove life from steps or not ferencd@0: const STEPS_COST = 0; // each step is 1 life ferencd@0: const STEPS_FREE = 1; // steps do not cost 1 life ferencd@0: const STEPS_SICK = 2; // player is sick, steps cost 2 life ferencd@0: var player_steps = STEPS_COST; ferencd@0: var step_count = 0; ferencd@0: ferencd@0: const TIME_HAS_EFFECT = 0; ferencd@0: const TIME_HAS_NO_EFFECT = 1; ferencd@0: var time_effect = TIME_HAS_EFFECT; ferencd@0: ferencd@0: const GAME_SUSPENDED = 1; ferencd@0: const GAME_RUNNING = 0; ferencd@0: var game_state = GAME_SUSPENDED; ferencd@0: ferencd@0: var time_passing_timeout = null; ferencd@0: ferencd@0: // These correspond to specific igw types: ferencd@0: // 0 - empty handed skeleton. Can be killed with SPEAR or anything above ferencd@0: // 1 - skeleton with spear. Can be killed with Spear but only if player has armor ferencd@0: // 2 - skeleton with bow. Does not move, just shoots. Can be killed with spear and armor ferencd@0: // 3 - skeletong with spear and armor. Cannot be killed ferencd@0: ferencd@0: function init_maze_draw_array() ferencd@0: { ferencd@0: var r = new Array(h); ferencd@0: for(var j=0; jNot all food is safe down here.", ferencd@0: "The is an easy prey when you have a .

Wearing also increases your chance of survival.

Otherwise ... you are easy prey to them.", ferencd@0: "You definitely should have eaten something on the way.

Finding the and the also helps.", ferencd@0: leave_text ferencd@0: ]; ferencd@0: ferencd@0: ferencd@0: const GO_BAD_FOOD = 1; ferencd@0: const GO_SKELETON = 2; ferencd@0: const GO_FATIGUE = 3; ferencd@0: const GO_LEVEL_DONE = 4; ferencd@0: ferencd@0: // reason: 1 = player died since he ate something he wasn't supposed to ferencd@0: // 2 = player was killed by a skeleton ferencd@0: // 3 = fatigue ferencd@0: // 4 = player finished the current level ferencd@0: function game_over(reason, i) ferencd@0: { ferencd@0: if(reason === GO_SKELETON) ferencd@0: { ferencd@0: killer_igwidx = i; ferencd@0: context.putImageData(igw[killer_igwidx].savedImage, igw[killer_igwidx].x, igw[killer_igwidx].y); ferencd@0: } ferencd@0: document.getElementById("goimg").style.visibility = 'visible'; ferencd@0: ferencd@0: var final_message = go_texts[reason - 1]; ferencd@0: if(reason !== GO_LEVEL_DONE) ferencd@0: { ferencd@0: update_life_visuals(0); ferencd@0: ferencd@0: player_dies(); ferencd@0: draw_a_wall(row,col); ferencd@0: context.drawImage(dying_player[5], x, y); ferencd@0: ferencd@0: final_message += story_text; ferencd@0: document.getElementById("goimg").src ="/img/gameover.png"; ferencd@0: player_state = PLAYER_DIED; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: document.getElementById('gonextlevel').style.visibility='visible'; ferencd@0: clearTimeout(time_passing_timeout); ferencd@0: } ferencd@0: ferencd@0: if(game_type === GAME_TYPE_TIMERUN) ferencd@0: { ferencd@0: final_message += "

" + document.getElementById("time_passed").innerHTML; ferencd@0: } ferencd@0: ferencd@0: document.getElementById("messages").style.visibility = 'visible'; ferencd@0: document.getElementById("messages").style.display = 'block'; ferencd@0: document.getElementById("gotext1").style.visibility = 'visible'; ferencd@0: document.getElementById("gotext1").innerHTML = final_message; ferencd@0: document.getElementById("gospan").style.visibility = 'hidden'; ferencd@0: ferencd@0: document.getElementById("sysmenu").style.visibility = 'hidden'; ferencd@0: ferencd@0: game_state = GAME_SUSPENDED; ferencd@0: } ferencd@0: ferencd@0: var maze_stats = init_maze_draw_array(); ferencd@0: ferencd@0: function point_in_circle(center_x, center_y, radius, x, y) ferencd@0: { ferencd@0: var D = Math.sqrt(Math.pow(center_x - x, 2) + Math.pow(center_y - y, 2)); ferencd@0: return D <= radius ferencd@0: } ferencd@0: ferencd@0: function draw_torches(next) ferencd@0: { ferencd@0: for(var i=0; i= pic_size / 2) ferencd@0: || (igw[i].saver === row && igw[i].savec === col) ferencd@0: )) ferencd@0: || dc; ferencd@0: } ferencd@0: ferencd@0: // Checks whether the player has a corresponding weapon which he can use to kill igw[i]. ferencd@0: // igw[i].t is the type of the igw and if the player weapon > igw[i].t then it can kill. ferencd@0: function player_has_corresponding_weapon(i) ferencd@0: { ferencd@0: // Fully equipped player will kill everything ferencd@0: if (player_armor === ARMOR_CHAINMAIL && player_weapon === WEAPON_SPEAR) ferencd@0: { ferencd@0: return true; ferencd@0: } ferencd@0: // player with spear will kill simple skeletons ferencd@0: if(player_weapon === WEAPON_SPEAR && igw[i].t === 0) ferencd@0: { ferencd@0: return true; ferencd@0: } ferencd@0: return (player_weapon >= igw[i].t); ferencd@0: } ferencd@0: ferencd@0: function player_has_armor() ferencd@0: { ferencd@0: return player_armor === ARMOR_CHAINMAIL; ferencd@0: } ferencd@0: ferencd@0: var anim_mod = 0; ferencd@0: ferencd@0: function resolve_weapon(weapon_here) { ferencd@0: if (weapon_here === RING) // ring, will stop the time ferencd@0: { ferencd@0: time_effect = TIME_HAS_NO_EFFECT; ferencd@0: document.getElementById("ring_of_health_div").style.visibility = 'visible'; ferencd@0: } ferencd@0: else if (weapon_here === SHOES) // shoes ferencd@0: { ferencd@0: if (player_armor === ARMOR_NONE) // player has no armor, images shoudl be lr_player_shoes ferencd@0: { ferencd@0: if(player_weapon === WEAPON_SPEAR) ferencd@0: { ferencd@0: player_imgset_index = 5; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: player_imgset_index = 4; ferencd@0: } ferencd@0: } ferencd@0: player_steps = STEPS_FREE; ferencd@0: document.getElementById("boots_of_light_div").style.visibility = 'visible'; ferencd@0: LIGHT_RADIUS = 5; ferencd@0: } ferencd@0: else if (weapon_here === WEAPON_SPEAR) // spear ferencd@0: { ferencd@0: player_weapon = WEAPON_SPEAR; ferencd@0: if (player_armor === ARMOR_NONE) // player has no armor, images shoudl be lr_player_spear ferencd@0: { ferencd@0: if(player_steps === STEPS_FREE) // Are there shoes on the player? ferencd@0: { ferencd@0: player_imgset_index = 5; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: player_imgset_index = 1; ferencd@0: } ferencd@0: } ferencd@0: else if (player_armor === ARMOR_CHAINMAIL) // player has armor, images should be lr_player_armor_spear ferencd@0: { ferencd@0: player_imgset_index = 2; ferencd@0: } ferencd@0: } ferencd@0: else if (weapon_here === ARMOR_CHAINMAIL) // found the armor ferencd@0: { ferencd@0: player_armor = ARMOR_CHAINMAIL; ferencd@0: if (player_weapon === WEAPON_SPEAR) { ferencd@0: player_imgset_index = 2; ferencd@0: } ferencd@0: else if (player_weapon === WEAPON_NONE) { ferencd@0: player_imgset_index = 3; ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: function resolve_loot(t) ferencd@0: { ferencd@0: var loot_value = item_value[t]; ferencd@0: var current_gold = parseInt(document.getElementById("gold").innerHTML); ferencd@0: current_gold += loot_value; ferencd@0: document.getElementById("gold").innerHTML = current_gold.toString(); ferencd@0: } ferencd@0: ferencd@0: function igw_kills_player(i) ferencd@0: { ferencd@0: if (!player_has_corresponding_weapon(i)) ferencd@0: { ferencd@0: if(player_has_armor()) ferencd@0: { ferencd@0: let current_life = parseInt(document.getElementById("energy").innerHTML); ferencd@0: let temp_health = current_life - 1; ferencd@0: ferencd@0: if (temp_health <= 0) ferencd@0: { ferencd@0: game_over(GO_SKELETON, i); ferencd@0: return true; ferencd@0: } ferencd@0: update_life_visuals(temp_health); ferencd@0: return false; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: game_over(GO_SKELETON, i); ferencd@0: return true; ferencd@0: } ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: if(igw_touches_player(i, true)) { ferencd@0: kill_igw(i); ferencd@0: } ferencd@0: return false; ferencd@0: } ferencd@0: ferencd@0: } ferencd@0: ferencd@0: var small_fellow_anim_idx = 0; ferencd@0: var small_fellow_anim_runs = false; ferencd@0: ferencd@0: function walkers_simulation() ferencd@0: { ferencd@0: if(player_state === PLAYER_DIED) ferencd@0: { ferencd@0: context.drawImage(dying_player[5], x, y); ferencd@0: return; ferencd@0: } ferencd@0: ferencd@0: if(game_state === GAME_SUSPENDED) ferencd@0: { ferencd@0: return; ferencd@0: } ferencd@0: ferencd@0: if(small_fellow_anim_runs && small_fellow_anim_idx < pic_size) ferencd@0: { ferencd@0: if(ffImgDataPrev) ferencd@0: { ferencd@0: context.putImageData(ffImgDataPrev, ffx, ffy); // clear canvas ferencd@0: } ferencd@0: ferencd@0: small_fellow_anim_idx ++; ferencd@0: ffx += ffdx; ferencd@0: ffy += ffdy; ferencd@0: ferencd@0: ffImgDataPrev = context.getImageData(ffx,ffy, anim_size, anim_size); ferencd@0: ferencd@0: context.drawImage(small_fellow, ffx, ffy); ferencd@0: ferencd@0: } ferencd@0: ferencd@0: // moving player drawing ferencd@0: if(animation_running) ferencd@0: { ferencd@0: if(!walkers_updating) ferencd@0: { ferencd@0: context.putImageData(imgDataPrev, x, y); // clear canvas ferencd@0: x += x_delta; ferencd@0: y += y_delta; ferencd@0: anim_mod = anim_mod + 1; ferencd@0: if (anim_mod % 4 === 0) current_anim_counter += 1; ferencd@0: if (current_anim_counter < pic_size / 4) { ferencd@0: imgDataPrev = context.getImageData(x, y, anim_size, anim_size); ferencd@0: } ferencd@0: else { ferencd@0: animation_running = false; ferencd@0: current_anim_counter = 0; ferencd@0: ferencd@0: // and here verify what is on the square we arrived to ferencd@0: ferencd@0: // 1. See did we find the exit? ferencd@0: if (col === exit_col && row === exit_row) { ferencd@0: game_over(GO_LEVEL_DONE, -1); ferencd@0: return; ferencd@0: } ferencd@0: ferencd@0: // 2. Any foodstuff or other here? ferencd@0: var food_type_here = have_food_here(row, col); ferencd@0: var maze_redraw_needed = false; ferencd@0: if (food_type_here !== -1) { ferencd@0: var current_life = parseInt(document.getElementById("energy").innerHTML); ferencd@0: var temp_health = current_life + food_effects[food_type_here]; ferencd@0: remove_food(row, col); ferencd@0: maze_redraw_needed = true; ferencd@0: if (temp_health > 100) { ferencd@0: temp_health = 100; ferencd@0: } ferencd@0: if (temp_health <= 0) { ferencd@0: game_over(GO_BAD_FOOD, -1); ferencd@0: return; ferencd@0: } ferencd@0: ferencd@0: update_life_visuals(temp_health); ferencd@0: } ferencd@0: ferencd@0: // Are we next to the small guy with a visible line? ferencd@0: if( row > h - 4 && col > w - 4 && game_type === GAME_TYPE_STORY) ferencd@0: { ferencd@0: small_fellow_needs_to_be_drawn = false; ferencd@0: maze_redraw_needed = true; ferencd@0: small_fellow_anim_runs = true; ferencd@0: } ferencd@0: ferencd@0: // see if there is a wepon there ferencd@0: var weapon_here = have_weapon_here(row, col); ferencd@0: if (weapon_here !== -1) ferencd@0: { ferencd@0: resolve_weapon(weapon_here); ferencd@0: remove_weapon(row, col); ferencd@0: maze_redraw_needed = true; ferencd@0: } ferencd@0: ferencd@0: // if this is an adventure game, see if there is any loot here ferencd@0: if(game_type === GAME_TYPE_ADVENTURE) ferencd@0: { ferencd@0: // see if there is a wepon there ferencd@0: var loot_here = have_loot_here(row, col); ferencd@0: if (loot_here !== -1) ferencd@0: { ferencd@0: resolve_loot(loot_here); ferencd@0: remove_loot(row, col); ferencd@0: maze_redraw_needed = true; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: if (maze_redraw_needed) ferencd@0: { ferencd@0: draw_maze(col, row, true); ferencd@0: imgDataPrev = context.getImageData(x, y, anim_size, anim_size); ferencd@0: } ferencd@0: ferencd@0: // see if this was a hit operation or not ferencd@0: if(anim_modder === thrust_anim_cnt) ferencd@0: { ferencd@0: // update the image set for the walking ferencd@0: anim_modder = step_anim_cnt; ferencd@0: player_imgset_index -= 6; ferencd@0: } ferencd@0: } ferencd@0: context.drawImage(get_current_player_image(player_dir), x, y); ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: draw_torches(true); ferencd@0: ferencd@0: window.walkers_updating = true; ferencd@0: var drawn_walkers = []; ferencd@0: ferencd@0: for (var i = 0; i < igw.length; i++) { ferencd@0: if (igw[i].state === DEAD) { ferencd@0: context.drawImage(skel_dies[5], igw[i].x, igw[i].y); ferencd@0: continue; ferencd@0: } ferencd@0: ferencd@0: igw[i].anim_mod = !igw[i].anim_mod; ferencd@0: if (igw[i].anim_mod) igw[i].anim_ctr++; ferencd@0: igw[i].just_updated = false; ferencd@0: ferencd@0: igw[i].saver = igw[i].r; ferencd@0: igw[i].savec = igw[i].c; ferencd@0: ferencd@0: if (igw_touches_player(i,false)) ferencd@0: { ferencd@0: if(igw_kills_player(i)) ferencd@0: { ferencd@0: return; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: if (igw[i].anim_ctr > pic_size / 2 - 1) { ferencd@0: // means we have stepped over the current tile, time to advance to the next one ferencd@0: igw[i].path_ctr = igw[i].path_ctr + igw[i].move_dir; ferencd@0: // console.log("igw[",i,'].path_ctr=',igw[i].path_ctr,' path_len=',igw[i].path_len); ferencd@0: if (igw[i].path_ctr === igw[i].path_len || igw[i].path_ctr < 0) { ferencd@0: // just perform a routine check that the last step of the igw does not kill the player ferencd@0: var tempr = igw[i].r; ferencd@0: var tempc = igw[i].c; ferencd@0: update_igw_location(i); ferencd@0: if (igw_touches_player(i,false)) ferencd@0: { ferencd@0: if(igw_kills_player(i)) ferencd@0: { ferencd@0: return; ferencd@0: } ferencd@0: } ferencd@0: //draw_a_wall(igw[i].r, igw[i].c); ferencd@0: ferencd@0: igw[i].r = tempr; ferencd@0: igw[i].c = tempc; ferencd@0: ferencd@0: // this reverses the igw ferencd@0: igw[i].move_dir = -igw[i].move_dir; ferencd@0: igw[i].path_ctr --; ferencd@0: if(igw[i].path_ctr < 0) ferencd@0: { ferencd@0: igw[i].path_ctr = 0; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: igw[i].dir = get_direction(igw[i].p[igw[i].path_ctr], igw[i].move_dir); ferencd@0: update_igw_location(i); ferencd@0: igw[i].anim_ctr = 0; ferencd@0: } ferencd@0: ferencd@0: if (maze_stats[igw[i].r][igw[i].c] === FULL_DRAWN && igw[i].savedImage === null) ferencd@0: { ferencd@0: igw[i].savedImage = context.getImageData(igw[i].x, igw[i].y, anim_size, anim_size); ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: if (maze_stats[igw[i].r][igw[i].c] === FOG_DRAWN) { ferencd@0: context.drawImage(fog_drawn_wall_images[maze[igw[i].r][igw[i].c]], igw[i].c * pic_size, igw[i].r * pic_size); ferencd@0: } ferencd@0: ferencd@0: // do we move away from a full drawn cell? ferencd@0: if (maze_stats[igw[i].saver][igw[i].savec] === FULL_DRAWN) { ferencd@0: draw_a_wall(igw[i].saver, igw[i].savec); ferencd@0: } ferencd@0: if (igw[i].savedImage === null) { ferencd@0: igw[i].savedImage = context.getImageData(igw[i].x, igw[i].y, anim_size, anim_size); ferencd@0: } ferencd@0: ferencd@0: } ferencd@0: ferencd@0: // restore the background ferencd@0: if( maze_stats[igw[i].r][igw[i].c] === FULL_DRAWN && igw[i].savedImage !== null && maze_stats[igw[i].saver][igw[i].savec] === FULL_DRAWN ) ferencd@0: { ferencd@0: draw_a_wall(igw[i].r, igw[i].c); ferencd@0: // draw_extra_objects(igw[i].r, igw[i].c, igw[i].r * pic_size, igw[i].c * pic_size) ferencd@0: context.putImageData(igw[i].savedImage, igw[i].x, igw[i].y); ferencd@0: ferencd@0: // draw only torches which are being affected ferencd@0: for (var k = 0; k < torches.length; k++) { ferencd@0: if (torches[k].i === igw[i].c && torches[k].j === igw[i].r) { ferencd@0: context.drawImage(torch_images[torches[k].anim_idx], torches[k].x, torches[k].y); ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: // move the walker on the screen ferencd@0: move_igw(i); ferencd@0: ferencd@0: if (maze_stats[igw[i].r][igw[i].c] === FULL_DRAWN) { ferencd@0: igw[i].savedImage = context.getImageData(igw[i].x, igw[i].y, anim_size, anim_size); ferencd@0: let dir_idx = get_dir_idx(igw[i].dir); ferencd@0: let ani_idx = igw[i].anim_ctr % igw[i].step_cnt; ferencd@0: // console.log('igw[i].dir',igw[i].dir, 'dir_idx',dir_idx,'ani_idx',ani_idx); ferencd@0: context.drawImage(walker_images[igw[i].t][dir_idx][ani_idx], igw[i].x, igw[i].y); ferencd@0: drawn_walkers.push({ ferencd@0: img: walker_images[igw[i].t][dir_idx][igw[i].anim_ctr % igw[i].step_cnt], ferencd@0: x: igw[i].x, ferencd@0: y: igw[i].y, ferencd@0: r: igw[i].r, ferencd@0: c: igw[i].c ferencd@0: }); ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: // and just draw again all the walkers that were drawn ferencd@0: if (drawn_walkers.length > 0) { ferencd@0: for (i = 0; i < drawn_walkers.length; i++) { ferencd@0: if (maze_stats[drawn_walkers[i].r][drawn_walkers[i].c] === FULL_DRAWN && ferencd@0: maze_stats[igw[i].saver][igw[i].savec] === FULL_DRAWN) { ferencd@0: context.drawImage(drawn_walkers[i].img, drawn_walkers[i].x, drawn_walkers[i].y); ferencd@0: } ferencd@0: } ferencd@0: // and the player ferencd@0: context.drawImage(get_current_player_image(player_dir), x, y); ferencd@0: } ferencd@0: window.walkers_updating = false; ferencd@0: ferencd@0: requestAnimationFrame(walkers_simulation); ferencd@0: } ferencd@0: ferencd@0: // previous image which was placed on the canvas ferencd@0: var imgDataPrev = null; ferencd@0: ferencd@0: ferencd@0: /* Mouse scroll handling */ ferencd@0: // The canvas will scroll back to these coordinates when done with mouse move ferencd@0: var marginLeftBackup = 0; ferencd@0: var marginTopBackup = 0; ferencd@0: var dragging = false; ferencd@0: var lastX = 0; ferencd@0: var lastY = 0; ferencd@0: var marginLeft = 0; ferencd@0: var marginTop = 0; ferencd@0: // mouse press handler ferencd@0: function mouse_press(e) ferencd@0: { ferencd@0: var evt = e || event; ferencd@0: dragging = true; ferencd@0: lastX = evt.clientX; ferencd@0: lastY = evt.clientY; ferencd@0: marginLeftBackup = canvas.style.marginLeft; ferencd@0: marginTopBackup = canvas.style.marginTop; ferencd@0: e.preventDefault(); ferencd@0: } ferencd@0: ferencd@0: function mouse_move(e) ferencd@0: { ferencd@0: var evt = e || event; ferencd@0: if (dragging) { ferencd@0: var deltaX = evt.clientX - lastX; ferencd@0: lastX = evt.clientX; ferencd@0: ferencd@0: if(marginLeft + deltaX <= 0 && canvas.width - Math.abs(marginLeft + deltaX) >= canvas_container.offsetWidth) // did we scroll out left/right ferencd@0: { ferencd@0: marginLeft += deltaX; ferencd@0: canvas.style.marginLeft = marginLeft + "px"; ferencd@0: } ferencd@0: ferencd@0: var deltaY = evt.clientY - lastY; ferencd@0: lastY = evt.clientY; ferencd@0: if(marginTop + deltaY <= 0 && canvas.height - Math.abs(marginTop + deltaY) >= canvas_container.offsetHeight) ferencd@0: { ferencd@0: marginTop += deltaY; ferencd@0: canvas.style.marginTop = marginTop + "px"; ferencd@0: } ferencd@0: } ferencd@0: e.preventDefault(); ferencd@0: } ferencd@0: ferencd@0: function mouse_up() { ferencd@0: dragging = false; ferencd@0: canvas.style.marginLeft = marginLeftBackup; ferencd@0: canvas.style.marginTop = marginTopBackup; ferencd@0: } ferencd@0: ferencd@0: var canv_anim_counter = 0; ferencd@0: var canv_moving_direction_ud = 0; ferencd@0: function animate_canvas_movement_up_down() { ferencd@0: canv_anim_counter += 1; ferencd@0: marginTop += canv_moving_direction_ud; ferencd@0: if (canv_anim_counter < pic_size) ferencd@0: { ferencd@0: requestAnimationFrame(animate_canvas_movement_up_down); ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: canv_anim_counter = 0; ferencd@0: } ferencd@0: if(canv_moving_direction_ud === -1) ferencd@0: { ferencd@0: if(canvas.height - Math.abs(marginTop) >= canvas_container.offsetHeight) ferencd@0: { ferencd@0: canvas.style.marginTop = marginTop + "px"; ferencd@0: } ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: if(marginTop <= 0) ferencd@0: { ferencd@0: canvas.style.marginTop = marginTop + "px"; ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: var canv_moving_direction_lr = 0; ferencd@0: function animate_canvas_movement_left_right() { ferencd@0: canv_anim_counter += 1; ferencd@0: marginLeft += canv_moving_direction_lr; ferencd@0: if (canv_anim_counter < pic_size) ferencd@0: { ferencd@0: requestAnimationFrame(animate_canvas_movement_left_right); ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: canv_anim_counter = 0; ferencd@0: } ferencd@0: if(canv_moving_direction_lr === -1) ferencd@0: { ferencd@0: if(canvas.width - Math.abs(marginLeft) >= canvas_container.offsetWidth) ferencd@0: { ferencd@0: canvas.style.marginLeft = marginLeft + "px"; ferencd@0: } ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: if(marginLeft <= 0) ferencd@0: { ferencd@0: canvas.style.marginLeft = marginLeft + "px"; ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: function remove_food(row, col) ferencd@0: { ferencd@0: for(var i=0; i= last_col_drawn - MAZE_EDGE_DISTANCE_SCROLL_TRIGGER) ferencd@0: { ferencd@0: last_col_drawn ++ ; ferencd@0: first_col_drawn ++; ferencd@0: canv_moving_direction_lr = -1; ferencd@0: canv_anim_counter = 0; ferencd@0: animate_canvas_movement_left_right(); ferencd@0: lr_scrolled = true; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: if(px_delta === -1) // left ferencd@0: { ferencd@0: if(col <= first_col_drawn + MAZE_EDGE_DISTANCE_SCROLL_TRIGGER && !lr_scrolled && first_col_drawn > 0) ferencd@0: { ferencd@0: last_col_drawn -- ; ferencd@0: first_col_drawn --; ferencd@0: canv_moving_direction_lr = 1; ferencd@0: canv_anim_counter = 0; ferencd@0: animate_canvas_movement_left_right(); ferencd@0: lr_scrolled = true; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: if(py_delta === 1) // down ferencd@0: { ferencd@0: if(row >= last_row_drawn - MAZE_EDGE_DISTANCE_SCROLL_TRIGGER && !lr_scrolled) ferencd@0: { ferencd@0: last_row_drawn ++ ; ferencd@0: first_row_drawn ++; ferencd@0: canv_moving_direction_ud = -1; ferencd@0: canv_anim_counter = 0; ferencd@0: animate_canvas_movement_up_down(); ferencd@0: ud_scrolled = true; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: if(py_delta === -1) //up ferencd@0: { ferencd@0: if(row <= first_row_drawn + MAZE_EDGE_DISTANCE_SCROLL_TRIGGER && !lr_scrolled && !ud_scrolled && first_row_drawn > 0) ferencd@0: { ferencd@0: last_row_drawn -- ; ferencd@0: first_row_drawn --; ferencd@0: canv_moving_direction_ud = 1; ferencd@0: canv_anim_counter = 0; ferencd@0: animate_canvas_movement_up_down(); ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: row = t_row; ferencd@0: col = t_col; ferencd@0: ferencd@0: anim_modder = step_anim_cnt; ferencd@0: window.animation_running = true; ferencd@0: current_anim_counter = 0; ferencd@0: x_delta = px_delta; ferencd@0: y_delta = py_delta; ferencd@0: } ferencd@0: ferencd@0: // and finally make sure the player is drawn back normally where it's supposed to be ferencd@0: draw_maze(col, row, true); ferencd@0: context.drawImage(get_current_player_image(player_dir), x, y); ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: function sleep(ms) ferencd@0: { ferencd@0: return new Promise(resolve => setTimeout(resolve, ms)); ferencd@0: } ferencd@0: ferencd@0: function hit_something() ferencd@0: { ferencd@0: if(! animation_running) // this tells us if we are in an animation ferencd@0: { ferencd@0: x_delta = 0; ferencd@0: y_delta = 0; ferencd@0: player_imgset_index += 6; ferencd@0: anim_modder = thrust_anim_cnt; ferencd@0: window.animation_running = true; ferencd@0: current_anim_counter = 0; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: // the keyboard handler ferencd@0: async function keypressed(e) ferencd@0: { ferencd@0: if(player_state === PLAYER_ALIVE) ferencd@0: { ferencd@0: let slept = 1; ferencd@0: while(window.walkers_updating && slept < 60) ferencd@0: { ferencd@0: slept ++; ferencd@0: await sleep(20); ferencd@0: } ferencd@0: ferencd@0: var code = e.keyCode; ferencd@0: switch (code) { ferencd@0: case 37: step(MOVE_IDX_LEFT, -1, 0); break; //Left key ferencd@0: case 38: step(MOVE_IDX_UP, 0, -1); break; //Up key ferencd@0: case 39: step(MOVE_IDX_RIGHT, 1, 0); break; //Right key ferencd@0: case 40: step(MOVE_IDX_DOWN, 0, 1); break; //Down key ferencd@0: case 32: hit_something(); // Space ferencd@0: ferencd@0: default: console.log(code); //Everything else ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: Element.prototype.remove = function() { ferencd@0: this.parentElement.removeChild(this); ferencd@0: }; ferencd@0: NodeList.prototype.remove = HTMLCollection.prototype.remove = function() { ferencd@0: for(var i = this.length - 1; i >= 0; i--) { ferencd@0: if(this[i] && this[i].parentElement) { ferencd@0: this[i].parentElement.removeChild(this[i]); ferencd@0: } ferencd@0: } ferencd@0: }; ferencd@0: ferencd@0: function toggle_gos(visible) ferencd@0: { ferencd@0: document.getElementById('gotext1').style.visibility=visible?'visible':'hidden'; ferencd@0: document.getElementById('gotext2').style.visibility=visible?'visible':'hidden'; ferencd@0: document.getElementById('gotext3').style.visibility=visible?'visible':'hidden'; ferencd@0: document.getElementById('gotext4').style.visibility=visible?'visible':'hidden'; ferencd@0: document.getElementById('gotext5').style.visibility=visible?'visible':'hidden'; ferencd@0: ferencd@0: } ferencd@0: ferencd@0: document.getElementById('badbrowser').remove(); ferencd@0: document.getElementById('gobutton').style.visibility='visible'; ferencd@0: toggle_gos(true); ferencd@0: ferencd@0: function time_passes_by() ferencd@0: { ferencd@0: if(player_state === PLAYER_DIED) ferencd@0: { ferencd@0: context.drawImage(dying_player[5], x, y); ferencd@0: return; ferencd@0: } ferencd@0: if(time_effect === TIME_HAS_EFFECT) ferencd@0: { ferencd@0: var current_life = parseInt(document.getElementById("energy").innerHTML); ferencd@0: current_life --; ferencd@0: update_life_visuals(current_life); ferencd@0: if(current_life <= 0) ferencd@0: { ferencd@0: game_over(GO_FATIGUE, -1); ferencd@0: ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: setTimeout(time_passes_by, 3000); ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: var seconds_passed = 0; ferencd@0: var minutes_passed = 0; ferencd@0: var hours_passed = 0; ferencd@0: var days_passed = 0; ferencd@0: ferencd@0: function time_tick() ferencd@0: { ferencd@0: seconds_passed ++; ferencd@0: if(seconds_passed === 60) ferencd@0: { ferencd@0: minutes_passed ++; ferencd@0: if(minutes_passed === 60) ferencd@0: { ferencd@0: hours_passed ++; ferencd@0: if(hours_passed === 24) ferencd@0: { ferencd@0: days_passed ++; ferencd@0: hours_passed = 0; ferencd@0: } ferencd@0: minutes_passed = 0; ferencd@0: } ferencd@0: seconds_passed = 0; ferencd@0: } ferencd@0: ferencd@0: let new_time = hours_passed.toString() + "h : " + minutes_passed.toString() + "m : " + seconds_passed.toString() + "s " + " "; ferencd@0: if(days_passed > 0) ferencd@0: { ferencd@0: new_time = days_passed.toString() + "days "; ferencd@0: } ferencd@0: document.getElementById('time_passed').innerHTML = new_time; ferencd@0: time_passing_timeout = setTimeout(time_tick, 1000); ferencd@0: ferencd@0: } ferencd@0: ferencd@0: function get_current_level() { ferencd@0: var lid = document.getElementById('lid').value; ferencd@0: var level = parseInt(lid); ferencd@0: return {level: level}; ferencd@0: } ferencd@0: ferencd@0: function setup_labyrinth(evt) ferencd@0: { ferencd@0: if(game_type === GAME_TYPE_TIMERUN) ferencd@0: { ferencd@0: time_effect = TIME_HAS_NO_EFFECT; ferencd@0: player_steps = STEPS_FREE; ferencd@0: } ferencd@0: ferencd@0: var __ret = get_current_level(); ferencd@0: var level = __ret.level; ferencd@0: document.getElementById('levelctr').innerHTML = level.toString(); ferencd@0: ferencd@0: var gid = document.getElementById('gid').value; ferencd@0: document.getElementById('gameid').innerHTML = "" + gid + " "; ferencd@0: ferencd@0: document.getElementById('messages').style.visibility='hidden'; ferencd@0: document.getElementById('gobutton').style.visibility='hidden'; ferencd@0: ferencd@0: toggle_gos(false); ferencd@0: ferencd@0: // draw the maze ferencd@0: draw_maze(col, row, false); ferencd@0: ferencd@0: // set up the previous image data in order to save it for the next animation step ferencd@0: imgDataPrev = context.getImageData(x,y, anim_size, anim_size); ferencd@0: ferencd@0: // draw the player ferencd@0: context.drawImage(get_current_player_image(player_dir), x, y); ferencd@0: ferencd@0: // setting up the event listeners ferencd@0: window.addEventListener('keydown', keypressed, false); ferencd@0: canvas.addEventListener('mousedown', mouse_press, false); ferencd@0: window.addEventListener('mousemove', mouse_move, false); ferencd@0: window.addEventListener('mouseup', mouse_up, false); ferencd@0: ferencd@0: init_walkers(); ferencd@0: ferencd@0: setTimeout(time_passes_by, 3000); ferencd@0: ferencd@0: game_state = GAME_RUNNING; ferencd@0: ferencd@0: walkers_simulation(); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: function post(path, params, method) { ferencd@0: method = method || "post"; ferencd@0: var form = document.createElement("form"); ferencd@0: form.setAttribute("method", method); ferencd@0: form.setAttribute("action", path); ferencd@0: ferencd@0: for(var key in params) { ferencd@0: if(params.hasOwnProperty(key)) { ferencd@0: console.log(key, params[key]); ferencd@0: ferencd@0: var hiddenField = document.createElement("input"); ferencd@0: hiddenField.setAttribute("type", "hidden"); ferencd@0: hiddenField.setAttribute("name", key); ferencd@0: hiddenField.setAttribute("value", params[key]); ferencd@0: ferencd@0: form.appendChild(hiddenField); ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: document.body.appendChild(form); ferencd@0: form.submit(); ferencd@0: } ferencd@0: ferencd@0: function go_next_level() ferencd@0: { ferencd@0: var gid = document.getElementById('gid').value; ferencd@0: post(window.location.href, {gid: gid}); ferencd@0: } ferencd@0: ferencd@0: function show_menu() ferencd@0: { ferencd@0: document.getElementById("messages").style.visibility = 'visible'; ferencd@0: document.getElementById("messages").style.display = 'block'; ferencd@0: document.getElementById("sysmenu").style.visibility = 'visible'; ferencd@0: document.getElementById("sysmenu").style.display = 'block'; ferencd@0: ferencd@0: document.getElementById("goimg").src = "/img/dungeonslogo.png"; ferencd@0: } ferencd@0: ferencd@0: document.addEventListener('touchstart', handleTouchStart, false); ferencd@0: document.addEventListener('touchmove', handleTouchMove, false); ferencd@0: ferencd@0: var xDown = null; ferencd@0: var yDown = null; ferencd@0: ferencd@0: function handleTouchStart(evt) { ferencd@0: xDown = evt.touches[0].clientX; ferencd@0: yDown = evt.touches[0].clientY; ferencd@0: }; ferencd@0: ferencd@0: function handleTouchMove(evt) { ferencd@0: if ( ! xDown || ! yDown ) { ferencd@0: return; ferencd@0: } ferencd@0: ferencd@0: var xUp = evt.touches[0].clientX; ferencd@0: var yUp = evt.touches[0].clientY; ferencd@0: ferencd@0: var xDiff = xDown - xUp; ferencd@0: var yDiff = yDown - yUp; ferencd@0: ferencd@0: if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {/*most significant*/ ferencd@0: if ( xDiff > 0 ) { ferencd@0: step(MOVE_IDX_LEFT, -1, 0); ferencd@0: } else { ferencd@0: step(MOVE_IDX_RIGHT, 1, 0); ferencd@0: } ferencd@0: } else { ferencd@0: if ( yDiff > 0 ) { ferencd@0: step(MOVE_IDX_UP, 0, -1); ferencd@0: } else { ferencd@0: step(MOVE_IDX_DOWN, 0, 1); ferencd@0: } ferencd@0: } ferencd@0: /* reset values */ ferencd@0: xDown = null; ferencd@0: yDown = null; ferencd@0: };