Comment appliquer la gravité à ma demande de balle rebondissante?
J'ai écrit un assez simple application java qui vous permet de glisser votre souris et en fonction de la durée de la souris, faites glisser que vous avez fait, il va tirer une balle dans cette direction, en rebondissant sur les murs, comme il va.
Voici une petite capture d'écran:
le texte d'alt http://img222.imageshack.us/img222/3179/ballbouncemf9.png
Chacun des cercles sur l'écran est une Boule d'objet. Les boules mouvement est décomposé en x et y du vecteur;
public class Ball {
public int xPos;
public int yPos;
public int xVector;
public int yVector;
public Ball(int xPos, int yPos, int xVector, int yVector) {
this.xPos = xPos;
this.yPos = yPos;
this.xVector = xVector;
this.yVector = yVector;
}
public void step()
{
posX += xVector;
posY += yVector;
checkCollisions();
}
public void checkCollisions()
{
//Check if we have collided with a wall
//If we have, take the negative of the appropriate vector
//Depending on which wall you hit
}
public void draw()
{
//draw our circle at it's position
}
}
Cela fonctionne très bien. Toutes les balles rebondissent autour de et autour de mur à mur.
Cependant, j'ai décidé que je voulais être en mesure d'inclure les effets de la gravité. Je sais que les objets d'accélérer vers la terre à 9,8 m/s, mais je n'ai pas directement savoir comment cela devrait se traduire par code. Je me rends compte que la yVector sera affectée, mais mon expérimentation avec les ce n'ont pas l'effet désiré que je voulais.
Idéalement, je voudrais être en mesure d'ajouter un peu de la gravité de ce programme et permettent aussi que les balles rebondissent à quelques reprises avant de s'installer à la "terre".
Comment puis-je créer ce rebondissement élastique, de la gravité? Comment dois-je manipuler les vecteurs de vitesse de la balle à chaque étape? Ce qui doit être fait quand il frappe le "terrain" afin que je puisse lui permettre de rebondir de nouveau, mais un peu plus court que la fois précédente?
Toute aide est très appréciée dans de me pointer dans la bonne direction.
Merci pour les commentaires tout le monde! C'est déjà génial de travailler!
Dans ma démarche() je suis l'ajout d'une gravité constante de mon yVector comme l'ont suggéré, et c'est mon checkCollision():
public void checkCollision()
{
if (posX - radius < 0) //Left Wall?
{
posX = radius; //Place ball against edge
xVector = -(xVector * friction);
}
else if (posX + radius > rightBound) //Right Wall?
{
posX = rightBound - radius; //Place ball against edge
xVector = -(xVector * friction);
}
//Same for posY and yVector here.
}
Cependant, les boules vont continuer à le faire glisser autour de la/rouler sur le sol. Je suppose que c'est parce que je suis tout simplement en prenant un pourcentage (90%) de leurs vecteurs chaque rebond et il n'est jamais vraiment zéro. Dois-je ajouter dans une case que si le xVector devient d'une certaine valeur absolue que je devrais juste changer à zéro?
source d'informationauteur
Vous devez vous connecter pour publier un commentaire.
Ce que vous avez à faire est de constamment soustraire une petite constante (quelque chose qui représente votre 9,8 m/s) à partir de votre yVector. Lorsque le ballon est à la baisse (yVector est déjà négatif), ce serait le faire aller plus vite. Quand il va jusqu' (yVector est positif), on pourrait le ralentir.
Ce ne serait pas compte de la friction, de sorte que les choses devraient rebondir assez bien pour toujours.
edit1:
Pour tenir compte de la friction, chaque fois que cela s'inverse (et on inverse le signe), de la baisse du nombre absolu un peu. Comme si elle frappe à yVector=-500, lorsque vous inversez la signer, la faire +480 au lieu de +500. Vous devriez probablement faire la même chose pour xVector pour l'empêcher de rebondir d'un côté à-côté.
edit2:
Aussi, si vous le souhaitez réagir à la friction de l'air", de réduire à la fois les vecteurs par une très petite quantité à chaque réglage.
edit3:
Au sujet de la chose rouler sur le bas pour toujours, en Fonction de votre nombre, il pourrait être l'une des deux choses. Votre nombre est important et il semble prendre une éternité à terminer, ou vous êtes arrondissement et de vos Vecteurs sont toujours 5 ou quelque chose. (90% de 5 à 4,5, de sorte qu'il peut arrondir à 5).
J'avais l'impression d'une instruction de débogage et de voir ce que le Vecteur de nombres sont comme. Si ils vont quelque part autour de 5 et juste rester là, alors vous pouvez utiliser une fonction qui tronque votre fraction à 4 au lieu de l'arrondissement de 5. Si elle continue à aller vers le bas et s'arrête finalement, alors vous pourriez avoir à élever votre coefficient de frottement.
Si vous ne pouvez pas trouver un moyen facile "arrondi" de la fonction, vous pouvez utiliser (0.9 * Vecteur) - 1, en soustrayant 1 à partir de votre équation devrait faire la même chose.
Lorsque les balles sont tous rouler sur le sol, oui, vérifier pour voir si la vitesse est en dessous d'une certaine valeur minimale et, le cas échéant, mettre zéro. Si vous regardez la physique qui se cache derrière ce type de idéalisée de mouvement et de comparer avec ce qui se passe dans le monde réel, vous verrez qu'une seule équation ne peut pas être utilisé pour tenir compte du fait qu'une balle réelle arrête de bouger.
BTW, ce que vous faites s'appelle de la méthode d'Euler pour l'intégration numérique. Il va comme ceci:
Commencer avec la cinématique équations du mouvement:
x(t) = x0 + vx*t + 0.5*axt^2
y(t) = y0 + vyt + 0.5*ayt^2
vx(t) = vx0 + axt
vy(t) = vy0 + ay*t
Où x et y sont la position, vx et vy sont la vitesse, ax et ay sont l'accélération, et t est le temps. x0, y0, vx0, et vy0 sont les valeurs initiales.
C'est ce qui décrit le mouvement d'un objet en l'absence de toute force extérieure.
Maintenant appliquer la gravité:
ay = -9.8 m/s^2
À ce stade, il n'y a pas besoin de faire quelque chose de délicat. Nous pouvons résoudre pour la position de chaque boule à l'aide de cette équation pour tout le temps.
Maintenant ajouter le frottement de l'air: Car c'est une bille sphérique, on peut supposer qu'il a un coefficient de frottement c. Il y a généralement deux choix quant à la façon de modéliser le frottement de l'air. Il peut être proportionnelle à la vitesse ou au carré de la vitesse. Nous allons utiliser le carré:
ax = -cvx^2
ay = -cvy^2 - 9.8
Parce que l'accélération est maintenant dépendante de la vitesse, qui n'est pas constant, nous nous devons d'intégrer. Ce qui est mauvais, car il n'y a aucun moyen de résoudre ce problème en main. Nous allons devoir intégrer numériquement.
//Enregistrer les valeurs précédentes
xold = x;
yold = y;
vxold = vx;
vyold = vy;
//Mise à jour de l'accélération
ax = -cvxold^2;
ay = -cvyold^2 - 9.8;
//Mise à jour vitesse
vx = vxold + axdt;
vy = vyold + aydt;
//Mise à jour de la position
x = xold + vxold*dt + 0.5*axdt^2;
y = yold + vyolddt + 0.5*ay*dt^2;
C'est une approximation, afin de ne pas être tout à fait correct, mais il va chercher OK. Le problème est que pour les grandes échéances, l'erreur augmente, donc si nous voulons modéliser avec précision le fonctionnement d'une vraie balle de se déplacer, nous devrions avoir à utiliser de très faibles valeurs de dt, ce qui causerait des problèmes avec précision sur un ordinateur. Pour le résoudre, il ya plus de techniques compliquées. Mais si vous voulez juste pour voir le comportement qui ressemble à la gravité et la friction dans le même temps, alors Euler la méthode est ok.
Chaque tranche de temps, vous devez appliquer les effets de la gravité par l'accélération de la balle dans le y à la baisse de la direction. Comme le projet de Loi K suggéré, c'est aussi simple que de faire une soustraction à partir de votre "yVector". Lorsque la balle touche le fond, yVector = -yVector, alors maintenant il se déplace vers le haut, mais encore qui accélère vers le bas. Si vous voulez faire les boules finit par cesser de rebondir, vous avez besoin de faire les collisions légèrement élastique, fondamentalement, par la suppression de la vitesse dans l'axe y de la direction, éventuellement par au lieu de "yVector = -yVector", faire "yVector = -0.9 * yVector".
dans checkCollisions(), vous devez inverser et multiplier yVector par un nombre compris entre 0 et 1 quand il rebondit sur le sol. Cela devrait vous donner l'effet désiré
C'est un mouvement balistique. Si vous avez un mouvement linéaire sur l'axe des x et un uniforme accéléré le mouvement sur l'axe des y.
L'idée de base est que l'axe des y suivra l'équation:
Ou, dans le code C, par exemple:
Où j'utilise ici tiem paramétrisation. Mais vous pouvez utiliser Torricelli:
Et, sur ce modèle, vous devez conserver les dernières valeurs de v et y.
Enfin, j'ai fait quelque chose de similaire en utilisant le premier modèle avec dt (temps de différentiel) étant fixé à 1/60 seconde (60 FPS).
Bien, les deux modèles donnent de bons réel des résultats semblables, mais sqrt(), par exemple, est cher.
Vous voulez vraiment pour simuler ce que la gravité n'est - il n'est de créer de la force qui agit sur le temps pour changer la vitesse d'un objet. Chaque fois que vous prenez une étape, vous pouvez changer la vitesse de votre balle un peu à l'ordre de "tirer" vers le bas du widget.
Afin de traiter avec le frottement /balle rebondissante s'installe problème, vous avez besoin de faire de la "terre" collision exercer un effet autre que juste le strict reflet - il doit enlever une certaine quantité d'énergie de la balle, la faisant rebondir sur une petite vitesse après qu'elle frappe le sol qu'elle serait autrement.
Une autre chose que vous devez généralement faire dans ces types de bouncy visualisations, c'est de donner au sol une partie latérale de frottement, de sorte que quand il frappe le sol tout le temps, elle finira par rouler à un arrêt.
Je suis d'accord avec ce "projet de Loi K", a déclaré, et tiens à ajouter que si vous les voulez pour "régler" vous aurez besoin de réduire les x et y des vecteurs au fil du temps (de la résistance). Ce devra être une très petite quantité à la fois, de sorte que vous pouvez avoir à modifier vos vecteurs de int à un type à virgule flottante, ou seulement de les réduire par 1 toutes les quelques secondes.
Ce que vous voulez faire est de changer les valeurs de xVector et yVector pour simuler la gravité et la friction. C'est vraiment assez simple à faire. (Besoin de changer l'ensemble de vos variables de flotteurs. Quand vient le temps de tirer, tout autour de la flotte.)
Dans votre démarche de fonction, après la mise à jour de la position de la balle, vous devez faire quelque chose comme ceci:
Cet échelles X et Y de la vitesse baisse légèrement, permettant à vos boules pour finalement s'arrêter de bouger, et applique ensuite une constante à la baisse "accélération" de la valeur de Y, qui va s'accumulent plus vite que le "ralentissement" et de provoquer les boules à l'automne.
C'est une approximation de ce que vous voulez vraiment faire. Ce que vous voulez vraiment est de garder un vecteur représentant l'accélération de vos boules. Chaque étape, vous serait alors produit scalaire que vecteur avec une gravité constante vecteur de modifier légèrement le ballon de l'accélération. Mais je pense que mon plus complexe que vous voulez obtenir, sauf si vous êtes à la recherche pour une vision plus réaliste de la physique de simulation.
Si l'on suppose une parfaite collision (c'est à dire toute l'énergie est conservée) tout ce que vous avez à faire inverser le signe de l'un de la vitesse scalaire en fonction de la paroi a été touché.
Par exemple, si la balle frappe la droite ou la gauche murs revese x composante scalaire et de laisser les y composante scalaire le même:
Si la balle touche le haut ou le bas des murs inverser l'axe composante scalaire et de laisser le x composante scalaire le même:
Dans ce scénario, une partie de l'énergie sera perdue lors de la collision avec le mur, donc juste ajouter un facteur de perte de prendre de quelques de la vitesse à chaque fois que le mur est touché: