2014-07-26 2 views
2

J'essaie de comprendre comment utiliser et créer des boules de collision avec des canevas HTML5, les exemples que j'ai regardés ont beaucoup de JavaScript, mais je dois les décomposer en plus petits morceaux pour obtenir une meilleure compréhension de ce qui se passe. Dans mon Example, ce que je comprends jusqu'à présent, c'est que je redessine les cercles toutes les 40 millisecondes sur le canevas, et j'appelle la fonction animate à chaque fois. Chaque fois que cela s'appelle la position des changements de cercle que je change avecComprendre le canevas HTML5

circles[0].x+=1; 
circles[0].y+=-1.5; 

donc mes objets de cercle sont dans un tableau, et il y a 2 choses que je voudrais réaliser

1) Non laisser les balles s'échapper de la zone de la toile

2) si les billes entrent en collision, rebondir l'une l'autre et inverser la direction.

Ce que je veux aborder d'abord que ne laisse pas les boules échapper à la toile et comment je voudrais aller sur le travail que sur

J'ai accès à l'window.width et window.height de sorte que son cas de compréhension comment obtenir la position de chaque balle dans le tableau et assurez-vous qu'il ne traverse pas ces limites

Si quelqu'un peut aider à expliquer cela, il serait très apprécié, je ne veux pas juste avoir du travail, préférerait de beaucoup comprendre que se passe-t-il?

Merci

+0

