Android studio 2d游戏fps问题

时间:2016-02-05 19:23:59

标签: java android 2d-games

我正在尝试开发可能首先在2d安卓游戏。我打算在不使用引擎的情况下从头开始构建它。我已设法创建以下线程:

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。 无论如何,我能做些什么来优化它?

谢谢

更新:我的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);
}

感谢您迄今为止提供的所有帮助

2 个答案:

答案 0 :(得分:0)

问题似乎不在主线程活动中,你跟着教程很好(除了行 - System.out.println(waitTime); - 但我不认为这是问题原因。) 问题最有可能发生在GamePanel上。 ;)

答案 1 :(得分:0)

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

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