게임 장애물

按下按钮可移动红色方块:






添加一些障碍

现在我们想为游戏添加一些障碍。

将新组件添加到游戏区域。将其设为绿色,宽 10 像素,高 200 像素,然后将其放置在右侧 300 像素、向下 120 像素的位置。

还需要更新每一帧中的障碍物组件:

인스턴스

var myGamePiece;
var myObstacle;
function startGame() {
  myGamePiece = new component(30, 30, "red", 10, 120);
  myObstacle = new component(10, 200, "green", 300, 120);
  myGameArea.start();
}
function updateGameArea() {
  myGameArea.clear();
  myObstacle.update();
  myGamePiece.newPos();
  myGamePiece.update();
}

직접 테스트해 보세요

충돌 = 게임 종료

위의 예제에서 장애물에 닿으면 어떤 일도 일어나지 않습니다. 게임에서 이는 만족스럽지 않습니다.

우리의 빨간 장애물이 어떻게 충돌했는지 알 수 있을까요?

컴포넌트 생성자 내에서 새 메서드를 생성하여 이 컴포넌트가 다른 컴포넌트와 충돌하는지 확인합니다. 프레임 업데이트마다 이 메서드를 호출해야하며, 초당 50 번 호출되어야 합니다.

또한 myGameArea 객체 추가 stop() 메서드가 20 밀리초 간격으로 호출됩니다.

인스턴스

var myGameArea = {
  canvas : document.createElement("canvas"),
  start : function() {
    this.canvas.width = 480;
    this.canvas.height = 270;
    this.context = this.canvas.getContext("2d");
    document.body.insertBefore(this.canvas, document.body.childNodes[0]);
    this.interval = setInterval(updateGameArea, 20);
  },
  clear : function() {
    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
  },
  stop : function() {
    clearInterval(this.interval);
  }
}
function component(width, height, color, x, y) {
  this.width = width;
  this.height = height;
  this.speedX = 0;
  this.speedY = 0;
  this.x = x;
  this.y = y;
  this.update = function() {
    ctx = myGameArea.context;
    ctx.fillStyle = color;
    ctx.fillRect(this.x, this.y, this.width, this.height);
  }
  this.newPos = function() {
    this.x += this.speedX;
    this.y += this.speedY;
  }
  this.crashWith = function(otherobj) {
    var myleft = this.x;
    var myright = this.x + (this.width);
    var mytop = this.y;
    var mybottom = this.y + (this.height);
    var otherleft = otherobj.x;
    var otherright = otherobj.x + (otherobj.width);
    var othertop = otherobj.y;
    var otherbottom = otherobj.y + (otherobj.height);
    var crash = true;
    if ((mybottom < othertop) ||
    (mytop > otherbottom) ||
    (myright < otherleft) ||
    (myleft > otherright)) {
      crash = false;
    }
    return crash;
  }
}
function updateGameArea() {
  if (myGamePiece.crashWith(myObstacle)) {
    myGameArea.stop();
  } else {
    myGameArea.clear();
    myObstacle.update();
    myGamePiece.newPos();
    myGamePiece.update();
  }
}

직접 테스트해 보세요

장애물 움직임

장애물이 고정되어 있을 때는 위험하지 않으므로, 그것이 움직이기를 원합니다.

매번 업데이트할 때 변경 myObstacle.x 의 속성 값:

인스턴스

function updateGameArea() {
  if (myGamePiece.crashWith(myObstacle)) {
    myGameArea.stop();
  } else {
    myGameArea.clear();
    myObstacle.x += -1;
    myObstacle.update();
    myGamePiece.newPos();
    myGamePiece.update();
  }
}

직접 테스트해 보세요

다중 장애물

여러 개의 장애물을 추가해 볼게요?

따라서, 프레임 수를 계산하기 위한 속성과 주어진 프레임 속도로 특정 작업을 수행하는 메서드가 필요합니다.

인스턴스

var myGameArea = {
  canvas : document.createElement("canvas"),
  start : function() {
    this.canvas.width = 480;
    this.canvas.height = 270;
    this.context = this.canvas.getContext("2d");
    document.body.insertBefore(this.canvas, document.body.childNodes[0]);
    this.frameNo = 0;
    this.interval = setInterval(updateGameArea, 20);
  },
  clear : function() {
    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
  },
  stop : function() {
    clearInterval(this.interval);
  }
}
function everyinterval(n) {
  if ((myGameArea.frameNo / n) % 1 == 0) {return true;}
  return false;
}

현재 프레임 번호가 주어진 간격과 일치하면, everyinterval 함수는 true를 반환합니다.

여러 개의 장애물을 정의하려면, 장애물 변수를 배열로 선언하세요.

다음으로, updateGameArea 함수에 일부 변경이 필요합니다.

인스턴스

var myGamePiece;
var myObstacles = [];
function updateGameArea() {
  var x, y;
  for (i = 0; i < myObstacles.length; i += 1) {
    if (myGamePiece.crashWith(myObstacles[i])) {
      myGameArea.stop();
      return;
    }
  }
  myGameArea.clear();
  myGameArea.frameNo += 1;
  if (myGameArea.frameNo == 1 || everyinterval(150)) {
    x = myGameArea.canvas.width;
    y = myGameArea.canvas.height - 200
    myObstacles.push(new component(10, 200, "green", x, y));
  }
  for (i = 0; i < myObstacles.length; i += 1) {
    myObstacles[i].x += -1;
    myObstacles[i].update();
  }
  myGamePiece.newPos();
  myGamePiece.update();
}

직접 테스트해 보세요

제목 updateGameArea 함수에서는 각 장애물을 순회하며 충돌이 발생했는지 확인해야 합니다. 충돌이 발생하면 updateGameArea 함수가 중지되고 더 이상 그려지지 않습니다.

updateGameArea 함수는 프레임을 세고, 150 프레임마다 장애물을 추가합니다.

무작위 크기의 장애물

게임의 어려움과 재미를 더하기 위해, 우리는 무작위 크기의 장애물을 보내어 빨간 정육면체가 충돌하지 않도록 상하로 이동해야 합니다.

인스턴스

function updateGameArea() {
  var x, height, gap, minHeight, maxHeight, minGap, maxGap;
  for (i = 0; i < myObstacles.length; i += 1) {
    if (myGamePiece.crashWith(myObstacles[i])) {
      myGameArea.stop();
      return;
    }
  }
  myGameArea.clear();
  myGameArea.frameNo += 1;
  if (myGameArea.frameNo == 1 || everyinterval(150)) {
    x = myGameArea.canvas.width;
    minHeight = 20;
    maxHeight = 200;
    height = Math.floor(Math.random()*(maxHeight-minHeight+1)+minHeight);
    minGap = 50;
    maxGap = 200;
    gap = Math.floor(Math.random()*(maxGap-minGap+1)+minGap);
    myObstacles.push(new component(10, height, "green", x, 0));
    myObstacles.push(new component(10, x - height - gap, "green", x, height + gap));
  }
  for (i = 0; i < myObstacles.length; i += 1) {
    myObstacles[i].x += -1;
    myObstacles[i].update();
  }
  myGamePiece.newPos();
  myGamePiece.update();
}

직접 테스트해 보세요