我正在尝试开发可能首先在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);
}
感谢您迄今为止提供的所有帮助
答案 0 :(得分:0)
问题似乎不在主线程活动中,你跟着教程很好(除了行 - System.out.println(waitTime); - 但我不认为这是问题原因。) 问题最有可能发生在GamePanel上。 ;)
答案 1 :(得分:0)
不要在游戏循环中使用Thread.sleep()
。不保证在指定的时间内睡觉。
无论如何,我认为使用Canvas时这是非常期待的行为。如果我是你,我会考虑使用OpenGL ES进行图形渲染。当然,这使得它变得更加复杂(尽管Android已经为你做了很多事情)。但好处非常明显 - 您可以获得实时的图形性能。