2016-02-05 87 views
0

我想要开发可能在2d的第一个android游戏。我打算从头开始构建而不使用引擎。我已经设法创建以下线程:Android studio 2d游戏fps问题

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); 
     } 
    } 
} 

我遇到的问题是,当向我的游戏添加东西时,averageFPS一直在下降。只有背景,它在我的Nexus 5上可以工作在30,但是在增加角色和障碍后,它会下降到22-21。 无论如何,我可以做到这一点来优化吗?

谢谢

UPDATE:我的GamePanel看起来是这样的:

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); 
} 

谢谢所有帮助到目前为止

+0

您是否在Android上编写实时游戏(https://youtu.be/U4Bk5rmIpic和https://youtu.be/7-62tRHLcHk) –

回答

0

似乎问题并不在主线程活动,你遵循教程罚款(除了行 - System.out.println(waitTime); - 但我不认为这是问题的原因。) 问题很可能在GamePanel。 ;)

+0

可以更具体地看到旧的Google IO视频? –

+0

不是。我不知道他的GamePanel活动是什么样子。 – Thenewguy

+0

我已经添加了游戏面板。我在教程中工作得很好,但在我的应用程序滞后。问题可以是图像的大小吗?我以480p和1080p分辨率制作了它们,但实际尺寸大约为20kb。 – Dany

0

永远不要在游戏循环中使用Thread.sleep()。不保证在指定的时间内睡眠。

无论如何,我认为这是使用Canvas时非常期待的行为。如果我是你,我会考虑使用OpenGL ES进行图形渲染等任何操作。当然,这使得它更加复杂(即使Android已经为你做了很多事情)。但好处很明显 - 您可以获得实际的实时图形性能。