/*
* Bille.java
*/
package labyrinthe.composants;
import android.app.Activity;
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.Toast;
import labyrinthe.jeu.VueParcours;
import labyrinthe.metier.Impact;
import labyrinthe.metier.Mouvement;
import labyrinthe.outils.Cercle;
import labyrinthe.outils.Coordonnee;
/**
* Une bille prsente dans un labyrinthe a des caracteristiques telles que une
* masse, un coefficient de frottement, un diametre
*
* @author melanie.marc
*
*/
public class Bille extends AbstractElement {
private static final long serialVersionUID = 3571862602603352424L;
/**
* masse par dfaut appliquer a la bille
*/
public static final Double MASSE_DEF = 1000.0;
/**
* coefficient de frottement par dfaut de la bille
*/
public static final Double COEFF_FROTTEMENT_DEF = 0.1;
/**
* diametre par dfaut de la bille
*/
public static final int DIAMETRE_DEF = 25;
/**
* masse de la bille en grammes
*/
private Double masse;
/**
* coefficient de frottement
*/
private Double coeffFrottement;
/**
* diametre de la bille
*/
private int diametre;
/**
* private Double mLastPosX; private Double mLastPosY;
*/
private Coordonnee lastPosition;
/**
* private Double mAccelX; private Double mAccelY;
*/
private Coordonnee positionAccelerometre;
/**
* TODO commenter le role frottement
*/
private Double mOneMinusFriction;
/**
* taille horizontale de l'ecran
*/
//private Double mHorizontalBound;
/**
* taille verticale de l'ecran
*/
//private Double mVerticalBound;
/**
* timestamp lors de l'appel la mthode update position
*/
private long mLastT;
/**
* ecart de temps precedent
*/
private float mLastDeltaT;
/**
* Initialise une bille par dfaut
*/
public Bille() {
super(POSITION_DEF);
this.masse = MASSE_DEF;
this.coeffFrottement = COEFF_FROTTEMENT_DEF;
this.diametre = DIAMETRE_DEF;
// coefficient of friction
final Double r = ((Double) Math.random() - 0.5f) * 0.2f;
mOneMinusFriction = 1.0f - coeffFrottement + r;
mLastDeltaT = 0.0f;
mLastT = 0;
this.lastPosition = this.getPosition();
this.positionAccelerometre = this.getPosition();
}
/**
* Cration de la bille une position de donne
*
* @param coordonnee
*/
public Bille(Coordonnee coordonnee) {
super(coordonnee);
this.masse = MASSE_DEF;
this.coeffFrottement = COEFF_FROTTEMENT_DEF;
this.diametre = DIAMETRE_DEF;
// coefficient of friction
final Double r = ((Double) Math.random() - 0.5f) * 0.2f;
mOneMinusFriction = 1.0f - coeffFrottement + r;
mLastDeltaT = 0.0f;
mLastT = 0;
this.lastPosition = this.getPosition();
this.positionAccelerometre = this.getPosition();
}
/**
* met a jour la nouvelle position de la bille et celle de l'accelerometre
*
* @param coord
* @param dT
* @param dTC
*/
public void computePhysics(Coordonnee coord, float dT, float dTC) {
//System.out.println("Bille.computePhysics() entree dans methode");
// gravit
final Double gx = -coord.getX() * masse;
final Double gy = -coord.getY() * masse;
//System.out.println("Bille.computePhysics() gravite = "+gx+","+gy);
/*
* F = mA <=> A = F / m We could simplify the code by completely
* eliminating "m" (the mass) from all the equations, but it would hide
* the concepts from this sample code.
*/
final Double invm = 1.0 / masse;
final Double ax = gx * invm;
final Double ay = gy * invm;
//System.out.println("Bille.computePhysics() accelero = "+ax+","+ay);
/*
* Time-corrected Verlet integration The position Verlet integrator is
* defined as x(t+t) = x(t) + x(t) - x(t-t) + a(t)t2 However, the
* above equation doesn't handle variable t very well, a time-corrected
* version is needed: x(t+t) = x(t) + (x(t) - x(t-t)) * (t/t_prev) +
* a(t)t2 We also add a simple friction term (f) to the equation:
* x(t+t) = x(t) + (1-f) * (x(t) - x(t-t)) * (t/t_prev) + a(t)t2
*/
final float dTdT = dT * dT;
double accelerationX = positionAccelerometre.getX() * dTdT;
double accelerationY = positionAccelerometre.getY() * dTdT;
double deplacementX =(mOneMinusFriction * dTC
* (this.getPosition().getX() - this.lastPosition.getX())
+ accelerationX);
double deplacementY = (mOneMinusFriction * dTC
* (this.getPosition().getY() - this.lastPosition.getY())
+ accelerationY);
//limitation de la vitesse de la bille
double vitesse = 13.0;
if(Math.abs(deplacementX)>vitesse){
deplacementX = Math.signum(deplacementX)*vitesse;
}
if(Math.abs(deplacementY)>vitesse){
deplacementY = Math.signum(deplacementY)*vitesse;
}
// determiner la nouvelle position de la bille
final Double x = this.getPosition().getX() + deplacementX;
final Double y = this.getPosition().getY() + deplacementY;
//System.out.println("Bille.computePhysics() nouvelle position = "+x+","+y);
// modifier lastPosition de la bille
this.lastPosition = new Coordonnee(this.getPosition().getX(), this
.getPosition().getY(), 1);
// modifier position courante de la bille
this.setPosition(new Coordonnee(x, y, 1));
// modifier position accelerometre
this.positionAccelerometre = new Coordonnee(ax, ay, 1);
//System.out.println("Bille.computePhysics() ancienne coord = "+this.lastPosition);
//System.out.println("Bille.computePhysics() coord accelerometre = "+this.positionAccelerometre);
//System.out.println("Bille.computePhysics() nouvelle coord = "+this.getPosition());
}
/**
* gestion des collisions entre this et le bord de l'ecran
*/
public void resolveCollisionWithBounds(Activity act) {
// TODO gerer la taille de l'ecran differement
Coordonnee ecran = new Coordonnee(act.getWindowManager().getDefaultDisplay().getWidth(),
act.getWindowManager().getDefaultDisplay().getHeight(),
1);
final Double xmax = ecran.getX();
final Double ymax = ecran.getY();
final Double x = this.getPosition().getX();
final Double y = this.getPosition().getY();
// variable tampon permettant de stocker la nouvelle position de la
// bille
// apres collision avec un bord de l'ecran
Double tempx, tempy;
tempx = x;
tempy = y;
// TODO si on touche un bord effectuer un rebond
if (x > xmax-this.getDiametre()/2) {
tempx = xmax-this.getDiametre()/2;
} else if (x < 0+this.getDiametre()/2) {
tempx = 0.0+this.getDiametre()/2;
}
if (y > ymax-this.getDiametre()/2) {
tempy = ymax-this.getDiametre()/2;
} else if (y < 0+this.getDiametre()/2) {
tempy = 0.0+this.getDiametre()/2;
}
// nouvelle position de la bille
this.setPosition(new Coordonnee(tempx, tempy, 1));
}
/**
* mise a jour de la position de la bille Update the position of each
* particle in the system using the Verlet integrator.
* @param vue
*/
private void updatePositions(Coordonnee coord, long timestamp) {
//System.out.println("Bille.updatePositions() ");
final long t = timestamp;
if (mLastT != 0) {
final float dT = (float) ((t - mLastT) * (1.0f / 100000000.0f));
if (mLastDeltaT != 0.0) {
final float dTC = dT / mLastDeltaT;
// dplacement de la bille
this.computePhysics(coord, dT, dTC);
}
mLastDeltaT = dT;
}
mLastT = t;
}
/**
*
* Performs one iteration of the simulation. First updating the position of
* all the particles and resolving the constraints and collisions.
*/
public void update(Coordonnee coord, long now, VueParcours vue) {
//System.out.println("Bille.update()");
// mise a jour des valeurs de temps et de la position de la bille
updatePositions(coord, now);
// tester les collisions entre les bords de l'ecran et la bille
this.resolveCollisionWithBounds((Activity)vue.getContext());
// tester les collisions entre la bille et les elements
Mouvement m = new Mouvement(this,vue);
// contient point d'impact avec object impact
Impact im = m.detectionColision();
// on vrifie s'il y a eu un impact
if (im != null) {
System.err.println("========Colision : "+im.getPoint());
m.reactionColision(im);
System.err.println("accelero"+positionAccelerometre.toString());
}
}
@Override
public void actionCollision() {
// TODO Auto-generated method stub
}
/**
* retourne le diametre de la bille
*
* @return le diametre de la bille
*/
public int getDiametre() {
return diametre;
}
/**
* Permet d'accder au cercle de la bille et ses paramtre
*
* @return une instance du cercle dfini par la bille
*/
public Cercle getCercle() {
return new Cercle(getPosition(), getDiametre());
}
/**
* Accsseur la masse de la bille
*
* @return la masse de la bille
*/
public Double getMasse() {
return masse;
}
/**
* Accsseur au coefficient de frottement de la bille
*
* @return le coeff de frottement de la bille
*/
public Double getCoeffFrottement() {
return coeffFrottement;
}
@Override
public String toString() {
return super.toString() + " masse : " + masse + " diametre : "
+ diametre + " frottement : " + coeffFrottement;
}
/**
* Accesseur la position precedente de la bille
* @return precedente coordonne de la bille
*/
public Coordonnee getLastPosition() {
return lastPosition;
}
/**
* Permet de redefinir les anciene coordonne de la bille
* ce qui est utile lors de changement de trajectoire dut un rebond
* @param lastPosition
*/
public void setLastPosition(Coordonnee lastPosition) {
this.lastPosition = lastPosition;
}
}
|