[Cette question] (http://stackoverflow.com/questions/20885297/collision-detection- in-html5-canvas) peut vous montrer comment détecter les collisions entre les balles et le conteneur, et [celui-ci] (http://stackoverflow.com/questions/8331243/circle-collision-javascript) entre les balles elles-mêmes. Ensuite, en cas de collision, vous devez changer la direction de la balle pour créer le rebond. – undefined

+0

Et [voici un tutoriel complet] (http://www.exeneva.com/2012/06/multiple-balls-bouncing-and-colliding-example/). – undefined

Répondre

2
circles[0].x+=1; 
circles[0].y+=-1.5; 

C'est assez difficile à maintenir. Au lieu de cela, je vous suggère d'avoir des propriétés pour les vitesses X et Y (j'ai utilisé moveX et moveY dans l'exemple).

Ensuite, vous devez vérifier si la position de la bille + la compensation de rayon est en contact avec les bords de la toile et, si c'est le cas, inverser la valeur de la vitesse. Ainsi, par exemple, la vitesse X de la balle est de 4 et maintenant elle touche la gauche ou la droite toile egde, la vitesse X devient -4.

C'est-il, en un mot:

  var c = circles[i]; 

      // check rebounds 
      if (c.x - c.radius <= 0 || c.x + c.radius >= canvas.width) 
       c.moveX = -c.moveX; // flip the horizontal speed component 
      if (c.y - c.radius <= 0 || c.y + c.radius >= canvas.height) 
       c.moveY = -c.moveY; // flip the vertical speed component 

      // Yellow Circle 
      c.x += c.moveX; // here we don't have to worry 
      c.y += c.moveY; // about directions anymore 

Voir mon exemple ici: http://jsfiddle.net/3tfUN/8/

Le même principe vaut pour les collisions entre les balles. Je suppose que vous voulez faire des collisions simples sans changements d'angle. Mais si vous souhaitez simuler de vraies collisions de balles, cela nécessiterait une trigonométrie plus sérieuse pour calculer exactement quand la collision pixel parfait aura lieu, et pour calculer les nouvelles composantes de vitesse X et Y.


MISE À JOUR

Un exemple avec détection de collision légèrement améliorée et la vitesse de transfert entre les billes: http://jsfiddle.net/3tfUN/12/

+0

je vous remercie pour votre réponse, oui je vais venir sur de simples collisions mais d'abord je pense mauvais digérer ce qui se passe ici, puis passer à ce – Richlewis

+2

Aussi vous n'avez pas besoin de faire rayon/2 - devrait être rayon – geedubb

+0

Vous êtes bienvenue, je suis en train d'étendre ce dernier violon pour inclure de simples collisions. Mais fondamentalement, ce sera la même chose que la détection de collisions toile egde. – Shomz

1

La toile est juste une "toile" où vous dessinez les cercles. Ce dont vous avez besoin pour accomplir ce que vous voulez est de modéliser un "monde" où les cercles sont objets avec des dimensions de largeur et de hauteur et leur position actuelle, et où les limites sont bien définies. Une fois que vous avez la largeur et la hauteur de chaque cercle et leur position, vous pouvez calculer où ils sont par rapport aux limites que vous définissez et voir si vous devez changer de direction ou continuer. Les collisions proviennent du même principe mais sont plus difficiles à modéliser si vous voulez qu'elles soient «réalistes» (dans le problème des limites, vous ne vous intéressez qu'à la largeur et à la hauteur des cercles parce que la zone de délimitation est en forme de boîte et le cercle se heurtera toujours au point le plus éloigné de son centre, tandis que lorsque deux cercles entrent en collision, vous devez tenir compte du rayon de chaque cercle au lieu de la "boîte englobante" qui les entoure

Je n'ai pas le temps maintenant pour vous montrer ces concepts avec des exemples, mais j'espère que je vous ai envoyé dans la bonne voie :).

3

Ceci vérifie les collisions sur les limites de la toile. J'ai mis à jour vos objets pour stocker vx et vy (vélocité) et la fonction draw() pour se déplacer en fonction de ces propriétés. J'ai ajouté checkBounds() qui inverse la vitesse lorsque le cercle sort des limites.

EDIT: modifié afin qu'il prenne en compte le rayon des cercles.

Faire une collision entre les cercles de détecter pourrait suivre un schéma similaire

http://jsfiddle.net/3tfUN/5/

var canvas = document.getElementById('ball-canvas'); 
    var context = canvas.getContext('2d') 
    var radius = 50; 
    var strokewidth = 2; 
    var strokestyle = '#666'; 
    var frameCount = 0; 
    var w = canvas.width; 
    var h = canvas.height; 

    // Circle Objects 
    var yellowCircle = { 
     x: 50, 
     y: h/2, 
     radius: radius, 
     color: 'yellow', 
     vx: 1, 
     vy: 1.5 
    } 

    var redCircle = { 
     x: 450, 
     y: h/2, 
     radius: radius, 
     color: 'red', 
     vx: 1, 
     vy: -1 
    } 

    var blueCircle = { 
     x: 850, 
     y: h/2, 
     radius: radius, 
     color: 'blue', 
     vx: -1, 
     vy: -1.5 
    } 

    // Create empty array and then push cirlce objects into array 
    var circles = []; 
    circles.push(yellowCircle, blueCircle, redCircle); 

    function checkBounds() { 
     for (var i = 0; i < circles.length; i++) { 
      var c = circles[i]; 
      if (c.x > w - c.radius || c.x < c.radius) { 
       c.vx = -c.vx; 
      } 
      if (c.y > h - c.radius || c.y < c.radius) { 
       c.vy = -c.vy; 
      } 
     } 
    } 

    // Clear last circle and draw again 
    function draw() { 
     context.clearRect(0, 0, canvas.width, canvas.height); // Clear the circle from the from page 
     for (var i = 0; i < circles.length; i++) { 
      var c = circles[i]; 
      context.beginPath(); 
      context.fillStyle = c.color // Set the color of the circle using key:valuecontext.fill(); 
      context.lineWidth = strokewidth; 
      context.strokeStyle = strokestyle; 
      context.stroke(); 
      context.arc(c.x, c.y, c.radius, 0, Math.PI * 2); // X-axis Position, y-axis Position, radius, % of fill, ? 
      context.closePath(); 
      context.fill(); 
     } 
    } 

    function animate() { 
     for (i = 0; i <= 2; i++) { 
      circles[i].x += circles[i].vx; 
      circles[i].y += circles[i].vy; 
     } 
     checkBounds(); 
     draw(); 
    } 

    var canvas = document.getElementById('ball-canvas'); 
    var context = canvas.getContext('2d') 
    var radius = 50; 
    setInterval(animate, 40);