2d html5 canvas collision, howto

匿名 (未验证) 提交于 2019-12-03 01:10:02

问题:

As the title suggests, I am having trouble with object collision... I am currently working on a 2d Html5 canvas game using JavaScript. I know how to keep the "player" object from going outside the width/height of the game canvas, and i know how to do something when the player collides with an object (such as a power up or enemy or whatever) but i just don't know how to make a "solid" object meaning when the player hits the solid object, the player just stops, and cannot go through the solid object.

This is what I have now (not all the code just what I feel is relevant, sorry if it's too much/too little.:

  var canvasPlayer = document.getElementById('canvasPlayer'); var ctxPlayer = canvasPlayer.getContext('2d'); var canvasWalls = document.getElementById('canvasWalls'); var ctxWalls = canvasWalls.getContext('2d');  function checkKeyDown(e) {         var keyID = (e.keyCode) || e.which;         if (keyID === 38 || keyID === 87)   { // up arrow OR W key         if (!player1.isDownKey && !player1.isLeftKey && !player1.isRightKey) {         player1.isUpKey = true;         e.preventDefault();         } }         if (keyID === 39 || keyID === 68)   { //right arrow OR D key         if (!player1.isDownKey && !player1.isLeftKey && !player1.isUpKey) {         player1.isRightKey = true;         e.preventDefault();         } }         if (keyID === 40 || keyID === 83)   {//down arrow OR S key         if (!player1.isUpKey && !player1.isLeftKey && !player1.isRightKey) {         player1.isDownKey = true;         e.preventDefault();         } }         if (keyID === 37 || keyID === 65)   {//left arrow OR A key         if (!player1.isDownKey && !player1.isUpKey && !player1.isRightKey) {         player1.isLeftKey = true;         e.preventDefault();         }         }     }      Walls.prototype.draw = function (){         ctxWalls.drawImage(imgSprite,this.srcX,this.srcY,this.width,this.height,this.drawX,this.drawY,this.width,this.height);         this.checkHitPlayer();         };     Walls.prototype.checkHitPlayer = function() {         if (this.drawX > player1.drawX &&         this.drawX = player1.drawY &&         this.drawY 

This works... except when trying to go up or left, the player only moves maybe 2-3 pixels, so it takes 3 left or up arrows to go left or up. As well the player can move straight through the wall which is not what i want. Any help is much appreciated sorry if i included too much or not enough code. Oh, i also forgot to mention the game is a puzzle game, and I have it set-up so a player can only move one direction at a time until hitting a wall.

回答1:

If you just want your player to stop when the reach a wall, you can apply some math:

For example: assume your player is a 10px by 10px rectangle and the right wall's X position is 200.

The X position of the right side of the rectangle is calculated like this:

var playerRightSide = player.x + player.width; 

You can test if the player has reached the wall like this:

if( playerRightSide >= 200 ) 

If the user tries to push their player beyond the wall, you would hold the player to the left of the wall using the players X position.

if( playerRightSide >= 200 ) { player.x = 190; }   

The 190 is the wall's X position (200) minus the player's width (10).

Read further if you're interested in doing more advanced collision testing.

Many basic game collisions can be classified into 3 types:

  • Circle versus Circle collision
  • Rectangle versus Rectangle collision
  • Rectangle versus Circle collision

Here’s an illustration of how to detect each of these common collisions.

Assume you define a circle like this:

var circle1={     x:30,     y:30,     r:10 }; 

Assume you define a rectangle like this:

var rect1={     x:20,     y:100,     w:20,     h:20 }; 

You can detect Circle vs Circle collisions like this...

...Using this Circle vs Circle collision-test code:

    // return true if the 2 circles are colliding     // c1 and c2 are circles as defined above      function CirclesColliding(c1,c2){         var dx=c2.x-c1.x;         var dy=c2.y-c1.y;         var rSum=c1.r+c2.r;         return(dx*dx+dy*dy

You can detect Rectangle vs Rectangle collisions like this...

...Using this Rectangle vs Rectangle collision-test code:

    // return true if the 2 rectangles are colliding     // r1 and r2 are rectangles as defined above      function RectsColliding(r1,r2){         return !(r1.x>r2.x+r2.w || r1.x+r1.wr2.y+r2.h || r1.y+r1.h

You can detect Rectangle vs Circle collisions like this...

...Using this Rectangle vs Circle collision-test code:

    // return true if the rectangle and circle are colliding     // rect and circle are a rectangle and a circle as defined above      function RectCircleColliding(rect,circle){         var dx=Math.abs(circle.x-(rect.x+rect.w/2));         var dy=Math.abs(circle.y-(rect.y+rect.y/2));          if( dx > circle.r+rect.w2 ){ return(false); }         if( dy > circle.r+rect.h2 ){ return(false); }          if( dx 

For example, you can use these collision tests to respond to a player touching a power-up cube:

    // create a circular player object     // that's located at [30,30] and has a radius of 10px      var player={x:30,y:30,r:10};       // create a rectangular power-up at position [200,30]      var powerup={x:200, y:30, w:20, h:20};       // Let's say the user keys the player to coordinate [200,35]      // (touching the power-up)      player.x = 220;     player.y = 35;       // you can test if the circular player is touching the rectangular power-up      if( RectCircleColliding(powerup,player)  ) {          // the player has collided with the power-up, give bonus power!          player.power += 100;      } 

Here is code and a Fiddle: http://jsfiddle.net/m1erickson/u6t48/

   


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!