Bonjour,
Je suis débutant en programmation Java. Je souhaite faire le jeux de la bouteille. Je me bloque sur un problème qui est le suivant. Quand je test mon programme sur mon pc la gestion de MotionEvent.ACTION_MOVE a l'aire à peux près satisfaisante. Cependant quand je test mon application sur mon Galaxy S4 je me rend compte que si je bouge mon doigt à une vitesse relativement moyenne je ne récupère plus la position en temps réel. Voici mon code. Savez vous pourquoi?

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
package com.example.bottle;
 
import com.example.bottle.R;
 
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
 
public class BottleView extends View 
{
 
    // Délais entre chaque image
    private final int DELAY = 20;
    // Durée de l'animation (ms)
    private final int DURATION = 1000;
 
    // Angle de départ de l'annimation
    private float startOrientation;
    // Angle de fin de l'annimation
    private float endOrientation;
    // Heure de début de l'animation (ms)
    private long startTime;
 
    // Image de la bouteille
    Bitmap mBitmap;
    private Paint bouteillePaint;
 
    // Position X et Y pour afficher l'image au milieux du canvas
    private float canvasCenterX;
    private float canvasCenterY;
 
    // Positions X et Y du centre de la bouteille utilisées pour le centre de rotation
    private int centerX;
    private int centerY;
 
    // Position de la nouvelle origine du repère cartésien qui sert à calculer l'angle de rotation
    private float newX, newY;
 
    // Angle représentant l'orientation de la bouteille;
    private float orientation=0;
    // Angle de rotation à effectuer
    private float angle=0;
 
    // Message avec des informations pour le debug
    private StatusMessage statusMsg;
 
    // Première position X et Y en fonction du repère de base (0,0) en haut à gauche
    private float firstX;
    private float firstY;
 
    // Position X et Y quand on bouge en fonction du repère de base (0,0) en haut à gauche
    private float curentX;
    private float curentY;
 
    // Dernière position X et Y en fonction du repère de base (0,0) en haut à gauche
    private float lastX;
    private float lastY;
 
 
 
    //~--- constructors -------------------------------------------------------
    public BottleView( Context context ) 
    {
        super( context );
        // Couleur des infos de débug
        statusMsg = new StatusMessage( Color.RED );
        // Chargement du BitMap original (149 x 528 px)
        mBitmap = BitmapFactory.decodeResource( getResources(), R.drawable.bouteille );
        // Activation keypad
    	this.setFocusable( true );
        this.requestFocus();
        // Activation du touch mode
        this.setFocusableInTouchMode( true );
        // Initialisation de la vue
        initView();
    }
 
    // Constructeur utilisé pour instancier la vue depuis sa
    // déclaration dans un fichier XML
    public BottleView( Context context, AttributeSet attrs ) 
    {
        super( context, attrs );
        // Couleur des infos de débug
        statusMsg = new StatusMessage( Color.RED );
        // Chargement du BitMap original (149 x 528 px)
        mBitmap = BitmapFactory.decodeResource( getResources(), R.drawable.bouteille );
        // Activation keypad
    	this.setFocusable( true );
        this.requestFocus();
        // Activation du touch mode
        this.setFocusableInTouchMode( true );
        // Initialisation de la vue
        initView();
    }
 
    //~--- get methods --------------------------------------------------------
 
    // permet de récupérer l'orientation de la bouteille
    public float getOrientation() 
    {
        return orientation;
    }
 
    //~--- set methods --------------------------------------------------------  
 
    // permet de changer l'orientation de la boussole
    public void setOrientation( float rotation ) 
    {
        // on met à jour l'orientation uniquement si elle a changé
        if ( rotation != this.orientation ) 
        {
          // Arrêter l'ancienne animation
            removeCallbacks(animationTask);
        	// Position courante
            this.startOrientation = this.orientation;
            // Position désirée
            this.endOrientation = rotation;
 
            // Détermination du sens de rotation de la bouteille
            if ( ( ( startOrientation + 180 ) % 360 ) > endOrientation )
            {
            	// Rotation vers la gauche
            	if ( ( startOrientation - endOrientation ) > 180 )
            	{
            		endOrientation += 360;
            	}
            } 
            else 
            {
            	// Rotation vers la droite
            	if ( ( endOrientation - startOrientation ) > 180 )
            	{
            		startOrientation += 360;
            	}
            }
 
            //Nouvelle animation
            startTime = SystemClock.uptimeMillis();
            postDelayed( animationTask, DELAY );
        }
    }
 
    //~--- methods ------------------------------------------------------------
 
