Добавление столкновения к прямоугольникам, чтобы спрайт не проходил? - PullRequest
0 голосов
/ 11 апреля 2019

Я пытаюсь сделать коллекционную игру. Это все еще в стадии разработки. Я пытаюсь добавить обнаружение столкновений к прямоугольнику на холсте, чтобы спрайт не мог проходить через него. Я знаю, как добавить столкновение, чтобы мой спрайт не покинул холст. Мои прямоугольники находятся в разных точках холста, и они различаются по размеру. Мне интересно, как мне это сделать?

Кроме того, совершенно необязательно, как мне иметь его, чтобы игрок собирал все предметы коллекционирования перед тем, как поговорить с собакой. вроде как квест.

Я новичок в этом, поэтому извиняюсь, если то, что я описал, не имело никакого смысла.

Спасибо!

Вот живой сайт: https://yewtreedesign.github.io/441_HW/HW11/index.html

Я пытался использовать ctx.rect в качестве значения в «если»

function moveCharacter(deltaX, deltaY, direction) {
  if (positionX + deltaX > 0 && positionX  + SCALED_WIDTH + deltaX < canvas.width) {
    positionX += deltaX;
  }
  if (positionY + deltaY > 0 && positionY + SCALED_HEIGHT + deltaY < canvas.height) {
    positionY += deltaY;
  }

но спрайт застревает на месте.

<script>
const SCALE = 1;
const WIDTH = 18;
const HEIGHT = 31;
const SCALED_WIDTH = SCALE * WIDTH;
const SCALED_HEIGHT = SCALE * HEIGHT;
const CYCLE_LOOP = [0, 1, 0, 2];
const FACING_DOWN = 0;
const FACING_UP = 1;
const FACING_LEFT = 2;
const FACING_RIGHT = 3;
const FRAME_LIMIT = 12;
const MOVEMENT_SPEED = 1;

let canvas = document.querySelector('canvas');
let ctx = canvas.getContext('2d');
let keyPresses = {};
let currentDirection = FACING_DOWN;
let currentLoopIndex = 0;
let frameCount = 0;
let positionX = 0;
let positionY = 0;
let img = new Image();
let shiba = new Image();
let rays = new Image();
let doritos = new Image();
let walls= new Image();



window.addEventListener('keydown', keyDownListener);
function keyDownListener(event) {
    keyPresses[event.key] = true;
}

window.addEventListener('keyup', keyUpListener);
function keyUpListener(event) {
    keyPresses[event.key] = false;
}

function loadImage() {
  walls.src='image/walls.png'
  img.src = 'atlus/mainsprite.png';
  shiba.src = 'image/shiba.gif';
  rays.src='image/shades.png';
  doritos.src='image/dorit.png';
  img.onload = function() {
    window.requestAnimationFrame(gameLoop);

  };

}

function drawFrame(frameX, frameY, canvasX, canvasY) {
  ctx.beginPath();
  ctx.drawImage(shiba, 225,20);
  ctx.closePath();

  ctx.beginPath();
  ctx.drawImage(rays, 400,20);
  ctx.drawImage(doritos, 420,250);
  ctx.drawImage(img,
                frameX * WIDTH, frameY * HEIGHT, WIDTH, HEIGHT,
                canvasX, canvasY, SCALED_WIDTH, SCALED_HEIGHT);
  ctx.drawImage(walls,0,0);
  ctx.closePath();
}
function drawWalls(){
  ctx.beginPath();
  ctx.rect(105.3, -1, 14.1, 73.5);
  ctx.stroke();
  ctx.closePath();
  ctx.beginPath();
  ctx.rect(366.5, -1, 14.1, 73.5);
  ctx.stroke();
  ctx.closePath();
  ctx.beginPath();
  ctx.rect(367, 173.2, 120, 14.1);
  ctx.stroke();
  ctx.closePath();
  ctx.beginPath();
  ctx.rect(-1, 173.2, 120, 14.1);
  ctx.stroke();
  ctx.closePath();
  ctx.beginPath();
  ctx.rect(105.3, 267.5, 14.1, 73.5);
  ctx.stroke();
  ctx.closePath();
  ctx.beginPath();
  ctx.rect(366.5, 267.5, 14.1, 73.5);
  ctx.stroke();
  ctx.closePath();

}


loadImage();

function gameLoop() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  let hasMoved = false;

  if (keyPresses.ArrowUp) {
    moveCharacter(0, -MOVEMENT_SPEED, FACING_UP);
    hasMoved = true;
  } else if (keyPresses.ArrowDown) {
    moveCharacter(0, MOVEMENT_SPEED, FACING_DOWN);
    hasMoved = true;
  }

  if (keyPresses.ArrowLeft) {
    moveCharacter(-MOVEMENT_SPEED, 0, FACING_LEFT);
    hasMoved = true;
  } else if (keyPresses.ArrowRight) {
    moveCharacter(MOVEMENT_SPEED, 0, FACING_RIGHT);
    hasMoved = true;
  }

  if (hasMoved) {
    frameCount++;
    if (frameCount >= FRAME_LIMIT) {
      frameCount = 0;
      currentLoopIndex++;
      if (currentLoopIndex >= CYCLE_LOOP.length) {
        currentLoopIndex = 0;
      }
    }
  }

  if (!hasMoved) {
    currentLoopIndex = 0;
  }

  drawFrame(CYCLE_LOOP[currentLoopIndex], currentDirection, positionX, positionY);
  window.requestAnimationFrame(gameLoop);
}

