Android Java中如何重复Bitmap?游戏背景横向重复实现求助
搞定Android平台游戏横向循环滚动背景的小技巧
嘿,老兄!看你在做类似马里奥的Android平台游戏,卡在横向循环滚动背景的问题上了是吧?我来给你捋捋怎么搞定这个事儿~
核心问题拆解
你现在的做法是每次draw都给bgSrcX累加20,但这样下去很快就会超出Bitmap的宽度,背景就会出现空白或者消失。而且你提到Bitmap太大,只画屏幕一半区域——其实咱们的核心需求是让背景无缝循环滚动,同时只绘制屏幕可见的部分,省性能。
具体实现步骤
1. 先把关键变量理清楚
首先得有几个变量跟踪背景状态,别用数组啦,单个变量更清晰:
// 你的超大背景Bitmap private Bitmap bgBitmap; // 背景在X轴的滚动偏移量 private float bgScrollOffset = 0; // 屏幕宽度,用来确定要画多大区域 private int screenWidth; // 背景Bitmap的实际宽度 private int bgWidth; // 滚动速度,你之前用的20,这里可以随便调 private final int SCROLL_SPEED = 20;
2. 提前获取屏幕宽度
在View的onSizeChanged方法里拿屏幕宽度,不用每次draw都算:
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); screenWidth = w; if (bgBitmap != null) { bgWidth = bgBitmap.getWidth(); } }
3. 重写draw方法,实现循环滚动
这是最关键的部分,咱们要处理偏移量的重置,还要只画屏幕可见的区域:
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (bgBitmap == null) return; // 更新滚动偏移量 bgScrollOffset += SCROLL_SPEED; // 重点!当偏移量超过背景宽度时,取模重置,实现无缝循环 bgScrollOffset %= bgWidth; // 先画第一部分背景:从当前偏移量到背景末尾的区域 int srcStartX = (int) bgScrollOffset; int drawWidth = bgWidth - srcStartX; canvas.drawBitmap(bgBitmap, new Rect(srcStartX, 0, bgWidth, bgBitmap.getHeight()), new Rect(0, 0, drawWidth, getHeight()), null); // 如果第一部分不够填满屏幕,就从背景开头补剩下的部分 if (drawWidth < screenWidth) { canvas.drawBitmap(bgBitmap, new Rect(0, 0, screenWidth - drawWidth, bgBitmap.getHeight()), new Rect(drawWidth, 0, screenWidth, getHeight()), null); } // 调用invalidate让View持续重绘,实现滚动效果 invalidate(); }
4. 为啥这么做?
- 用
%= bgWidth来重置偏移量,相当于让背景“绕回去”,不会出现空白; - 用
Rect裁剪Bitmap的源区域和目标区域,只画屏幕上能看到的部分,完美解决你说的“Bitmap太大只画屏幕区域”的需求,性能拉满; - 分两部分绘制是为了处理背景末尾和开头衔接的情况,保证滚动时不会有断层。
额外的小优化
- 如果你的背景是由小瓷砖(Tile)组成的,其实可以用
BitmapShader加TileMode.REPEAT来实现,更高效,但如果是单张大Bitmap,上面的方法就足够了; - 可以把滚动速度和帧率绑定,比如用
Choreographer,这样在不同设备上滚动速度更一致; - 记得在View销毁时回收Bitmap,别搞内存泄漏:
@Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (bgBitmap != null && !bgBitmap.isRecycled()) { bgBitmap.recycle(); bgBitmap = null; } }
这样改完,你的背景就能像马里奥里那样无限循环横向滚动啦,而且性能也没问题~
内容的提问来源于stack exchange,提问作者Yekta Sarıoğlu
相关产品推荐
相关产品推荐