    // Définir la taille de la vue
    @Override
    protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec ) 
    {
    	int measuredWidth  = measure( widthMeasureSpec );
    	int measuredHeight = measure( heightMeasureSpec );
    	setMeasuredDimension( measuredWidth, measuredHeight );
    }
 
    // Déterminer la taille de notre vue
	private int measure( int measureSpec ) 
	{
		int result   = 0;
	    int specMode = MeasureSpec.getMode( measureSpec );
	    int specSize = MeasureSpec.getSize( measureSpec );
 
	    if ( specMode == MeasureSpec.UNSPECIFIED ) 
	    {
	    	// Le parent ne nous a pas donné d'indications,
	    	// on fixe donc une taille
	    	result = 150;
	    } 
	    else 
	    {
	    	// On va prendre la taille de la vue parente
	    	result = specSize;
	    }
 
	    return result;
	}
 
	// Initialise les pinceaux
	private void initView() 
	{
		bouteillePaint = new Paint();
	}
 
	// Appelée pour redessiner la vue
	@Override
	protected void onDraw( Canvas canvas ) 
	{
		// On détermine le centre de lécran
		canvasCenterX = ( canvas.getWidth() - mBitmap.getWidth() ) / 2;
		canvasCenterY = ( canvas.getHeight() - mBitmap.getHeight() ) / 2;
 
		//On détermine le point au centre de notre image (bouteille)
		centerX = (int) ( canvasCenterX + ( mBitmap.getWidth() / 2 ) );
		centerY = (int) ( canvasCenterY + ( mBitmap.getHeight() / 2 ) );
 
		// On sauvegarde la position initiale du canevas
		canvas.save();
 
		// On tourne le canevas pour que la bouteille pointe vers le haut
		canvas.rotate( orientation, centerX, centerY);
		// On dessine la bouteille au centre du canvas
		canvas.drawBitmap( mBitmap, canvasCenterX, canvasCenterY, bouteillePaint );
 
		// On restaure la position initiale (inutile ici mais prévoyant)
		canvas.restore();
 
		// MAJ des inforamtions de débug
		statusMsg.update( curentX, curentY, newX, newY, angle );
		// Affichage des informations de débug
		statusMsg.draw( canvas );
	}
 
	// Gestion de l'annimation de rotation de la bouteille
	private Runnable animationTask = new Runnable() 
	{
	    public void run() 
	    {
	        long curTime   = SystemClock.uptimeMillis();	// Temps courant
	        long totalTime = curTime - startTime;			// Temps passé
 
	        if ( totalTime > DURATION )	// Si le temps écoulé est superrieur à la limite maximale
	        {
	            // Fin de l'animation
	            orientation = endOrientation;
	            removeCallbacks( animationTask );
	        } 
	        else 
	        {
	            //Changer la position de la bouteille
	        	float perCent = ( (float) totalTime ) / DURATION; // Pourcentatge de l'avancement de l'annimation
	            // Animation plus réaliste de la bouteille (accélération au début et décélération à la fin)
	            perCent = (float) Math.sin( perCent * 1.5 );
	            //On s'assure qu'on ne dépassera pas 1
	            perCent = Math.min( perCent, 1 );
	            //On determine la nouvelle orientation de la bouteille
	            orientation = (float) ( startOrientation + ( perCent * ( endOrientation - startOrientation ) ) );
	            //Rappeler cette tâche dans DELAY ms pour dessiner la suite
	            postDelayed(this, DELAY);
	        }
	        // Quoi qu'il arrive, on demande à la vue de se redessiner
	        optimizedInvalidate();
	    }
	};
 
	// Touch-input handler
	@Override
	public boolean onTouchEvent(MotionEvent event) 
	{ 
		switch ( event.getAction() ) 
		{
			case MotionEvent.ACTION_DOWN:
   				firstX = event.getX();
   				firstY = event.getY();
   			case MotionEvent.ACTION_MOVE:
   				curentX = event.getX();
   				curentY = event.getY();
   				this.setOrientation( mesureRotation( curentX, curentY ) );
   				break;
   			case MotionEvent.ACTION_UP:
   				lastX = event.getX();
   				lastY = event.getY();
   				this.setOrientation( mesureRotation( lastX, lastY ) );
   				return true;
		}
 
		return true;  // Event handled
	}
 
	// Mesure l'angle de rotation
	public float mesureRotation( float x, float y )
	{
		float adjacent, hypotenuse;
 
		// On change le repère pour s'adapter au centre de rotation.
		newX = x - centerX;
		newY = centerY - y;
		// Mesure du coté adjacent
		adjacent = newY;
		// Mesure de l'hypotenuse
		hypotenuse = (float) Math.sqrt( Math.pow( newX, 2 ) + Math.pow( newY, 2 ) );
		// On calcule l'angle
		if( newX >= 0 )
		{
			angle = (float) ( Math.acos( adjacent / hypotenuse ) * 57.3 ); // conversion des radiants en degré.
		}
		else
		{
			angle = (float) ( Math.acos( -adjacent / hypotenuse ) * 57.3 ) + 180; // conversion des radiants en degré.
		}
 
		return angle;
	}
 
	// Optimisation de Invalidate()
	private void optimizedInvalidate()
	{   
		final int mBitmapHeight = mBitmap.getHeight();
	    //On trouve les coordonnées du point supérieur gauche de la zone à invalider
	    final int x1 = centerX - ( mBitmapHeight / 2 );
	    final int y1 = centerY - ( mBitmapHeight / 2 );
	    // On trouve les coordonnées du point inférieur droit de la zone à
	    final int x2 = centerX + ( mBitmapHeight / 2 );
	    final int y2 = centerY + ( mBitmapHeight / 2 );
	    //Invalide la vue en utilisant invalidate(int, int, int, int)
	    //invalidate(x1, y1, x2, y2);
	    invalidate(); //debug
	}
}