2d html5 collision de toile, comment

Comme le suggère le titre, j'ai des problèmes avec la collision d'objets … Je travaille actuellement sur un jeu de toile 2d Html5 utilisant JavaScript. Je sais comment empêcher l'objet "joueur" d'aller en dehors de la largeur / hauteur de la toile de jeu, et je sais comment faire quelque chose lorsque le joueur entre en collision avec un objet (par exemple, un power-up ou un ennemi ou n'importe quoi) mais je juste Ne sait pas comment faire un objet "solide" signifiant quand le joueur frappe l'objet solide, le joueur s'arrête et ne peut pas passer par l'objet solide.

C'est ce que j'ai maintenant (pas tout le code juste ce que je ressens est pertinent, désolé si c'est trop ou trop peu

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.drawX + player1.width && this.drawY >= player1.drawY && this.drawY < player1.drawY + player1.height) { player1.isUpKey = false; player1.isDownKey = false; player1.isRightKey = false; player1.isLeftKey = false; } }; 

Cela fonctionne … sauf lorsque vous essayez de monter ou de quitter, le joueur ne déplace que 2-3 pixels, donc il faut 3 flèches gauche ou haute pour aller vers la gauche ou vers le haut. De plus, le joueur peut se déplacer directement à travers le mur, ce qui n'est pas ce que je veux. Toute aide est très appréciée, désolé si j'ai inclus trop ou pas assez de code. Oh, j'ai également oublié de mentionner que le jeu est un jeu de puzzle, et je l'ai configuré pour qu'un joueur ne puisse se déplacer qu'une direction à la fois jusqu'à frapper un mur.

Si vous voulez simplement que votre lecteur s'arrête lorsque vous atteignez un mur, vous pouvez appliquer des calculs:

Par exemple: supposez que votre joueur est un rectangle de 10px par 10px et que la position X du mur droit est de 200.

La position X du côté droit du rectangle est calculée comme suit:

 var playerRightSide = player.x + player.width; 

Vous pouvez tester si le joueur a atteint le mur comme ceci:

 if( playerRightSide >= 200 ) 

Si l'utilisateur tente de pousser son joueur au-delà du mur, vous maintenez le joueur à gauche du mur à l'aide de la position des joueurs X.

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

Le 190 est la position X du mur (200) moins la largeur du joueur (10).

Lisez plus loin si vous souhaitez effectuer des tests de collision plus avancés.

De nombreuses collisions de base sur les jeux peuvent être classées en 3 types:

  • Collision Circle versus Circle
  • Rectangle versus Rectangle collision
  • Rectangle versus collision par cercle

Voici une illustration de la façon de détecter chacune de ces collisions communes.

Supposons que vous définissez un cercle comme celui-ci:

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

Supposons que vous définissiez un rectangle comme ceci:

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

Vous pouvez détecter des collisions Circle vs Circle comme ça …

Entrez la description de l'image ici

… Utilisation de ce code de test de collision Circle vs Circle:

  // 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<=rSum*rSum); } 

Vous pouvez détecter des collisions Rectangle vs Rectangle comme celle-ci …

Entrez la description de l'image ici

… Utilisation de ce code Rectangle vs Rectangle collision-test:

  // 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.w<r2.x || r1.y>r2.y+r2.h || r1.y+r1.h<r2.y); } 

Vous pouvez détecter des collisions Rectangle vs Circle comme ça …

Entrez la description de l'image ici

… En utilisant ce code de test de collision Rectangle vs Circle:

  // 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 <= rect.w ){ return(true); } if( dy <= rect.h ){ return(true); } var dx=dx-rect.w; var dy=dy-rect.h return(dx*dx+dy*dy<=circle.r*circle.r); } 

Par exemple, vous pouvez utiliser ces tests de collision pour répondre à un joueur touchant un cube de mise sous tension:

  // 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; } 

Voici le code et un violon: http://jsfiddle.net/m1erickson/u6t48/

 <!doctype html> <html> <head> <link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css --> <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script> <style> body{ background-color: ivory; padding:20px; } canvas{border:1px solid red;} </style> <script> $(function(){ var canvas=document.getElementById("canvas"); var ctx=canvas.getContext("2d"); window.requestAnimFrame = (function(callback) { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60); }; })(); ctx.fillStyle="lightgray"; ctx.strokeStyle="skyblue"; // top collision circle vs circle var circle1={x:30,y:30,r:10}; var circle2={x:70,y:40,r:10}; var circle3={x:100,y:30,r:10}; var direction1=1; // middle collision rect vs rect var rect1={x:20,y:100,w:20,h:20}; var rect2={x:50,y:110,w:20,h:20}; var rect3={x:90,y:100,w:20,h:20}; var direction2=1; // bottom collision rect vs circle var circle4={x:30,y:200,r:10}; var rect4={x:50,y:205,w:20,h:20}; var circle5={x:100,y:200,r:10}; var direction3=1; function drawAll(){ ctx.clearRect(0,0,canvas.width,canvas.height); drawCircle(circle1); drawCircle(circle2); drawCircle(circle3); drawCircle(circle4); drawCircle(circle5); drawRect(rect1); drawRect(rect2); drawRect(rect3); drawRect(rect4); } function drawCircle(c){ ctx.beginPath(); ctx.arc(cx,cy,cr,0,Math.PI*2,false); ctx.closePath(); ctx.fill(); ctx.stroke(); } function drawRect(r){ ctx.beginPath(); ctx.rect(rx,ry,rw,rh); ctx.closePath(); ctx.fill(); ctx.stroke(); } // return true if the 2 circles are colliding 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<=rSum*rSum); } // return true if the 2 rectangles are colliding function RectsColliding(r1,r2){ return !(r1.x>r2.x+r2.w || r1.x+r1.w<r2.x || r1.y>r2.y+r2.h || r1.y+r1.h<r2.y); } // return true if the rectangle and circle are colliding function RectCircleColliding(rect,circle){ var dx=Math.abs(circle.x-(rect.x+rect.w/2)); var dy=Math.abs(circle.y-(rect.y+rect.h/2)); if( dx > circle.r+rect.w/2 ){ return(false); } if( dy > circle.r+rect.h/2 ){ return(false); } if( dx <= rect.w ){ return(true); } if( dy <= rect.h ){ return(true); } var dx=dx-rect.w; var dy=dy-rect.h return(dx*dx+dy*dy<=circle.r*circle.r); } var fps = 15; function animate() { setTimeout(function() { requestAnimFrame(animate); // circle vs circle circle2.x = circle2.x+direction1; if( CirclesColliding(circle2,circle1) || CirclesColliding(circle2,circle3) ){ direction1=-direction1; } // rect vs rect rect2.x = rect2.x+direction2; if( RectsColliding(rect2,rect1) || RectsColliding(rect2,rect3) ){ direction2=-direction2; } // rect vs circle rect4.x = rect4.x+direction3; if( RectCircleColliding(rect4,circle4) || RectCircleColliding(rect4,circle5) ){ direction3=-direction3; } drawAll(); }, 1000 / fps); } animate(); }); // end $(function(){}); </script> </head> <body> <canvas id="canvas" width=300 height=300></canvas> </body> </html>