Pour une expériencenet et une sécurité optimale, mettez à jour votre navigateur. Mettre à jour maintenant
package com.creativegames; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Paint; import android.graphics.drawable.BitmapDrawable; import android.view.MotionEvent; public class GameLoop extends Thread { /** Variable booléenne pour arrêter le jeu */ public boolean running; /** durée de la pause entre chaque frame (FPS=10) */ private long sleepTime = 100; /** Ecran de jeu */ public GameView screen; /** le dernier évenement enregistré */ public MotionEvent lastEvent; /** Personnage animé */ private Sprite mario; /** Valeur du FPS (nombre de frames par secondes) */ private int fps; public void initGame(Context context) { // créer la vue du jeu this.screen = new GameView(context, this); Bitmap img = ((BitmapDrawable) context.getResources().getDrawable( R.drawable.bad1)).getBitmap(); // créer un sprite en spécifiant la position et la vitesse puis l'écran mario = new Sprite(img, 0, 0, 2, 3, screen); running = true; } /** * Ici on va faire en sorte que lorsqu'on clique sur l'écran, le sprite va * se rendre à la position cliquée * */ public void processEvents() { if (lastEvent != null && lastEvent.getAction() == MotionEvent.ACTION_DOWN) { int xTouch = (int)lastEvent.getX(); int yTouch = (int)lastEvent.getY(); mario.moveTo(xTouch, yTouch); } lastEvent = null; } /** * Mise à jour des composants du jeu Ici nous déplaçon le personnage avec la * vitesse vx S'il sort de l'écran, on le fait changer de direction * */ public void update() { mario.update(); } /** Dessiner les composant du jeu sur le buffer de l'écran */ public void render() { Paint paint = new Paint(); // effacer l'écran avec la couleur verte paint.setColor(0xFF008000); this.screen.canvas.drawPaint(paint); // dessiner le sprite this.mario.render(screen.canvas); // ecrire le fps paint.setColor(0xFFFFFFFF); this.screen.canvas.drawText("FPS : " + fps, 10, 10, paint); // appliquer le buffer à l'écran this.screen.invalidate(); } @Override public void run() { long startTime; long elapsedTime; // durée de (update()+render()) long sleepCorrected; // sleeptime corrigé while (this.running) { startTime = System.currentTimeMillis(); this.processEvents(); this.update(); this.render(); elapsedTime = System.currentTimeMillis() - startTime; sleepCorrected = sleepTime - elapsedTime; // si jamais sleepCorrected<0 alors faire une pause de 1 ms if (sleepCorrected < 0) { sleepCorrected = 1; } try { Thread.sleep(sleepCorrected > 0 ? sleepCorrected : 1); } catch (InterruptedException e) { } // calculer le FSP fps = (int) (1000/(System.currentTimeMillis() - startTime)); } } }
private int getAnimationRow() { // animation: 3 back, 1 left, 0 front, 2 right if (Math.abs(xSpeed) > Math.abs(ySpeed)) { if (xSpeed > 0) return 2; //right else return 1; //left } else { if(ySpeed>0) return 0; //down else return 3; //up } }
public void render(Canvas canvas) { int srcX = currentFrame * width; int srcY = getAnimationRow() * height; Rect src = new Rect(srcX, srcY, srcX + width, srcY + height); Rect dst = new Rect(x, y, x + width, y + height); canvas.drawBitmap(image, src, dst, null); }Enfin le code source intégral de la classe Sprite
package com.creativegames; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Rect; public class Sprite { private static final int BMP_ROWS = 4; private static final int BMP_COLUMNS = 3; private GameView gameView; private Bitmap image; private int x; private int y; private int xSpeed; private int ySpeed; /** numéro de la frame courante */ private int currentFrame; /** dimension du sprite */ private int width; private int height; public Sprite(Bitmap bmp, int x, int y, int vx, int vy, GameView gameView) { this.width = bmp.getWidth() / BMP_COLUMNS; this.height = bmp.getHeight() / BMP_ROWS; this.gameView = gameView; this.image = bmp; this.x = x; this.y = y; this.xSpeed = vx; this.ySpeed = vy; } public void update() { if (x >= gameView.getWidth() - width - xSpeed || x + xSpeed <= 0) { xSpeed = -xSpeed; } x = x + xSpeed; if (y >= gameView.getHeight() - height - ySpeed || y + ySpeed <= 0) { ySpeed = -ySpeed; } y = y + ySpeed; currentFrame = (currentFrame + 1) % BMP_COLUMNS; } private int getAnimationRow() { // animation: 3 back, 1 left, 0 front, 2 right if (Math.abs(xSpeed) > Math.abs(ySpeed)) { if (xSpeed > 0) return 2; //right else return 1; //left } else { if(ySpeed>0) return 0; //down else return 3; //up } } public void render(Canvas canvas) { int srcX = currentFrame * width; int srcY = getAnimationRow() * height; Rect src = new Rect(srcX, srcY, srcX + width, srcY + height); Rect dst = new Rect(x, y, x + width, y + height); canvas.drawBitmap(image, src, dst, null); } /** déterminer la vitesse vers le point cliqué */ public void moveTo(int x2, int y2) { int dx = x2-this.x; int dy = y2-this.y; double r = Math.sqrt(dx*dx+dy*dy); xSpeed = (int) (3*dx/r); ySpeed = (int) (3*dy/r); } }Inconvénients de cette méthode !
package com.creativegames; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Bitmap.Config; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; public class GameView extends SurfaceView implements Callback{ public int width; //largeur de l'écran public int height; //hauteur de l'écran public Canvas canvas; //outil pour dessiner sur l'écran private Bitmap buffer; // pixel buffer private SurfaceHolder holder; private GameLoop game; //pointeur vers la boucle de jeu public GameView(Context context, GameLoop game) { super(context); this.holder = getHolder(); this.holder.addCallback(this); this.game = game; } /** Rafraichir l'écran*/ @Override public void invalidate() { if (holder != null) { Canvas c = holder.lockCanvas(); if (c != null) { c.drawBitmap(buffer, 0, 0, null); holder.unlockCanvasAndPost(c); } } } /**callback lorsque l'écran est touché * on stocke l'événement pour être ensuite traité dans la boucle de jeu*/ @Override public boolean onTouchEvent(MotionEvent event) { this.game.lastEvent = event; return true; } /** callback lorsque la surface est chargée, * donc démarrer la boucle de jeu*/ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { this.width = width; this.height = height; this.buffer = Bitmap.createBitmap(width, height, Config.ARGB_8888); this.canvas = new Canvas(buffer); this.game.start(); } public void surfaceCreated(SurfaceHolder holder) { } public void surfaceDestroyed(SurfaceHolder holder) { } }
package com.creativegames; import com.creativegame.R; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Paint; import android.graphics.drawable.BitmapDrawable; import android.view.MotionEvent; public class GameLoop extends Thread { /** Variable booléenne pour arrêter le jeu */ public boolean running; /** * durée de la pause entre chaque frame * du jeu pour frame per second FPS=10 * on a sleepTime=100 */ private long sleepTime = 100; /** Ecran de jeu */ public GameView screen; /** le dernier évenement enregistré sur l'écran*/ public MotionEvent lastEvent; /** Position de l'image que nous dessions sur l'écran */ private int x, y; /** vitesse de l'image : nombre de pixel parcouru à chaque boucle de jeu */ private int vx; /** image que nous allons dessiner */ private Bitmap img; /** contexte de l'application */ private Context context; /** activer ou désactiver l'animation*/ private boolean animate; public void initGame(Context context) { this.context = context; img = ((BitmapDrawable) context.getResources().getDrawable( R.drawable.ic_launcher)).getBitmap(); x = 0; y = 10; vx = 2; animate = true; running = true; this.screen = new GameView(context, this); } /** la boucle de jeu */ @Override public void run() { while (this.running) { this.processEvents(); this.update(); this.render(); try { Thread.sleep(sleepTime); } catch (InterruptedException e) { } } } /** Dessiner les composant du jeu sur le buffer de l'écran*/ public void render() { Paint paint = new Paint(); paint.setColor(0xFF000000); //effacer l'écran avec la couleur noire this.screen.canvas.drawPaint(paint); this.screen.canvas.drawBitmap(img, x, y, null); this.screen.invalidate(); } /** Mise à jour des composants du jeu * Ici nous déplaçon le personnage avec la vitesse vx * S'il sort de l'écran, on le fait changer de direction * */ public void update() { if(this.animate==false) return; int oldX = x; x = x + vx; if (x < 0 || x > screen.width - img.getWidth()) { x = oldX; vx = -vx; } } /** Ici on va faire en sorte que lorsqu'on clique sur l'écran, * L'animation s'arrête/redémarre * */ public void processEvents() { if (lastEvent != null && lastEvent.getAction() == MotionEvent.ACTION_DOWN) { this.animate = ! this.animate; } lastEvent = null; } }
package com.creativegames; import android.app.Activity; import android.os.Bundle; public class Main extends Activity { private GameLoop game; /** A la création de l'activité * 1. on initialise le jeu et affecter la vue à l'activité * */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); game = new GameLoop(); game.initGame(this); setContentView(game.screen); } /** Lorsque l'application s'arrête, il faut arrêter proprement la boucle de jeu*/ @Override protected void onDestroy() { game.running = false; super.onDestroy(); } }Voici me résultat de l'exécution du code: une image qui se déplace en va et vient dans l'écran, cadencé par le sleepTime. Au clic, l'animation s'arrête/redémarre.
@Override public void run() { long startTime; long elapsedTime; // durée de (update()+render()) long sleepCorrected; // sleeptime corrigé while (this.running) { startTime = System.currentTimeMillis(); this.processEvents(); this.update(); this.render(); elapsedTime = System.currentTimeMillis() - startTime; sleepCorrected = sleepTime - elapsedTime; // si jamais sleepCorrected<0 alors faire une pause de 1 ms if (sleepCorrected < 0) { sleepCorrected = 1; } try { Thread.sleep(sleepCorrected > 0 ? sleepCorrected : 1); } catch (InterruptedException e) { } // calculer le FSP fps = (int) (1000/(System.currentTimeMillis() - startTime)); } }