function moveCharacter(deltaX, deltaY, direction) {
  if (positionX + deltaX > 0 && positionX  + SCALED_WIDTH + deltaX < canvas.width) {
    positionX += deltaX;
  }
  if (positionY + deltaY > 0 && positionY + SCALED_HEIGHT + deltaY < canvas.height) {
    positionY += deltaY;
  }
  currentDirection = direction;
}

</script>

Прямо сейчас код показывает вещи, как и должно быть, просто нет обнаружения столкновений между объектами, кроме границ холста со спрайтом.

UPDATE: Благодаря ellertsmari, я могу получить обнаружение столкновений для регистрации и чтения на моей консоли. Есть обнаружение столкновений. Я пытаюсь получить его, чтобы мой персонаж остановился на обнаружении, чтобы спрайт не прошел по нему. Я сейчас работаю над этим. Если кто-нибудь знает, как заставить это работать, это будет здорово. Если я смогу найти его самостоятельно, я обновлю здесь код, чтобы другие могли посмотреть:].

Обновленный код: (ссылка также обновляется)

const SCALE = 1;
const WIDTH = 18;
const HEIGHT = 31;
const SCALED_WIDTH = SCALE * WIDTH;
const SCALED_HEIGHT = SCALE * HEIGHT;
const CYCLE_LOOP = [0, 1, 0, 2];
const FACING_DOWN = 0;
const FACING_UP = 1;
const FACING_LEFT = 2;
const FACING_RIGHT = 3;
const FRAME_LIMIT = 12;
const MOVEMENT_SPEED = 1;
let canvas = document.querySelector('canvas');
let ctx = canvas.getContext('2d');
let keyPresses = {};
let currentDirection = FACING_DOWN;
let currentLoopIndex = 0;
let frameCount = 0;
let positionX = 0;
let positionY = 0;
let img = new Image();
let shiba = new Image();
let rays = new Image();
let doritos = new Image();
let walls=     [{"id": "wall1", "x": 105.3, "y": -1,    "width": 14.1, "height": 73.5},
                {"id": "wall2", "x": 366.5, "y": -1,    "width": 14.1, "height": 73.5},
                {"id": "wall3", "x": 367,   "y": 173.2, "width": 120,  "height": 14.1},
                {"id": "wall4", "x": -1,    "y": 173.2, "width": 120,  "height": 14.1},
                {"id": "wall5", "x": 105.3, "y": 267.5, "width": 14.1, "height": 73.5},
                {"id": "wall6", "x": 366.5, "y": 267.5, "width": 14.1, "height": 73.5}
              ];
              function drawWalls(){
                for(var i=0; i< walls.length; i++){
                  ctx.fillStyle="white";
                  ctx.fillRect(walls[i].x, walls[i].y, walls[i].width,walls[i].height);
                }
            }
            function collidingWith(walls){
              console.log("you are colliding with:", walls.id);

}
window.addEventListener('keydown', keyDownListener);
function keyDownListener(event) {
    keyPresses[event.key] = true;
}
window.addEventListener('keyup', keyUpListener);
function keyUpListener(event) {
    keyPresses[event.key] = false;
}
function loadImage() {
    img.src = 'atlus/mainsprite.png';
  shiba.src = 'image/shiba.gif';
  rays.src='image/shades.png';
  doritos.src='image/dorit.png';
  img.onload = function() {
    window.requestAnimationFrame(gameLoop);
  };
}
function drawFrame(frameX, frameY, canvasX, canvasY) {
  ctx.beginPath();
  ctx.drawImage(shiba, 225,20);
  ctx.closePath();
  ctx.beginPath();
  ctx.drawImage(rays, 400,20);
  ctx.drawImage(doritos, 420,250);
  ctx.drawImage(img,
                frameX * WIDTH, frameY * HEIGHT, WIDTH, HEIGHT,
                canvasX, canvasY, SCALED_WIDTH, SCALED_HEIGHT);
  ctx.closePath();
}

