我的滚动位图画布使用起来太慢
我正在学习 Android 编程。我制作了几个基本游戏,但为了学习,我想制作一款汽车驾驶游戏。我想到的最简单的方法是将汽车保持在屏幕中间并滚动背景以产生运动的错觉。
作为弄清楚引擎的实验,我创建了一个从 PNG 加载的 2048x1200 位图。这将是地图。然后,我创建一个从屏幕上显示的地图中裁剪出来的 1024x600 的新位图。我这样做是 getWidth() & getHeight() 给出这些尺寸。我每次都会根据运动情况采取不同的裁剪以在屏幕上显示。
不幸的是我发现这太慢而无法使用。如果我想让汽车平稳行驶,就必须以蜗牛般的速度行驶。我得到大约 18 fps。
我正在使用 James Daniello 的简单游戏循环
我也阅读下面的堆栈溢出文章,其中提到要尽可能地将对象创建排除在主循环之外,我正在尽力做到这一点。
如何在 Android 游戏中在屏幕上绘制大量位图,且性能不会降低
Romain Guy 的这篇文章也很有用,它介绍了如何将位图保持与屏幕相同的格式,以防止必须将其转换为在屏幕上显示,这是非常成本高昂。
位图质量、条带和抖动
在转向 OpenGL 之前,我想弄清楚使用 Canvas 和位图可以实现的最佳效果。我是否受到限制,或者我应该采取不同的做法?我发现每次只需滚动地图 1 像素即可实现平滑滚动,帧速率为 18 fps。
private Bitmap track;
private Bitmap visible;
private Point position;
private int fps = 0;
private long lastFpsTime = 0;
private int fpsCount = 0;
Paint pText;
public void Draw(Canvas c){
visible = Bitmap.createBitmap(track, position.x + 512, position.y + 300, 512, 300);
position.x++;
c.drawBitmap(visible, 0,0, null);
c.drawText("FPS: " + fps, 10, 10, pText);
}
public void Init(Resources resources) {
// Load Map from track1.png
track = Bitmap.createBitmap(2048, 1200, Bitmap.Config.RGB_565);
Bitmap track1 = BitmapFactory.decodeResource(resources, R.drawable.track1);
track = track1.copy(Bitmap.Config.RGB_565, true);
position = new Point(0,0);
//Setup the Text Paint Object
pText = new Paint();
pText.setColor(Color.WHITE);
pText.setStyle(Style.FILL_AND_STROKE);
}
public void Update() {
fpsCount++;
if (System.currentTimeMillis() - lastFpsTime >= 1000){
lastFpsTime = System.currentTimeMillis();
fps = fpsCount;
fpsCount = 0;
}
}
I am learning to program for the Android. I've made a couple of basic games, but for learning I'd like to make a car driving game. The simplest way I thought of doing this was to keep the car in the middle of the screen and scroll the background to give the illusion of movement.
As an experiment to figure out the engine, I created a 2048x1200 Bitmap which I load from a PNG. This will be the map. I then create a new bitmap of 1024x600 cropped from the map which I display on screen. I do this as getWidth() & getHeight() give these dimensions. I take a different crop each time based on movement to show on screen.
Unfortunately I find this too slow to use. The car would have to move at a snails pace if I wanted it to be smooth. I get about 18fps.
I am using James Daniello's Simple Game Loop
I also read the following stack overflow article which says to keep the object creation out of the main loop as much as possible, which I am doing as best I can.
How to draw lots of bitmaps on screen in an Android game without slow performance
Also of use was this article by Romain Guy on keeping the Bitmap as the same format as the screen to stop it having to be transformed to be displayed on the screen, which is very costly.
Bitmap quality, banding and dithering
I'd like to figure out the best I can achieve with Canvas and Bitmaps before I move on to OpenGL. Am I at the limitations, or should I do something differently? I find I get 18fps when just scrolling the map 1px at a time for smooth scrolling.
private Bitmap track;
private Bitmap visible;
private Point position;
private int fps = 0;
private long lastFpsTime = 0;
private int fpsCount = 0;
Paint pText;
public void Draw(Canvas c){
visible = Bitmap.createBitmap(track, position.x + 512, position.y + 300, 512, 300);
position.x++;
c.drawBitmap(visible, 0,0, null);
c.drawText("FPS: " + fps, 10, 10, pText);
}
public void Init(Resources resources) {
// Load Map from track1.png
track = Bitmap.createBitmap(2048, 1200, Bitmap.Config.RGB_565);
Bitmap track1 = BitmapFactory.decodeResource(resources, R.drawable.track1);
track = track1.copy(Bitmap.Config.RGB_565, true);
position = new Point(0,0);
//Setup the Text Paint Object
pText = new Paint();
pText.setColor(Color.WHITE);
pText.setStyle(Style.FILL_AND_STROKE);
}
public void Update() {
fpsCount++;
if (System.currentTimeMillis() - lastFpsTime >= 1000){
lastFpsTime = System.currentTimeMillis();
fps = fpsCount;
fpsCount = 0;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您将在绘制的每一帧上创建一个新的位图。它非常昂贵。您应该使用带有源矩形和目标矩形的drawBitmap() 版本。
You are creating a new bitmap on every frame you draw. It's extremely expensive. You should use the version of drawBitmap() that takes a source and a destination rectangle instead.
您可以使用以下两种策略之一,而不是从原始位图进行复制和缩放:矩阵或剪切矩形。矩阵将允许您在一个对象中执行与平移(平移)、缩放、倾斜和旋转相关的所有数学运算。每个操作也是可选的。这些操作是根据位图的原点计算的。使用的 api 是 Canvas.drawBitmap(位图位图、Matrix 矩阵、Paint 绘画)。这使您可以最大程度地控制位图的转换,但要充分利用它,您需要了解一些线性代数。
第二种选择是使用 矩形,我相信它更容易可视化并从一开始就与之合作。在位图上使用源矩形,您可以将其可视化为可以在位图尺寸上滑动的窗口,也可以根据需要扩展和缩小。目标矩形将代表您希望在屏幕上看到的内容的尺寸。通常是背景的 SurfaceView 的尺寸。使用 Canvas.drawBitmap(位图位图、矩形src、矩形dst、Paintpaint) API。
Instead of copying and scaling from the original bitmap you can use one of two strategies: a matrix or clipping rectangle. A matrix will allow you to perform all the math related to translation (panning), scaling, skew, and rotation into one object. Each operation is optional too. The operations are calculated with respect to the origin of the Bitmap. The api to use with this is Canvas.drawBitmap (Bitmap bitmap, Matrix matrix, Paint paint). This gives you the greatest control over transforming the Bitmap but to fully use this you'll need to understand some Linear Algebra.
The second option is to use a rectangle, I believe its easier to visualize and work with, in the beginning. Using a source rectangle over the Bitmap you can visualize that as a window that can slide over the dimensions of the Bitmap, also it can be expanded and shrunk as desired. The destination rectangle will represent the dimensions of what you'd like to see on the screen. Often the dimensions of the SurfaceView for a background. Use the Canvas.drawBitmap (Bitmap bitmap, Rect src, Rect dst, Paint paint) API for it.