2016-02-05 2 views
0

Je suis en train de développer le premier jeu Android en 2d. J'ai l'intention de le construire à partir de zéro sans l'utilisation d'un moteur. J'ai réussi à créer le fil suivant:Android studio 2d jeu fps numéro

import android.graphics.Canvas; 
import android.view.SurfaceHolder; 


public class MainThread extends Thread { 
private int FPS = 30; 
private double averageFPS; 
private GamePanel gamePanel; 
private SurfaceHolder surfaceHolder; 
private boolean running; 
public static Canvas canvas; 

public MainThread(SurfaceHolder surfaceHolder, GamePanel gamePanel) { 
    super(); 
    this.surfaceHolder = surfaceHolder; 
    this.gamePanel = gamePanel; 
} 


@Override 
public void run() { 
    long startTime; 
    long timeMillis; 
    long waitTime; 
    long totalTime = 0; 
    int frameCount = 0; 
    // how many milliseconds it take to run through the loop 
    long targetTime = 1000/FPS; 

    while (running) { 
     startTime = System.nanoTime(); 
     canvas = null; 

     // try to lock the canvas for pixel editing 
     try { 
      canvas = this.surfaceHolder.lockCanvas(); 
      synchronized (surfaceHolder) { 
       // the main game loop 
       this.gamePanel.update(); 
       this.gamePanel.draw(canvas); 

      } 
     } catch (Exception e) { 
     } finally { 
      if (canvas != null) { 
       try { 
        surfaceHolder.unlockCanvasAndPost(canvas); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     } 

     timeMillis = (System.nanoTime() - startTime)/1000000; 
     waitTime = targetTime - timeMillis; 

     try { 
      System.out.println(waitTime); 
      this.sleep(waitTime); 
     } catch (Exception e) { 
     } 

     totalTime += System.nanoTime() - startTime; 
     frameCount++; 

     if (frameCount == FPS) { 
      averageFPS = 1000/((totalTime/frameCount)/1000000); 
      frameCount = 0; 
      totalTime = 0; 
      System.out.println(averageFPS); 
     } 
    } 
} 

Le problème que j'ai est que le averageFPS continue tomber lors de l'ajout de choses à mon jeu. Avec seulement l'arrière-plan, il fonctionne à 30 sur mon Nexus 5 mais en ajoutant du caractère et des obstacles, il tombe à 22-21. Y a-t-il un moyen de l'optimiser?

Merci

MISE À JOUR: mon GamePanel ressemble à ceci:

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.graphics.Rect; 
import android.graphics.Typeface; 
import android.view.MotionEvent; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 

import java.util.ArrayList; 
import java.util.Random; 


public class GamePanel extends SurfaceView implements SurfaceHolder.Callback  { 

public static final int WIDTH = 1920; 
public static final int HEIGHT = 1080; 
public static float MOVESPEED = -12; 

private Random rand = new Random(); 

private MainThread thread; 
private Background bg; 
private Treadmill tm; 
private Player player; 

private ArrayList<Box> boxes; 

private int minDistance = 600; 
private int score; 

public GamePanel(Context context) { 
    super(context); 

    // add callback service to the holder to intercept events 
    getHolder().addCallback(this); 


    // make gamePanel focusable so it can handle events 
    setFocusable(true); 
} 


@Override 
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 

} 

@Override 
public void surfaceDestroyed(SurfaceHolder holder) { 
    boolean retry = true; 
    while (retry) { 
     try { 
      thread.setRunning(false); 
      thread.join(); 
      retry = false; 
      thread = null; 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 

    } 
} 

@Override 
public void surfaceCreated(SurfaceHolder holder) { 
    // instantiate objects 
    thread = new MainThread(getHolder(), this); 
    bg = new Background(BitmapFactory.decodeResource(getResources(), R.drawable.background)); 
    tm = new Treadmill(BitmapFactory.decodeResource(getResources(), R.drawable.ground)); 
    player = new Player(BitmapFactory.decodeResource(getResources(), R.drawable.character)); 

    boxes = new ArrayList<Box>(); 


    //start game loop 
    thread.setRunning(true); 
    thread.start(); 
} 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    if (event.getAction() == MotionEvent.ACTION_DOWN) { 

     if (player.jump == false) { 
      player.setVelocity(-14f); 
      player.setJump(true); 
     } 
     return true; 
    } 

    return super.onTouchEvent(event); 

} 

public void update() { 

    bg.update(); 
    tm.update(); 
    player.update(); 

    if (boxes.size() == 0) { 
     boxes.add(new Box(BitmapFactory.decodeResource(getResources(), R.drawable.box), 
       WIDTH)); 
    } else if (boxes.get(boxes.size() - 1).getX() < WIDTH) { 
     if (WIDTH - boxes.get(boxes.size() - 1).getX() < minDistance) { 
      boxes.add(new Box(BitmapFactory.decodeResource(getResources(), R.drawable.box), 
        rand.nextInt(400 - 50) + WIDTH + minDistance)); 

     } 
    } 

    for (int i = 0; i < boxes.size(); i++) { 
     if (boxes.get(i).getX() <= player.getX() && boxes.get(i).getX() >= player.getX() - 12) { 
      score++; 
      MOVESPEED -= 0.2; 
      System.out.println(MOVESPEED); 
     } 
     if (collision(boxes.get(i), player)) { 
      boxes.remove(i); 
      break; 
     } 

     if (boxes.get(i).getX() < -100) { 
      boxes.remove(i); 
      break; 
     } 

    } 
    for (int i = 0; i < boxes.size(); i++) { 
     boxes.get(i).update(); 
    } 

} 

@Override 
public void draw(Canvas canvas) { 
    final float scaleFactorX = getWidth()/(WIDTH * 1.f); 
    final float scaleFactorY = getHeight()/(HEIGHT * 1.f); 

    if (canvas != null) { 
     final int saveState = canvas.save(); 

     canvas.scale(scaleFactorX, scaleFactorY); 
     // draw the background 
     bg.draw(canvas); 

     tm.draw(canvas); 

     player.draw(canvas); 

     for (Box bx : boxes) { 
      bx.draw(canvas); 
     } 

     drawText(canvas); 
     canvas.restoreToCount(saveState); 
    } 
} 

public boolean collision(GameObject a, GameObject b) { 
    if (Rect.intersects(a.getRectangle(), b.getRectangle())) { 
     return true; 
    } 
    return false; 
} 

public void drawText(Canvas canvas) { 
    Paint paint = new Paint(); 
    paint.setColor(Color.BLACK); 
    paint.setTextSize(50); 
    paint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); 
    canvas.drawText("Score: " + (score), 15, HEIGHT - 20, paint); 
} 

Merci pour toute l'aide jusqu'à

+0

Avez-vous vu les anciennes vidéos Google IO sur Writing Real Time Games pour Android (https://youtu.be/U4Bk5rmIpic et https://youtu.be/7-62tRHLcHk) –

Répondre

0

Le problème ne semble pas être dans l'activité de thread principal , vous avez bien suivi le tutoriel (sauf pour la ligne - System.out.println (waitTime); - mais je ne pense pas que ce soit le problème.) Le problème est le plus probable dans le GamePanel. ;)

+0

Peut-être plus spécifique? –

+0

Non. Je ne sais pas à quoi ressemble son activité GamePanel. – Thenewguy

+0

J'ai ajouté le panneau de jeu. J'ai très bien travaillé dans le tutoriel, mais sur mon application, il traîne. Le problème peut-il être la taille des images? Je les ai fait à la résolution 480p et 1080p mais la taille réelle des images est petite autour de 20kb. – Dany

0

Ne jamais utiliser Thread.sleep() dans les boucles de jeu. Il n'est pas garanti de dormir pendant la durée spécifiée.

Quoi qu'il en soit, je pense que c'est un comportement assez attendu lors de l'utilisation de Canvas. Si j'étais vous je considérerais utiliser OpenGL ES pour quelque chose comme le rendu graphique. Certainement, cela le rend beaucoup plus complexe (même si Android a déjà fait beaucoup de choses pour vous). Mais l'avantage est évident: vous obtenez des performances graphiques en temps réel.