J'essaie de comprendre ce problème très Hello World-y dans le développement de jeux. J'ai créé un jeu TicTacToe dans XNA, donc je suppose que la prochaine étape serait un clone de Breakout .
Gardez à l'esprit que je n'ai aucune connaissance de la programmation de jeux ni même des mathématiques à appliquer où. C'est pourquoi je pose cette question.
À la question: Comment puis-je déterminer où la balle doit rebondir lorsqu'elle frappe la pagaie au bas de l'écran?
J'imagine que ce serait quelque chose comme:
- Capturez la vitesse et l'angle de la balle entrante.
- Détecter l'endroit où il a touché la barre (extrême gauche, extrême droite, centre) et selon cela lui donner une vitesse plus élevée s'il a touché les zones extérieures.
- C'est là que je suis coincé. Hehe.
Des idées? Je me rends compte que ce n'est pas une question de type de réponse simple, mais je suis sûr que tout le monde est confronté à un moment donné.
Je lis le livre Algèbre linéaire qui a été recommandé sur ce site Web, mais je n'ai toujours aucune idée si je dois l'appliquer ici.
Réponses:
Voici la logique pertinente que j'ai utilisée sur le pong sur ma page d'accueil : (allez jouer avant de lire, afin que vous sachiez l'effet que j'obtiens avec le code suivant)
Essentiellement, lorsque le ballon entre en collision avec la raquette, sa direction est complètement ignorée; on lui donne une nouvelle direction selon la distance du centre de la pagaie à laquelle il est entré en collision. Si la balle frappe la raquette en plein centre, elle est renvoyée exactement à l'horizontale; s'il frappe directement sur le bord, il s'envole à un angle extrême (75 degrés). Et il voyage toujours à vitesse constante.
Prenez la valeur Y du milieu de la raquette et soustrayez l'intersection Y de la balle. Si la palette mesure 10 pixels de haut, ce nombre sera compris entre -5 et 5. J'appelle cela "l'intersection relative" car elle se trouve maintenant dans "l'espace de la palette", l'intersection de la balle par rapport au milieu de la palette.
Prenez l'intersection relative et divisez-la par la moitié de la hauteur de la palette. Maintenant, notre nombre de -5 à 5 est une décimale de -1 à 1; c'est normalisé . Multipliez-la ensuite par l'angle maximum selon lequel vous voulez que la balle rebondisse. Je l'ai réglé sur 5 * Pi / 12 radians (75 degrés).
Enfin, calculez les nouvelles vitesses de balle, en utilisant une trigonométrie simple.
Ce n'est peut-être pas tout à fait l'effet recherché, ou vous pouvez également déterminer une vitesse en multipliant l'intersection relative normalisée par une vitesse maximale; cela rendrait le ballon aller plus vite s'il frappe près du bord d'une pagaie, ou plus lentement s'il frappe près du centre.
Un vecteur contient à la fois la vitesse et la direction, implicitement. Je stocke mon vecteur en tant que "vx" et "vy"; c'est-à-dire la vitesse dans la direction x et la vitesse dans la direction y. Si vous n'avez pas suivi de cours d'introduction à la physique, cela peut vous sembler quelque peu étranger.
La raison pour laquelle je fais cela est parce qu'elle réduit les calculs par image nécessaires; chaque image, il suffit de le faire
x += vx * time;
ety += vy * time;
où le temps est le temps écoulé depuis la dernière image, en millisecondes (donc les vitesses sont en pixels par milliseconde).Concernant la mise en œuvre de la capacité à courber le ballon:
Tout d'abord, vous devez connaître la vitesse de la raquette au moment où la balle frappe; ce qui signifie que vous devez garder une trace de l'historique de la pagaie, afin de pouvoir connaître une ou plusieurs positions passées de la pagaie afin de pouvoir les comparer à sa position actuelle pour voir si elle a bougé. (changement de position / changement de temps = vitesse; vous avez donc besoin de 2 positions ou plus, et les heures de ces positions)
Vous devez maintenant également suivre une vitesse angulaire de la balle, qui représente pratiquement la courbe le long de laquelle elle se déplace, mais est équivalente à la rotation réelle de la balle. Semblable à la façon dont vous interpoleriez l'angle de rebond à partir de la position relative de la balle lors de la collision avec la palette, vous devrez également interpoler cette vitesse angulaire (ou rotation) à partir de la vitesse de la palette lors de la collision. Plutôt que de simplement régler le spin comme vous le faites avec l'angle de rebond, vous voudrez peut-être ajouter ou soustraire au spin existant de la balle, car cela a tendance à bien fonctionner dans les jeux (le joueur peut remarquer que la balle tourne et la faire tourner) encore plus follement, ou contrer le spin pour tenter de le faire voyager droit).
Notez, cependant, que bien que ce soit le sens le plus commun et probablement le plus facile à mettre en œuvre, la physique réelle d'un rebond ne repose pas uniquement sur la vitesse de l'objet qu'il frappe; un objet sans vitesse angulaire (sans rotation) qui frappe une surface à un angle, se verra conférer une rotation. Cela pourrait conduire à un meilleur mécanisme de jeu, donc vous voudrez peut-être examiner cela, mais je ne suis pas certain de la physique derrière, donc je ne vais pas essayer de l'expliquer.
la source
Cela fait un moment que je n'ai pas fait ça, mais je pense que j'ai bien compris.
Étant donné une collision parfaite, l'angle de réflexion est égal à l'angle d'incidence.
Vous connaissez la normale de votre pagaie (en supposant une surface plane): N Vous connaissez votre position d'origine de votre balle (au début de votre pas de temps): P Vous connaissez votre nouvelle position de la balle (à la fin du pas de temps): P 'Vous connaissez votre point de collision: C En supposant que vous avez calculé que le segment P -> P' passe à travers votre palette, votre nouvelle position réfléchie (P '') serait:
P '+ 2 * (N * (P' point -N))
La sous-expression N * (P 'dot -N) calcule la profondeur le long de la normale de collision de la balle. Le signe moins est de corriger le fait que nous vérifions la profondeur opposée à la direction de la normale.
Le P '+ 2 * la partie de la sous-expression ramène la balle au-dessus du plan de collision de 2 fois la profondeur de la collision.
Si vous voulez une collision moins que parfaite, changez le facteur 2 pour qu'il soit (1 + (1-k)) où k est votre coefficient de frottement. Une collision parfaite a une valeur k de 0, ce qui fait que l'angle de réflexion est exactement celui de l'angle entrant. Une valeur k de 1 provoque une collision où la balle reste à la surface du plan de collision.
Votre nouveau vecteur de vitesse, V '', direction serait P '' - C. Normalisez-le et multipliez par votre vitesse entrante et votre amplitude de vitesse résultante serait la même, mais dans la nouvelle direction. Vous pouvez singer avec cette vitesse en la multipliant par un coefficient, l, qui augmenterait (l> 1) ou diminuerait (l <1) la vitesse résultante.
Résumer:
P '' = P '+ (1-k) * (N * (P dot -N)) V' '= l * V * ((P' '- C) / | P' '- C |)
Où k et l sont les coefficients de votre choix.
la source
La réflexion peut être effectuée «correctement» ou «facilement».
La "bonne" façon est de calculer des vecteurs perpendiculaires aux murs. En 2D, c'est assez facile et vous pourriez probablement les coder en dur. Ensuite, l'étape de réflexion laisse essentiellement intacte la composante "parallèle" du mouvement et inverse la composante "perpendiculaire". Il y a probablement des informations détaillées sur le Web pour cela, peut-être même chez MathWorld.
La manière "simple" consiste à simplement annuler le mouvement X ou Y lorsque vous frappez un mur. Si vous frappez les parois latérales, vous nieriez X. Si vous frappez le haut, vous niez Y. Si vous voulez accélérer la balle, augmentez simplement ce que vous voulez; vous pouvez l'accélérer dans sa direction actuelle en multipliant les vitesses X et Y ou vous ne pouvez accélérer que sur un axe.
la source
Je fais moi-même un jeu arkanoid-ish et je pense que la solution sur la façon dont la balle devrait se comporter lorsque vous frappez la pagaie est assez simple et plus rapide que d'entrer dans l'approche sin / cos ... cela fonctionne bien pour les besoins d'un jeu comme ça. Voici ce que je fais:
Bien sûr, étant donné que la vitesse de la balle augmente dans le temps, j'interpole les étapes avant / après x, y pour garder une détection de collision précise, en parcourant tous les "stepX" et "stepY" qui sont calculés en divisant chaque composante de la vitesse par le module du vecteur formé par les positions actuelles et futures du ballon.
Si une collision contre la pagaie se produit, je divise la vitesse Y par 20. Ce "20" est la valeur la plus pratique que j'ai trouvée pour obtenir mon angle maximal résultant lorsque la balle frappe sur les côtés de la pagaie, mais vous pouvez la changer comme bon vous semble vos besoins sont, jouez avec quelques valeurs et choisissez le meilleur pour vous. En divisant, disons une vitesse de 5, qui est ma vitesse de jeu initiale par ce nombre (20), j'obtiens un "facteur de rebond" de 0,25. Ce calcul maintient mes angles assez proportionnels lorsque la vitesse augmente dans le temps jusqu'à ma valeur de vitesse maximale qui, par exemple, pourrait être de 15 (dans ce cas: 15/20 = 0,75). Sachant que mes coordonnées x, y sont au milieu (x et y représentent le centre de la palette), je multiplie ensuite ce résultat par la différence entre la position de la balle et la position de la palette. Plus la différence est grande, le grandear l'angle résultant. De plus, en utilisant un padlle à manche moyen, vous obtenez le signe correct pour l'incrément x en fonction du côté que la balle frappe sans avoir à vous soucier du calcul du centre. En pseudo-code:
Pour n = 0 au module ...
si collision_detected alors speedX = - (speedY / 20) * (paddleX - ballX); speedY = -speedY;
sortie; fin si
...
x = x + stepX; y = y + stepY;
fin pour
Rappelez-vous, essayez toujours de garder les choses SIMPLES. J'espère que ça aide!
la source
La palette dans Breakout, lorsqu'elle suit le style que vous décrivez, est généralement modélisée comme une surface courbe. L'angle d'incidence change en fonction de l'endroit où la pagaie frappe. Au point mort, la tangente à la courbe est absolument horizontale et la balle se reflète comme prévu. Lorsque vous vous éloignez du centre, la tangente à la courbe devient de plus en plus angulaire et la balle se reflète différemment en conséquence.
Le point clé est que c'est l'angle de réflexion, et non la vitesse de la balle, qui change. La vitesse de la balle augmente généralement lentement au fil du temps.
la source
angle = 1 - 2 * (ball.x - paddle.left) / paddle.width
vous donnera un nombre compris entre 1 et -1; ceci (fois une valeur modifiée pour vos mécanismes de jeu) est la pente de la ligne tangente au point où la balle est entrée en collision. Réfléchissez sur cette ligne plutôt que sur la ligne strictement horizontale.Nolan Bushnell a prononcé un discours d'ouverture au SIEGE le week-end dernier et a parlé d'un problème similaire avec le pong d'origine. Vous n'avez pas à faire beaucoup de calculs compliqués. Si vous frappez vers la partie gauche du panneau, envoyez la balle vers la gauche. Faites de même pour le côté droit.
Pour commencer, vous pouvez faire un angle de 45 degrés pour les côtés gauche et droit. Une fois que vous avez terminé le jeu, vous pouvez, si vous le souhaitez, revenir en arrière et rendre cela plus compliqué, mais le plus simple possible pour commencer.
la source
Breakout est un travail classique pour débutants pour commencer à plonger dans le monde de la programmation de jeux basée sur la physique. Fondamentalement, la balle a un mouvement de rebond lorsqu'elle frappe le mur. Comme quelqu'un ci-dessus l'a suggéré, l'angle d'incidence est égal à l'angle de réflexion. Mais quand on considère la balle frapper la pagaie. La logique est divisée en 3 sections. 1.) La balle frappe la partie centrale de la pagaie. 2.) La balle frappe la partie gauche de la raquette. 3.) La balle frappant la position droite de la raquette.
Lorsque vous considérez la partie centrale: vous ne devez pas différer l'effet de rebond de celui qui est appliqué lorsque vous frappez la balle. La balle est juste déviée normalement, mais lorsque l'une ou l'autre direction est touchée, le cas est différent.
Lorsque le ballon est frappé sur le côté gauche, c'est-à-dire, considérez le ballon venant du côté gauche de l'écran et vous venez avec la pagaie du côté droit. Ensuite, lorsque vous frappez la balle avec la partie gauche, la balle doit se refléter dans la direction d'où elle vient. À gauche avec le même angle d'où elle vient. Il en va de même inversement. Dans la partie droite, la même chose s'applique également.
Ce mouvement de la balle vers la gauche ou la droite lorsqu'elle est frappée la rend plus crédible.
J'espère que vous avez eu l'idée, au moins du point de vue logique. Merci
la source
Imaginez que vous calculez la distance entre le centre de la raquette et le point où la balle Y a frappé et appelez-la
d
. Supposonsd
que la valeur soit positive lorsque la balle frappe au-dessus du centre de la raquette. Vous pouvez maintenant augmenterd * -0.1
la vitesse Y de votre balle et elle commencera à changer de direction. Voici un exemple en javascript qui peut être facilement traduit en c #!la source
ceci aidera http://www-classes.usc.edu/engr/ee-s/477p/s00/pong.html à inverser simplement x et y selon l'endroit où il frappe l'écran. si elle monte et touche le haut, elle inverse la vitesse y tout en gardant la vitesse x
la source
Salut, j'ai récemment essayé de faire un jeu de balle et j'ai trouvé une solution pour cela. Alors ce que j'ai fait: la pagaie bouge pendant que nous jouons. Mon système de coordonnées est laissé tel quel, le point en haut à gauche du canevas est 0,0. La palette se déplace dans ce système de coordonnées. L'axe x pointe de 0 à la largeur du canevas et l'axe y pointe sur 0 à la hauteur du canevas. J'ai créé une pagaie avec une taille fixe de 100 largeur et 20 hauteur. Et puis je dessine un cercle imaginé autour de lui. Lorsque la balle frappe la pagaie, je calcule le point central de la pagaie
Ensuite, je soustrais le centre de la position actuelle de la balle de cette façon, le système de coordonnées sera au centre de la palette, ballCenter est le point où la balle a frappé la palette (- (largeur de palette + r) .. 0 .. (largeur de palette + r )) ce n'est rien d'autre que de redimensionner le point de frappe sur la pagaie
calculer le point d'intersection du cercle à l'aide du point de frappe de la balle (x0) c'est un recalcul, nous demandons la coordonnée y sur le cercle avec la coordonnée x0 déjà connue et il fallait un flip pour l'axe y
calculer la dérivée de l'équation normale du cercle qui est définie autour de la palette avec radis paddleRadius f (x, y) = x ^ 2 + y ^ 2-r ^ 2
normaliser le vecteur N, pour obtenir un vecteur unitaire pour la surface normale
nous avons maintenant les normales de surface normalisées (unitaires) pour la palette. Calculez la nouvelle direction avec ces normales de surface, cela sera calculé à l'aide de la formule du vecteur de réflexion: new_direction = old_direction-2 * point (N, old_direction) * N, mais avec la surface normale pointant toujours vers le haut, la volonté de la normale changer d'un point à un autre où la balle touche la raquette
J'ai publié ma solution à ce problème. Pour plus de détails et pour le jeu complet, vous pouvez voir mon dépôt github:
https://github.com/zoli333/BricksGame
écrit en java avec éclipse. Il y a une autre solution pour cela commentée dans Ball.java, où le redimensionnement ne se produit pas, je ne déplace pas le système de coordonnées au point central de la palette, au lieu de cela je calcule tout cela ci-dessus à partir du système de coordonnées topleft 0,0 par rapport à le point central de la pagaie. Cela fonctionne aussi.
la source