loadImage();
function gameLoop() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  drawWalls();

  let hasMoved = false;
  if (keyPresses.ArrowUp) {
    moveCharacter(0, -MOVEMENT_SPEED, FACING_UP);
    hasMoved = true;
  } else if (keyPresses.ArrowDown) {
    moveCharacter(0, MOVEMENT_SPEED, FACING_DOWN);
    hasMoved = true;
  }
  if (keyPresses.ArrowLeft) {
    moveCharacter(-MOVEMENT_SPEED, 0, FACING_LEFT);
    hasMoved = true;
  } else if (keyPresses.ArrowRight) {
    moveCharacter(MOVEMENT_SPEED, 0, FACING_RIGHT);
    hasMoved = true;
  }
  if (hasMoved) {
    frameCount++;
    if (frameCount >= FRAME_LIMIT) {
      frameCount = 0;
      currentLoopIndex++;
      if (currentLoopIndex >= CYCLE_LOOP.length) {
        currentLoopIndex = 0;
      }
    }
  }
  if (!hasMoved) {
    currentLoopIndex = 0;
  }
  drawFrame(CYCLE_LOOP[currentLoopIndex], currentDirection, positionX, positionY);
  window.requestAnimationFrame(gameLoop);
}
function moveCharacter(deltaX, deltaY, direction) {
  walls.forEach(walls=>{
  if( positionX + deltaX + SCALED_WIDTH > walls.x && positionX + deltaX < walls.x + walls.width
    && positionY + deltaY + SCALED_HEIGHT > walls.y && positionY + deltaY < walls.y + walls.height
  ){
    collidingWith(walls);
  }
})

if (positionX + deltaX > 0 && positionX + SCALED_WIDTH + deltaX < canvas.width) {positionX += deltaX;}
if (positionY + deltaY > 0 && positionY + SCALED_HEIGHT + deltaY < canvas.height) {positionY += deltaY;}
  currentDirection = direction;
}

1 Ответ

0 голосов
/ 11 апреля 2019

Единственное, чего вам не хватает, это сохранить где-нибудь координаты ваших прямоугольников.Хорошим местом для этого был бы массив.Я вижу, что вы создали функцию для рисования всех прямоугольников под изображением, но, как вы можете прочитать здесь , этот холст не будет помнить, где находятся прямоугольники.

Итак, что вы можете сделать, эточтобы создать новый массив (давайте назовем его wallArr), и внутри вашей функции drawWalls вы можете просто переместить ваши координаты в этот массив, чтобы после того, как все ваши функции drawWalls будут выглядеть примерно так:

function drawWalls(){
  wallsArr.push({ name: "wall1", x: 105.3, y: -1,    width: 14.1, height: 73.5});
  wallsArr.push({ name: "wall2", x: 366.5, y: -1,    width: 14.1, height: 73.5});
  wallsArr.push({ name: "wall3", x: 367,   y: 173.2, width: 120,  height: 14.1});
  wallsArr.push({ name: "wall4", x: -1,    y: 173.2, width: 120,  height: 14.1});
  wallsArr.push({ name: "wall5", x: 105.3, y: 267.5, width: 14.1, height: 73.5})
  wallsArr.push({ name: "wall6", x: 366.5, y: 267.5, width: 14.1, height: 73.5});
}

вы можете захотетьпереименуйте функцию во что-то другое, так как она на самом деле ничего не рисует, и не забудьте вызвать функцию один раз так: drawWalls()

Чтобы симулировать коллизию, вы можете захотеть сделать коллизию как эта:

function collidingWith(object){
  console.log("you are colliding with:", object.name);
}

А затем, чтобы обнаружить столкновение, вам нужно будет проходить через стены (или весь объект, с которым вы хотите столкнуться) при каждом движении.Например, внутри функции moveCharacter вы можете выполнить:

wallsArr.forEach(wall=>{
  if( positionX + deltaX + SCALED_WIDTH > wall.x
    && positionX + deltaX < wall.x+wall.width
    && positionY + deltaY + SCALED_HEIGHT > wall.y
    && positionY + deltaY < wall.y+wall.height
  ){
    collidingWith(wall);
  }
})

Тогда вы сможете в любой момент увидеть, с какой стеной сталкивается ваш персонаж.Конечно, вы можете сделать это гораздо более общим, если вы хотите иметь возможность сталкиваться с другими объектами, но, надеюсь, вы поймете эту идею и сможете продолжить отсюда.

Удачи с остальными!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...