【问题标题】:How to load a bitmap for an android game?如何为安卓游戏加载位图?
【发布时间】:2013-02-05 20:05:34
【问题描述】:

我一直在开发一个没有位图或任何东西的游戏,我使用矩形作为对象,并根据它们的目的改变它们的颜色,比如玩家的红色矩形和墙壁的灰色矩形。我的问题是用位图/图像替换矩形的正确方法是什么?

我知道加载位图你可以这样做:

Bitmap randomBitmap = BitmapFactory.decodeResource(getResources(),
com.example.android4gametest.R.drawable.ic_launcher);

我应该加载所有位图并将它们传递给他们的类,还是应该在他们的类中加载位图而不是传递它?以及我将如何做到这一点,因为我无法使用 BitmapFactory,因为我无法访问 getResources()!或者我应该从我的资产文件夹中加载我的位图/图像,我知道我不会有你可以说弄乱位图的相同“工具”。

主活动

public class MainActivity extends Activity {
Game theGame;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
    WindowManager.LayoutParams.FLAG_FULLSCREEN);

    setContentView(new Game(this));
}
}

游戏面板 公共类 Game 扩展 SurfaceView 实现 SurfaceHolder.Callback {

GameThread _thread;

public Game(Context context) {
    super(context);

    getHolder().addCallback(this);

    setFocusable(true);

    _thread = new GameThread(getHolder(), this);


}

public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {
    // TODO Auto-generated method stub

}

public void surfaceCreated(SurfaceHolder holder) {
    _thread.setRunning(true);
    _thread.start();

}

public void surfaceDestroyed(SurfaceHolder holder) {
    // TODO Auto-generated method stub

}

@Override
protected void onDraw(Canvas canvas) {
    Log.d("OnDraw", "it is Drawing");
    canvas.drawColor(Color.BLUE);
}

public void update() {
    // TODO Auto-generated method stub  
}
}

GameLoop 这里什么都没有

    public class GameThread extends Thread{
/*FPS Code*/
private final static int MAX_FPS = 30;
private static final int FRAME_PERIOD = 1000/MAX_FPS;




protected SurfaceHolder holder;
protected Game game;
private boolean isRunning = false;

public GameThread(SurfaceHolder _holder, Game _game) {
    this.holder = _holder;
    this.game = _game;
}



/**
 * Returns True if the game is still running and False if the game is over
 * @return
 */
public boolean isRunning() {
    return isRunning;
}
/**
 * Set to true for the game loop to start 
 * @param isRunning
 */
public void setRunning(boolean isRunning) {
    this.isRunning = isRunning;
}


@Override
public void run() {
    Canvas c;
    Log.d("Pallyways", "Starting game Loop");

    long beingTime;
    long timeDiff;
    int sleepTime;
    int framesSkipped;

    sleepTime = 0;

    while(isRunning){
        c = null;
        try{

            c = holder.lockCanvas();
            synchronized(holder){
                beingTime = System.currentTimeMillis();
                framesSkipped = 0;
                game.update();//Update
                game.onDraw(c);//Redraw

                timeDiff = System.currentTimeMillis() - beingTime ;
                sleepTime = (int) (FRAME_PERIOD - timeDiff);

                if(sleepTime>0){
                    try{
                        Thread.sleep(sleepTime);} 
                    catch (InterruptedException e) {
                        e.printStackTrace();}
                    finally{}
                }

                while(sleepTime<0 && framesSkipped < 5){
                    game.update();

                    sleepTime+= FRAME_PERIOD;
                    framesSkipped++;
                }

            }
        }finally{if(c!=null){
            holder.unlockCanvasAndPost(c);
        }
        }
    }
}

}

英雄类我还没有开始,但我想知道如何在不同包上的类上加载位图

package com.example.android4gametest.Actors;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import com.example.android4gametest.R;

public class Hero {
//getContext() gives me an error and that is because it does not have a reference

private Bitmap hero = BitmapFactory.decodeResource(getContext().getResources(),
R.drawable.ic_launcher);
public Hero(){

}}

【问题讨论】:

    标签: java android


    【解决方案1】:

    根据位图的大小/数量,可以将它们加载到 Game 类的构造函数中。但是请注意,如果您一次将太多/太大的位图加载到内存中,您可能会遇到一些 OOM 错误或在进行第一次绘图调用时出现延迟。当您不再需要位图时,您必须确保将其归零并有效地回收它们。在我的第一场比赛中遇到了这个问题

    【讨论】:

    • 啊,我会做一些关于回收位图的研究!现在没有,我的在线游戏需要 4 个位图英雄、墙壁、目标和可由玩家移动的对象
    【解决方案2】:

    不要在游戏对象的构造函数中加载Bitmap。如果这些Bitmaps 中的任何一个将被多个对象(即敌人类)使用,那么如果您将它们加载到对象的构造函数中,您将在内存中拥有Bitmap 的多个副本。这可能导致OutOfMemoryException。而是在构造函数之外(在游戏线程或游戏面板中)加载您的 Bitmap,然后将 Bitmap 对象传递给构造函数或设置器,并以这种方式设置您的私有 Bitmaps。您只需在内存中保留有限数量的Bitmaps

    您可能还需要考虑加载“屏幕”,在加载 Bitmaps 时显示进度条或微调器。

    【讨论】:

    • 我更新的 Hero 类将 Context 作为参数,然后在 Hero 构造函数中,我将位图传递给 hero 类 public Hero(context){ bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher},这不是正确的做法吗?你能提供我和例子以便更好地理解吗
    • 这对于像 Hero 类这样的对象来说没问题,但是如果你有可以重复的敌人或通电,那么你可能希望在管理类或线程类中的资源上调用一次 decodeResource 方法并像这样在构造函数中传递它:Powerup(Bitmap health)。抱歉,如果这没有帮助。
    【解决方案3】:

    加载位置并不重要。我认为您的主要问题是访问资源。在视图中,您可以调用:

    getContext().getResources()
    

    编辑:

    所以在Hero的构造函数的方法签名中添加Context作为参数:

    public Hero(Context context){
      private Bitmap hero = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher);
    }
    

    【讨论】:

    • 我是否必须将上下文传递给我的类才能使用位图加载它?所以可以说我的类英雄构造函数类似于Hero(Context)
    • 哎呀,我的错,以为你的课扩展了视图。是的,那也行。只是不要保留对 Context 的全局引用或将其保留在 WeakReference 中
    • 我知道这可以工作,但它是正确的方式吗?以有效的方式做到这一点?
    • 我看不出为什么不这样做的原因。只要记住在完成位图/旋转等时回收您的位图。
    【解决方案4】:

    不要!使用动态对象.. 我的意思是根本不要在游戏中创建动态对象,这些会触发 GC 并使一切在它想要的时候运行时结结巴巴。您必须自己控制一切,并在障碍物和敌人上使用静态/最终“对象”和数组。对象将在启动时加载到堆上,这意味着您将加载它们直到应用程序关闭。因此,您必须在这些静态对象中拥有什么和不拥有什么之间找到平衡,但找到它就很容易了。

    位图应该在这些静态非动态对象之外加载,对象应该只做计算。

    并且永远不要在你之间使用任何不必要的计算、循环或 Thread.sleep c = holder.lockCanvas();和 holder.unlockCanvasAndPost(c);就像您在代码中所做的那样。 这可以并且最终会使游戏闪烁。

    问候, 我

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-16
      相关资源
      最近更新 更多