【问题标题】:Scroll Background Like Lunar Lander or Ninja Jump Game - Android像月球着陆器或忍者跳跃游戏一样滚动背景 - Android
【发布时间】:2012-08-20 23:40:42
【问题描述】:

我正在使用 Canvas/Sur​​faceview 开发 2d 游戏,但在滚动背景图像时遇到问题。

查看游戏 - http://youtu.be/4Gi5rRqzZ3M

在 NinJump 游戏中,角色忍者只是在 X 坐标中跳跃,背景图像以非常高的速度滚动,使忍者看起来像是在运行。

我已经创建了基本设置,创建了忍者,添加了跳转功能,添加了背景。 现在我想一遍又一遍地重复相同的背景。我怎样才能做到这一点?

以下是我的源文件 - 主要活动类

    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);
 }



}

【问题讨论】:

    标签: android game-physics 2d-games


    【解决方案1】:

    看起来您正在渲染方法中的 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。这将创建一个无限循环的滚动图像。

    使用这种技术时,考虑图像边缘很重要;图像的设计应使其无缝平铺,否则在循环点沿边缘会出现明显的视觉伪影。

    【讨论】:

    • 您能否详细解释一下我应该在哪里编码...我是android的新手。我也认为必须涉及 FPS 因素
    • 我没有,但我已经在原始帖子本身中添加了所有源代码。对于背景图片,我使用的是简单的白色背景。
    • 我真的受够了,如果有人有时间那么任何人都可以制作一个工作教程
    猜你喜欢
    • 1970-01-01
    • 2012-05-16
    • 2016-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-07
    • 2010-11-27
    • 1970-01-01
    相关资源
    最近更新 更多