我正在使用Canvas / Surfaceview开发2D游戏,并且在滚动背景图像方面存在问题。
查看游戏 - http://youtu.be/4Gi5rRqzZ3M
在NinJump游戏中,角色Ninja只是在X坐标中跳跃而背景图像以非常高的速度滚动,使Ninja看起来像是在实际运行。
我创建了基本设置,创建了Ninja,添加了跳转功能,添加了背景。 现在我想一遍又一遍地重复相同的背景。我怎样才能做到这一点?
以下是我的源文件 - 主要活动类
package com.abc.apps;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;
public class LadderActivity extends Activity {
private static final String TAG = LadderActivity.class.getSimpleName();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// requesting to turn the title OFF
requestWindowFeature(Window.FEATURE_NO_TITLE);
// making it full screen
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
// set our MainGamePanel as the View
setContentView(new MainGameBoard(this));
Log.d(TAG, "View added");
}
@Override
protected void onDestroy() {
Log.d(TAG, "Destroying...");
super.onDestroy();
}
@Override
protected void onStop() {
Log.d(TAG, "Stopping...");
super.onStop();
}
}
游戏板扩展了SurfaceView
package com.abc.apps;
import android.app.Activity;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MainGameBoard extends SurfaceView implements SurfaceHolder.Callback{
private MainGameLoop thread;
private Monkey monkey;
private static final String TAG = MainGameLoop.class.getSimpleName();
int currentX, currentY;
public MainGameBoard(Context context) {
super(context);
// TODO Auto-generated constructor stub
// adding the callback (this) to the surface holder to intercept events
//This line sets the current class (MainGamePanel) as the handler for the events happening on the actual surface
getHolder().addCallback(this);
// create monkey and load bitmap INITIALIZE AT LEFT
monkey = new Monkey(BitmapFactory.decodeResource(getResources(), R.drawable.actor),60, 340);
// create the game loop thread
thread = new MainGameLoop(getHolder(), this);
// make the GamePanel focusable so it can handle events.
setFocusable(true);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
thread.setRunning(true);
thread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
// tell the thread to shut down and wait for it to finish
// this is a clean shutdown
boolean retry = true;
while (retry) {
try {
thread.join();
retry = false;
}
catch (InterruptedException e) {
// try again shutting down the thread
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
//For jumping Left
if (event.getX() < (getWidth()/2 - 32)) {
// Log.d(TAG, "Coords: x=" + event.getX() + ",y=" + event.getY());
//Log.d(TAG, "Jump Left");
// Sleep so that the main thread doesn't get flooded with UI events.
try {
Thread.sleep(32);
monkey.setX((getWidth()/2 - 60));
monkey.setY(monkey.getY()-70);
} catch (InterruptedException e) {
// No big deal if this sleep is interrupted.
}
}
//For Jumping Right
if (event.getX() > (getWidth()/2 + 32)) {
//Log.d(TAG, "Coords: x=" + event.getX() + ",y=" + event.getY());
//Log.d(TAG, "Jump Right");
// Sleep so that the main thread doesn't get flooded with UI events.
try {
Thread.sleep(32);
monkey.setX((getWidth()/2 + 60));
monkey.setY(monkey.getY()-70);
} catch (InterruptedException e) {
// No big deal if this sleep is interrupted.
}
}
/* //Middle Portion
if (event.getX() > (getWidth()/2 - 32) && event.getX() < (getWidth()/2 +32)) {
//thread.setRunning(false);
//((Activity)getContext()).finish();
}*/
}
return true;
}
public void render(Canvas canvas) {
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.monkey_sc), 0, 0,null);
monkey.draw(canvas);
}
/* @Override
protected void onDraw(Canvas canvas){
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.monkey_scene), 0, 0,null);
monkey.draw(canvas);
}*/
}
主游戏圈
package com.abc.apps;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.util.Log;
import android.view.SurfaceHolder;
public class MainGameLoop extends Thread {
private SurfaceHolder surfaceHolder;
private MainGameBoard gameBoard;
private Monkey monkey;
private static final String TAG = MainGameLoop.class.getSimpleName();
// flag to hold game state
private boolean running = true;
public void setRunning(boolean running) {
this.running = running;
}
@Override
public void run() {
Canvas canvas;
Log.d(TAG, "Starting game loop");
while (running) {
canvas = null;
// try locking the canvas for exclusive pixel editing on the surface
try {
canvas = surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
// update game state
// render state to the screen
// draws the canvas on the panel
gameBoard.render(canvas);
}
}
finally {
// in case of an exception the surface is not left in
// an inconsistent state
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
} // end finally
}
}
public MainGameLoop(SurfaceHolder surfaceHolder, MainGameBoard gameBoard) {
super();
this.surfaceHolder = surfaceHolder;
this.gameBoard = gameBoard;
}
}//MainThread
猴子班
package com.abc.apps;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.MotionEvent;
public class Monkey {
private Bitmap bitmap; // the actual bitmap
private int x; // the X coordinate
private int y; // the Y coordinate
private boolean touched; // if monkey is touched
public Monkey(Bitmap bitmap, int x, int y) {
this.bitmap = bitmap;
this.x = x;
this.y = y;
}
public Bitmap getBitmap() {
return bitmap;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public boolean isTouched() {
return touched;
}
public void setTouched(boolean touched) {
this.touched = touched;
}
public void draw(Canvas canvas) {
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawBitmap(bitmap, x - (bitmap.getWidth() / 2), y, paint);
}
}
答案 0 :(得分:1)
看起来您正在使用render方法在MainGameBoard类中绘制背景。
public void render(Canvas canvas) {
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.monkey_sc), 0, 0,null);
monkey.draw(canvas);
}
你应该只需要2个drawBitmap调用而不是1个。
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.monkey_sc), 0, y_offset1,null);
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.monkey_sc), 0, y_offset2,null);
我假设每个背景图像的高度相同或者大于屏幕高度;如果它小于屏幕高度,则需要超过2个实例。
然后你在y_offset1 = 0处开始1张图片,在y_offset2 = -image_height处开始另一张图片。
每次抽奖你都会增加y_offset1和y_offset2相同的数量。然后,您需要检查两个偏移量,以查看是否有大于屏幕高度的量。如果是,那么现在“屏幕下方”的y_offset应该重置为另一个y_offset减去image_height。这将创建一个无限循环的滚动图像。
使用此类技术时,重要的是要考虑图像边缘;图像应设计成无缝拼接,否则在循环点沿边缘会出现明显的视觉效果。