├── .gitattributes ├── .gitignore ├── canvas.js ├── game.js ├── hero.js ├── img ├── exit.png ├── gun.png ├── hero.png ├── slope45degleft.png ├── slope45degright.png ├── slopeminus45degleft.png ├── slopeminus45degright.png ├── void.png ├── wall_portalable.png └── wall_unportalable.png ├── index.html ├── inputs.js ├── maps.js └── tiles.js /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /canvas.js: -------------------------------------------------------------------------------- 1 | /* Canvas */ 2 | 3 | // Canvas context 4 | ctx = canvas.getContext("2d"); 5 | 6 | // Canvas DOMRect 7 | canvas_rect = {}; 8 | 9 | // On load, and when the window is resized 10 | (onresize = function(){ 11 | 12 | // Change the canvas style depending on the screen ratio vs. 16/9 13 | if(innerWidth < innerHeight * 16 / 9){ 14 | canvas.className = "portrait"; 15 | } 16 | else { 17 | canvas.className = "landscape"; 18 | } 19 | 20 | // Save DOMRect 21 | canvas_rect = canvas.getBoundingClientRect(); 22 | })(); -------------------------------------------------------------------------------- /game.js: -------------------------------------------------------------------------------- 1 | /* Game loop */ 2 | 3 | 4 | // Constants 5 | var prev_time = +new Date(); 6 | var time = 0; 7 | var frametime = 0; 8 | var normal_frametime = 16; 9 | var frametime_coef = 0; 10 | 11 | game = function(){ 12 | 13 | // Handle framerate 14 | time = +new Date(); 15 | frametime = time - prev_time; 16 | prev_time = time; 17 | frametime_coef = frametime / normal_frametime; 18 | l3.value = frametime_coef; 19 | 20 | //zzz+=1; 21 | //rotate_hero(zzz); 22 | 23 | // Make the hero move, walk, jump, fall... 24 | move_hero(); 25 | 26 | // Draw the scene 27 | canvas.width = canvas.width; 28 | 29 | ctx.fillStyle = "#abc"; 30 | ctx.fillRect(0,0,40,600); 31 | 32 | ctx.fillStyle = "#aca"; 33 | ctx.fillRect(760,0,800,600); 34 | 35 | ctx.fillStyle = "black"; 36 | for(i in maps[0]){ 37 | for(j in maps[0][i]){ 38 | if(maps[0][i][j] != "0"){ 39 | ctx.drawImage(tiles[maps[0][i][j]].sprite, j * tile_w, i * tile_h, tile_w, tile_h); 40 | } 41 | } 42 | } 43 | 44 | // Draw the hero 45 | ctx.save(); 46 | ctx.translate(hero.x, hero.y); 47 | ctx.rotate(hero.angle); 48 | ctx.drawImage(hero_sprite, -16, -16, tile_w, tile_h); 49 | ctx.restore(); 50 | 51 | // Debug 52 | /*for(var i in vectors){ 53 | ctx.fillStyle = "red"; 54 | ctx.fillRect(hero.x + hero[i][0]-1, hero.y + hero[i][1]-1,2,2); 55 | }*/ 56 | 57 | /*for(var j = 0; j < hero_w; j++){ 58 | ctx.fillStyle = "green"; 59 | ctx.fillRect(hero.x + hero.L4[0] + j * hero.right[0], hero.y + hero.L4[1] + j * hero.right[1],2,2); 60 | }*/ 61 | 62 | if(hero.x > tile_w * 24){ 63 | rotate_hero(45); 64 | } 65 | 66 | if(hero.x < tile_w * 1){ 67 | rotate_hero(-45); 68 | } 69 | 70 | // Next frame 71 | requestAnimationFrame(game); 72 | }; 73 | 74 | onload = function(){ 75 | zzz = 0;//Math.floor(Math.random()*8) * 45; 76 | rotate_hero(zzz); 77 | game(); 78 | } -------------------------------------------------------------------------------- /hero.js: -------------------------------------------------------------------------------- 1 | /* Hero */ 2 | 3 | /* 4 | * The hero is drawn as a 32 x 32 sprite, its hitbox is 22 x 28. 5 | * Its center point is at the center of its hitbox (x = 11; y = 14) 6 | * A few other points are placed around the hitbox to simplify the collision tests: 7 | * L1, C1, R1 (x = 0 / 11 / 21; y = 0) 8 | * L2, C2, R2 (x = 0 / 11 / 21; y = 14) 9 | * L3, R3 (x = 0 / 21; y = 20) 10 | * L4, L5, C3, R5, R4 (x = 0 / 4 / 11 / 16 / 21; y = 24) 11 | * 12 | * C1 13 | * L1 *-----------*-----------* R1 14 | * | | 15 | * | | 16 | * | | 17 | * | | 18 | * | | 19 | * | | 20 | * | | 21 | * | | 22 | * | | 23 | * | | 24 | * | | 25 | * | C2 | 26 | * L2 * * * R2 27 | * | (hero.x; hero.y) | 28 | * | | 29 | * | | 30 | * | | 31 | * | | 32 | * | | 33 | * | | 34 | * | | 35 | * L3 * * R3 36 | * | | 37 | * | | 38 | * | | 39 | * | | 40 | * L4 *---*-------*-------*---* R4 41 | * L5 C3 R5 42 | * 43 | */ 44 | 45 | // Constants 46 | var hero_w = 22; 47 | var hero_h = 28; 48 | 49 | // Base vectors (Right and Bottom vectors of length 1) 50 | // These two vectors get rotated according to the hero's angle 51 | // then all the other vectors are deduced from them 52 | var uright = [1,0]; 53 | var ubottom = [0,1]; 54 | 55 | // Working vectors 56 | // These vectors are not used as-is but rotated according to the hero's angle and stored in the hero's properties 57 | var uL1 = [-11, -14]; 58 | var uC1 = [0, -14]; 59 | var uR1 = [11, -14]; 60 | var uL2 = [-11, 0]; 61 | var uR2 = [11, 0]; 62 | var uL3 = [-11, 8]; 63 | var uC3 = [0, 14]; 64 | var uR3 = [11, 8]; 65 | var uL4 = [-11, 14]; 66 | var uR4 = [11, 14]; 67 | var uL5 = [-7, 14]; 68 | var uR5 = [7, 14]; 69 | 70 | 71 | // The names of the base vectors to rotate using maths, and their const equivalent 72 | base_vectors = { 73 | "right": uright, 74 | "bottom": ubottom 75 | } 76 | 77 | // The names of the immportant vectors to rotate using the base vectors, and their const equivalent 78 | vectors = { 79 | "L1": uL1, 80 | "C1": uC1, 81 | "R1": uR1, 82 | "L2": uL2, 83 | "R2": uR2, 84 | "L3": uL3, 85 | "C3": uC3, 86 | "R3": uR3, 87 | "L4": uL4, 88 | "R4": uR4, 89 | "L5": uL5, 90 | "R5": uR5, 91 | }; 92 | 93 | 94 | // Properties 95 | var hero = { 96 | x: 200, // x position of C2 97 | y: 199, // y position of C2 98 | 99 | angle: 0, // angle in radians (0: head on top) 100 | 101 | // Vectors (rotated with the hero) 102 | right: [], // Normalized vector to the "right" (relative to the hero) 103 | bottom: [], // and "bottom" 104 | 105 | L1: [], // Position of L1 from center (C2) 106 | C1: [], // etc 107 | R1: [], 108 | L2: [], 109 | R2: [], 110 | L3: [], 111 | C3: [], 112 | R3: [], 113 | L4: [], 114 | R4: [], 115 | L5: [], 116 | R5: [], 117 | 118 | // Speeds and accelerations: 119 | // Constant 120 | max_walk_speed: 3, 121 | walk_acceleration: 0.3, 122 | walk_idle_deceleration: -1, 123 | jump_speed: -14, 124 | gravity: 1, 125 | 126 | // Variable 127 | walk_speed: 0, 128 | fall_speed: 0, 129 | max_fall_speed: 6, 130 | 131 | // State 132 | freefall: true // freefall 133 | }; 134 | 135 | // Functions 136 | var rotate_hero = function(angle_deg){ 137 | 138 | // Convert in radians 139 | hero.angle = angle_deg * Math.PI / 180; 140 | 141 | // Rotate base vectors 142 | for(var i in base_vectors){ 143 | hero[i] = [ 144 | base_vectors[i][0] * Math.cos(hero.angle) - base_vectors[i][1] * Math.sin(hero.angle), 145 | base_vectors[i][0] * Math.sin(hero.angle) + base_vectors[i][1] * Math.cos(hero.angle) 146 | ]; 147 | } 148 | 149 | // Rotate real vectors 150 | for(var i in vectors){ 151 | hero[i] = [ 152 | vectors[i][0] * hero.right[0] + vectors[i][1] * hero.bottom[0], 153 | vectors[i][0] * hero.right[1] + vectors[i][1] * hero.bottom[1] 154 | ]; 155 | } 156 | } 157 | 158 | // Hero moves (left / right / jump / fall) 159 | var move_hero = function(){ 160 | 161 | // Walk left: 162 | if(keys.left && !keys.right){ 163 | 164 | // Apply a negative walk acceleration to the hero's speed 165 | hero.walk_speed -= hero.walk_acceleration; 166 | 167 | // Limit the hero's speed 168 | if(hero.walk_speed < -hero.max_walk_speed){ 169 | hero.walk_speed = -hero.max_walk_speed; 170 | } 171 | } 172 | 173 | // Walk right: 174 | else if(keys.right && !keys.left){ 175 | 176 | // Apply a negative walk acceleration to the hero's speed 177 | hero.walk_speed += hero.walk_acceleration; 178 | 179 | // Limit the hero's speed 180 | if(hero.walk_speed > hero.max_walk_speed){ 181 | hero.walk_speed = hero.max_walk_speed; 182 | } 183 | } 184 | 185 | // Idle: 186 | 187 | else{ 188 | 189 | if(Math.abs(hero.walk_speed) < 1){ 190 | hero.walk_speed = 0; 191 | } 192 | 193 | else{ 194 | 195 | // If the hero stops walking, decelerate 196 | if(hero.walk_speed > 0){ 197 | hero.walk_speed += hero.walk_idle_deceleration; 198 | } 199 | else if(hero.walk_speed < 0){ 200 | hero.walk_speed -= hero.walk_idle_deceleration; 201 | } 202 | } 203 | } 204 | 205 | // Move horizontally 206 | for(var i = 0; i < Math.abs(hero.walk_speed) * frametime_coef; i++){ 207 | hero.x += hero.right[0] * Math.sign(hero.walk_speed); 208 | hero.y += hero.right[1] * Math.sign(hero.walk_speed); 209 | 210 | // Detect collision on the right (R1,R2,R3) 211 | if(hero.walk_speed > 0){ 212 | 213 | // Climb a slope on the right (one solid between R4 and R3, but R1 + 3 "up", C1, L1, R2 and R3 not solid) 214 | if( 215 | !is_solid(hero.x + hero.R1[0] + -3 * hero.bottom[0], hero.y + hero.R1[1] + -3 * hero.bottom[1]) 216 | && 217 | !is_solid(hero.x + hero.C1[0], hero.y + hero.C1[1]) 218 | && 219 | !is_solid(hero.x + hero.L1[0], hero.y + hero.L1[1]) 220 | && 221 | !is_solid(hero.x + hero.R2[0], hero.y + hero.R2[1]) 222 | && 223 | !is_solid(hero.x + hero.R3[0], hero.y + hero.R3[1]) 224 | ){ 225 | for(var j = 0; j < 4; j++){ 226 | if(is_solid(hero.x + hero.R4[0] + -j * hero.bottom[0], hero.y + hero.R4[1] + -j * hero.bottom[1])){ 227 | hero.x += -hero.bottom[0] * 4; 228 | hero.y += -hero.bottom[1] * 4; 229 | break; 230 | } 231 | } 232 | } 233 | 234 | // Slide if the slope is too strong on the right 235 | // TODO 236 | 237 | // Collision 238 | if(is_solid(hero.x + hero.R1[0], hero.y + hero.R1[1]) 239 | || 240 | is_solid(hero.x + hero.R2[0], hero.y + hero.R2[1]) 241 | || 242 | is_solid(hero.x + hero.R3[0], hero.y + hero.R3[1]) 243 | ){ 244 | hero.walk_speed = 0; 245 | hero.x -= hero.right[0]; 246 | hero.y -= hero.right[1]; 247 | break; 248 | } 249 | } 250 | 251 | // Detect collision on the left (L1,L2,L3) 252 | else if(hero.walk_speed < 0){ 253 | 254 | // Climb a slope on the left (one solid between L4 and L3, but L1 + 3 "up", C1, R1, L2 and L3 not solid) 255 | if( 256 | !is_solid(hero.x + hero.L1[0] + -3 * hero.bottom[0], hero.y + hero.L1[1] + -3 * hero.bottom[1]) 257 | && 258 | !is_solid(hero.x + hero.C1[0], hero.y + hero.C1[1]) 259 | && 260 | !is_solid(hero.x + hero.R1[0], hero.y + hero.R1[1]) 261 | && 262 | !is_solid(hero.x + hero.L2[0], hero.y + hero.L2[1]) 263 | && 264 | !is_solid(hero.x + hero.L3[0], hero.y + hero.L3[1]) 265 | ){ 266 | for(var j = 0; j < 4; j++){ 267 | if(is_solid(hero.x + hero.L4[0] + -j * hero.bottom[0], hero.y + hero.L4[1] + -j * hero.bottom[1])){ 268 | hero.x += -hero.bottom[0] * 4; 269 | hero.y += -hero.bottom[1] * 4; 270 | break; 271 | } 272 | } 273 | } 274 | 275 | // Slide if the slope is too strong on the left 276 | // TODO 277 | 278 | // Collision 279 | if( 280 | is_solid(hero.x + hero.L1[0], hero.y + hero.L1[1]) 281 | || 282 | is_solid(hero.x + hero.L2[0], hero.y + hero.L2[1]) 283 | || 284 | is_solid(hero.x + hero.L3[0], hero.y + hero.L3[1]) 285 | ){ 286 | hero.walk_speed = 0; 287 | hero.x -= -hero.right[0]; 288 | hero.y -= -hero.right[1]; 289 | break; 290 | } 291 | } 292 | } 293 | 294 | 295 | // Jump: 296 | if(keys.up && !hero.freefall){ 297 | hero.freefall = true; 298 | hero.fall_speed += hero.jump_speed; 299 | } 300 | 301 | // Freefall: 302 | hero.fall_speed += hero.gravity; 303 | 304 | if(hero.fall_speed > hero.max_fall_speed){ 305 | hero.fall_speed = hero.max_fall_speed; 306 | } 307 | 308 | l1.value = hero.fall_speed; 309 | 310 | // Move vertically 311 | mv: for(var i = 0; i < Math.abs(hero.fall_speed) * frametime_coef; i++){ 312 | hero.x += hero.bottom[0] * Math.sign(hero.fall_speed); 313 | hero.y += hero.bottom[1] * Math.sign(hero.fall_speed); 314 | 315 | // Detect collision on the bottom (L4,C3,R4) 316 | if(hero.fall_speed > 0){ 317 | for(var j = 0; j < hero_w; j++){ 318 | if(is_solid(hero.x + hero.L4[0] + j * hero.right[0], hero.y + hero.L4[1] + j * hero.right[1])){ 319 | hero.fall_speed = 0; 320 | hero.x -= hero.bottom[0]; 321 | hero.y -= hero.bottom[1]; 322 | hero.freefall = false; 323 | break mv; 324 | } 325 | } 326 | } 327 | 328 | // Detect collision on the top (L1,C1,R1) 329 | else if( 330 | (hero.fall_speed < 0 && 331 | ( 332 | is_solid(hero.x + hero.L1[0], hero.y + hero.L1[1]) 333 | || 334 | is_solid(hero.x + hero.C1[0], hero.y + hero.C1[1]) 335 | || 336 | is_solid(hero.x + hero.R1[0], hero.y + hero.R1[1]) 337 | ) 338 | ) 339 | ){ 340 | hero.fall_speed = 0; 341 | hero.x -= -hero.bottom[0]; 342 | hero.y -= -hero.bottom[1]; 343 | break; 344 | } 345 | } 346 | } -------------------------------------------------------------------------------- /img/exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xem/platform-engine/b270167ae3812f6b7d73049e21a9ffa20387aed3/img/exit.png -------------------------------------------------------------------------------- /img/gun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xem/platform-engine/b270167ae3812f6b7d73049e21a9ffa20387aed3/img/gun.png -------------------------------------------------------------------------------- /img/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xem/platform-engine/b270167ae3812f6b7d73049e21a9ffa20387aed3/img/hero.png -------------------------------------------------------------------------------- /img/slope45degleft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xem/platform-engine/b270167ae3812f6b7d73049e21a9ffa20387aed3/img/slope45degleft.png -------------------------------------------------------------------------------- /img/slope45degright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xem/platform-engine/b270167ae3812f6b7d73049e21a9ffa20387aed3/img/slope45degright.png -------------------------------------------------------------------------------- /img/slopeminus45degleft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xem/platform-engine/b270167ae3812f6b7d73049e21a9ffa20387aed3/img/slopeminus45degleft.png -------------------------------------------------------------------------------- /img/slopeminus45degright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xem/platform-engine/b270167ae3812f6b7d73049e21a9ffa20387aed3/img/slopeminus45degright.png -------------------------------------------------------------------------------- /img/void.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xem/platform-engine/b270167ae3812f6b7d73049e21a9ffa20387aed3/img/void.png -------------------------------------------------------------------------------- /img/wall_portalable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xem/platform-engine/b270167ae3812f6b7d73049e21a9ffa20387aed3/img/wall_portalable.png -------------------------------------------------------------------------------- /img/wall_unportalable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xem/platform-engine/b270167ae3812f6b7d73049e21a9ffa20387aed3/img/wall_unportalable.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | platform engine 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /inputs.js: -------------------------------------------------------------------------------- 1 | /* Inputs */ 2 | 3 | // Keys pressed 4 | keys = { 5 | left: false, 6 | up: false, 7 | top: false 8 | }; 9 | 10 | 11 | // Key down / keypress (left, top, right) 12 | onkeydown = onkeypress = function(e){ 13 | switch(e.keyCode){ 14 | case 37: 15 | keys.left = true; 16 | break; 17 | case 38: 18 | keys.up = true; 19 | break; 20 | case 39: 21 | keys.right = true; 22 | break; 23 | } 24 | }; 25 | 26 | // Key up (left, top, right) 27 | onkeyup = function(e){ 28 | switch(e.keyCode){ 29 | case 37: 30 | keys.left = false; 31 | break; 32 | case 38: 33 | keys.up = false; 34 | break; 35 | case 39: 36 | keys.right = false; 37 | break; 38 | } 39 | }; -------------------------------------------------------------------------------- /maps.js: -------------------------------------------------------------------------------- 1 | /* Maps */ 2 | 3 | maps = []; 4 | 5 | maps[0] = [ 6 | "0000000000000000000000000", 7 | "0000000000000000000000000", 8 | "0000000000000000000000000", 9 | "0000000000000000000000000", 10 | "0000000000000000000000000", 11 | "0000000000000000000000000", 12 | "0000000000000000000000000", 13 | "0000000500000000000000000", 14 | "0000000011000040000000000", 15 | "0000000010000020000003000", 16 | "0000000010023500001054012", 17 | "0003000000200340020300021", 18 | "2305203202100030240530211", 19 | "1111121111111111111111111", 20 | ]; 21 | 22 | current_map = 0; -------------------------------------------------------------------------------- /tiles.js: -------------------------------------------------------------------------------- 1 | /* Tiles */ 2 | 3 | // Size 4 | tile_w = 32; 5 | tile_h = 32; 6 | 7 | 8 | // Sprites / tileset 9 | // Solid => 0: non-solid, 1: solid, 2: other (slope) 10 | // Solidity(x,y) => tells if a pixel is solid in a given tile 11 | 12 | tiles = { 13 | 14 | // 0: void 15 | "0": { 16 | sprite: void_sprite, 17 | solid: 0 18 | }, 19 | 20 | // 1: wall "unportalable" 21 | "1": { 22 | sprite: wall_unportalable_sprite, 23 | solid: 1 24 | }, 25 | 26 | // 2: slope 45deg right 27 | "2": { 28 | sprite: slope_45deg_right, 29 | solid: 2, 30 | solidity: function(x,y){ 31 | return y > tile_w - x; 32 | } 33 | }, 34 | 35 | // 3: slope 45deg left 36 | "3": { 37 | sprite: slope_45deg_left, 38 | solid: 2, 39 | solidity: function(x,y){ 40 | return y > x; 41 | } 42 | }, 43 | 44 | // 4: slope 45deg right 45 | "4": { 46 | sprite: slope_minus_45deg_right, 47 | solid: 2, 48 | solidity: function(x,y){ 49 | return y < x; 50 | } 51 | }, 52 | 53 | // 5: slope 45deg right 54 | "5": { 55 | sprite: slope_minus_45deg_left, 56 | solid: 2, 57 | solidity: function(x,y){ 58 | return y < tile_w - x; 59 | } 60 | } 61 | }; 62 | 63 | 64 | // Check if a coordinate (x:y) is on a solid pixel or not 65 | is_solid = function(x,y){ 66 | 67 | var tile_y = Math.floor(y / tile_h); 68 | 69 | // Return false if the pixel is at undefined map coordinates 70 | if(!maps[current_map][tile_y]){ 71 | return false; 72 | } 73 | 74 | var tile_x = Math.floor(x / tile_w); 75 | 76 | if(!maps[current_map][tile_y][tile_x]){ 77 | return false; 78 | } 79 | 80 | // Return false if the tile is not solid 81 | if(tiles[maps[current_map][tile_y][tile_x]].solid === 0){ 82 | return false; 83 | } 84 | 85 | // Return true if the tile is solid 86 | if(tiles[maps[current_map][tile_y][tile_x]].solid === 1){ 87 | return true; 88 | } 89 | 90 | // Finally, return the solidity of the current pixel if the tile is semi-solid 91 | var pixel_x = x - tile_x * tile_w; 92 | var pixel_y = y - tile_y * tile_h; 93 | return tiles[maps[current_map][tile_y][tile_x]].solidity(pixel_x, pixel_y); 94 | } --------------------------------------------------------------------------------