2D Platform Shooter Canvas游戏|创建拍摄功能

时间:2018-11-09 13:56:23

标签: javascript canvas game-development

所以我正在为一个学校项目制作这个非常基本的游戏。我让所有基本控制器都在工作,跳跃,左右导航,但我一直在努力寻找使角色能够射击的方法。我也想做到这一点,就像每次拍摄之间的休息一样,就像一个螺栓动作。碰撞部分应该没有问题,因此在那里不需要帮助。

(function() {
 var requestAnimationFrame =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame;
})();

var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
width = 640,
height = 480,
player = {
x: width / 2,
y: height - 140,
width: 35,
height: 90,
speed: 3,
velX: 0,
velY: 0,
jumping: false,
grounded: false
},
keys = [],
friction = 0.8,
gravity = 0.3;

var hovedkarakterBilde = new Image();
    hovedkarakterBilde.src = "mc1.png";

var boxes = [];

// dimensions
boxes.push({
// venstre vegg
x: 0,
y: 0,
width: 10,
height: height
 });
boxes.push({
// gulv
x: 0,
y: height - 68,
 width: width,
height: 1
});

boxes.push({
x: 120,
y: 250,
width: 80,
height: 80
});
boxes.push({
 x: 170,
 y: 275,
 width: 80,
 height: 80
 });
 boxes.push({
 x: 220,
 y: 325,
 width: 80,
 height: 80
  });
boxes.push({
 x: 270,
 y: 225,
 width: 40,
 height: 40
 });

canvas.width = width;
canvas.height = height;

 function update() {
 // check keys
 if (keys[38]) {
   // up arrow or space
  if (!player.jumping && player.grounded) {
  player.jumping = true;
  player.grounded = false;
  player.velY = -player.speed * 2;
   }
  }
  if (keys[39]) {
  // right arrow
  if (player.velX < player.speed) {
  player.velX++;
   }
  }
 if (keys[37]) {
 // left arrow
 if (player.velX > -player.speed) {
  player.velX--;
  }
 }

  player.velX *= friction;
  player.velY += gravity;

  ctx.clearRect(0, 0, width, height);
  ctx.fillStyle = "black";
  ctx.beginPath();

  player.grounded = false;
  for (var i = 0; i < boxes.length; i++) {
  ctx.rect(boxes[i].x, boxes[i].y, boxes[i].width, boxes[i].height);

  var dir = colCheck(player, boxes[i]);

  if (dir === "l" || dir === "r") {
    player.velX = 0;
    player.jumping = false;
  } else if (dir === "b") {
    player.grounded = true;
    player.jumping = false;
 } else if (dir === "t") {
    player.velY *= -1;
 }
 }

 if (player.grounded) {
player.velY = 0;
}

player.x += player.velX;
player.y += player.velY;

ctx.fill();
ctx.drawImage(
hovedkarakterBilde,
player.x,
player.y,
player.width,
player.height
 );

requestAnimationFrame(update);
}



function colCheck(shapeA, shapeB) {
// get the vectors to check against
 var vX = shapeA.x + shapeA.width / 2 - (shapeB.x + shapeB.width / 2),
  vY = shapeA.y + shapeA.height / 2 - (shapeB.y + shapeB.height / 2),
  // add the half widths and half heights of the objects
  hWidths = shapeA.width / 2 + shapeB.width / 2,
  hHeights = shapeA.height / 2 + shapeB.height / 2,
  colDir = null;

 // if the x and y vector are less than the half width or half height, they 
 we must be inside the object, causing a collision
  if (Math.abs(vX) < hWidths && Math.abs(vY) < hHeights) {
 // figures out on which side we are colliding (top, bottom, left, or right)
   var oX = hWidths - Math.abs(vX),
    oY = hHeights - Math.abs(vY);
    if (oX >= oY) {
    if (vY > 0) {
      colDir = "t";
      shapeA.y += oY;
    } else {
      colDir = "b";
      shapeA.y -= oY;
     }
   } else {
     if (vX > 0) {
      colDir = "l";
      shapeA.x += oX;
    } else {
      colDir = "r";
      shapeA.x -= oX;
     }
  }
}
  return colDir;
}

document.body.addEventListener("keydown", function(e) {
keys[e.keyCode] = true;
});

document.body.addEventListener("keyup", function(e) {
 keys[e.keyCode] = false;
 });

window.addEventListener("load", function() {
update();
});    

HTML:

</head>
<body>
<canvas id="canvas" style="background: url('bakgrunn1.png')"></canvas>
 </body>
 <script src="spillv2.js"></script>

2 个答案:

答案 0 :(得分:0)

首先要考虑的是子弹是命中扫描还是弹丸。命中扫描意味着当子弹发射时,子弹立即击中目标。这可以通过使用射线投射检查是否撞击到对象来完成。基于弹丸的子弹是指用户指向某个方向时,子弹实际上会“移动”。这可以通过向播放器添加“子弹”数组来实现。因此,当玩家单击时,将在项目列表中添加项目符号对象。该项目符号对象将在绘制循环中自行绘制,并将从用户移动到其指向的方向。

添加延迟很简单,您可以拥有一个“ cooldown”变量,该变量是一个持续n毫秒的计数器。当用户触发时,计数器设置为n,并开始递减计数到0。当用户触发时,您可以再次触发。

答案 1 :(得分:0)

好吧,您可以创建一个shoot(e)函数,例如,当用户按下(keydown)空间然后创建一个新数组时,该函数将被调用,假设ammo[]。然后,在shoot()内,您将执行以下操作:

const ammo = [];
let shooting = false;
function shoot(e) {
      e = e || event;
      const key = e.keyCode;
      if(shooting) return; // This will prevent from shooting more bullets while holding space
      // So you'd need to press space for each time you want to shoot.
      if(key == 32) { // Key code 32 is SPACE
         shooting = true;
         // You get the coordinates from your player, from which the bullet will shoot
         ammo.push({
         x: player.x,
         y: player.y + (player.height / 2) 

        // Player.height / 2 is basically setting the ammo at the middle of the character
        });
      }
}

然后,我假设您在update()函数中进行了所有更新(是的,从逻辑上讲:D),您将执行类似的操作:

function update() {
  // Insert it somewhere
  for(let i = 0; i < ammo.length; i++) {
    // The "theBullet" part refers to either your image for the bullet
    ctx.drawImage(theBullet, ammo[i].x, ammo[i].y;
    ammo[i].x++ // Or however fast you'd like it to go.
  }
}

希望它有点清晰,我正在自己开发一款太空射击游戏类型的游戏,快要完成了,所以在这里分享了我的一些代码:)并不意味着它是最好的,但是它确实可以做到:)