Коллизия в Tilemap
- var canvas = document.getElementById('canvas');
- var w = canvas.width; //размеры канваса
- var h = canvas.height;
- var g = canvas.getContext('2d');
- g.font = "10px Verdana"; //дефолтный шрифт
- var keys = {}; //нажатые клавиши
- var player = {
- x:0, y:0, w: 16, h: 32,
- sx: 0, sy: 0, //скорость игрока
- onLand: false //возможность прыгать и тд
- };
- var tsize = 32; //размер тайла
- var map = [
- [0,0,0,0,0,0,0,0,0,0,0,0],
- [0,0,0,0,0,0,0,0,0,0,0,0],
- [0,0,0,0,0,0,0,0,0,1,0,0],
- [0,0,0,0,1,0,0,0,1,0,0,0],
- [0,0,1,0,0,0,0,0,0,1,1,0],
- [0,0,0,0,0,1,0,0,1,0,1,0],
- [1,1,1,1,1,1,1,1,1,1,1,1]
- ];
- //array object lifehukc
- map.w = map[0].length;
- map.h = map.length;
- //обработка клавиш
- window.onkeydown = function (e) {
- keys[e.keyCode] = true;
- }
- window.onkeyup = function (e) {
- keys[e.keyCode] = false;
- }
- function drawPlayer() {
- g.fillStyle = "#F9A520";
- g.fillRect(player.x, player.y, player.w, player.h);
- }
- function drawMap() {
- g.fillStyle = "#A0A020";
- for (var iy = 0; iy < map.h; iy++)
- for (var ix = 0; ix < map.w; ix++) {
- var id = map[iy][ix];
- if (id != 0) g.fillRect(ix*tsize, iy*tsize, tsize, tsize);
- }
- }
- function getTile(x, y) {
- var cell = 0; //или 1/undefined/null/etc
- if (x > -1 && y > -1 && x < map.w && y < map.h) {
- cell = map[y][x];
- }
- return cell;
- }
- function updatePlayer() {
- player.sy += 0.1; //гравитация
- if (player.sx != 0) {
- var sx = Math.abs(player.sx);
- var vx = sx / player.sx; //вектор направления
- while(sx > tsize) { //скорость больше размера тайла
- player.x += tsize * vx;
- sx -= tsize;
- collision(player, 0);
- if (player.sx == 0) sx = 0;
- }
- player.x += sx * vx;
- collision(player, 0); //коллизия по x
- }
- if (player.sy != 0) {
- var sy = Math.abs(player.sy);
- var vy = sy / player.sy;
- while(sy > tsize) {
- player.y += tsize * vy;
- sy -= tsize;
- collision(player, 1);
- if (player.sy == 0) sy = 0;
- }
- player.onLand = false;
- player.y += sy * vy;
- collision(player, 1); //коллизия по y
- }
- //замедление по x
- if (player.sx >= 0.1) player.sx -= 0.1;
- if (player.sx <= -0.1) player.sx += 0.1;
- if (Math.abs(player.sx) < 0.1) player.sx = 0;
- //управление
- if ((keys[37] || keys[65]) && player.sx > -3) player.sx -= 0.3;
- if ((keys[39] || keys[68]) && player.sx < 3) player.sx += 0.3;
- if ((keys[40] || keys[83])) player.sy = 999; //очень быстро вниз
- if (keys[69]) player.sx = tsize*2; //световые скачки на Q/E
- if (keys[81]) player.sx = -tsize*2;
- if ((keys[38] || keys[87]) && player.onLand) { //прыжок
- player.onLand = false;
- player.sy = -4;
- }
- if (keys[82]) { //перезапуск на клавишу R
- player.x = 0;
- player.y = 0;
- player.sx = 0;
- player.sy = 0;
- }
- }
- function collision(body, dir) {
- var x = Math.floor(body.x / tsize);
- var y = Math.floor(body.y / tsize);
- var maxX = Math.ceil((body.x + body.w) / tsize);
- var maxY = Math.ceil((body.y + body.h) / tsize);
- for (var iy = y; iy < maxY; iy++)
- for (var ix = x; ix < maxX; ix++) {
- if (getTile(ix, iy) != 1) continue;
- if (dir == 0) { //движение по x
- if (body.sx > 0) { //вправо
- body.x = ix * tsize - body.w;
- body.sx = 0;
- } else if (body.sx < 0) { //влево
- body.x = ix * tsize + tsize;
- body.sx = 0;
- }
- } else if (dir == 1) { //движение по y
- if (body.sy > 0) { //вниз
- body.onLand = true;
- body.y = iy * tsize - body.h;
- body.sy = 0;
- } else if (body.sy < 0) { //вверх
- body.y = iy * tsize + tsize;
- body.sy = 0;
- }
- }
- }
- }
- function main() {
- updatePlayer();
- g.clearRect(0, 0, w, h);
- drawMap();
- drawPlayer();
- g.fillStyle="#000"; //~~Math.floor~~
- g.fillText(""+~~player.x+","+~~player.y, 0, 10);
- g.fillText(""+~~player.sx+","+~~player.sy, 0, 20);
- }
- setInterval(main, 1000 / 60);
Управление WASD/стрелки, Q/E для сильного ускорения, R для рестарта.
Предлагайте варианты по улучшению кода основной коллизии.
Старая (убогая) версия:
https://jsfiddle.net/RblSb/xw5ybxtj/6/
Текущая:
https://jsfiddle.net/RblSb/xw5ybxtj/
Предлагайте варианты по улучшению кода основной коллизии.
Старая (убогая) версия:
https://jsfiddle.net/RblSb/xw5ybxtj/6/
Текущая:
https://jsfiddle.net/RblSb/xw5ybxtj/