【问题标题】:how to draw infinite amount of sprites?如何绘制无限数量的精灵?
【发布时间】:2015-08-23 23:52:19
【问题描述】:

我是一名初级程序员,我正在 android studio 中制作一款飞扬的小鸟游戏。我被困在制作从屏幕右侧进入的导弹。关于如何解决这个问题的任何提示、提示和技巧?我想自己制作一个精灵列表并尝试无限循环这个列表,但我不知道如何。

基斯

public Missles(GamePanel game, Bitmap bmp) {
    this.game = game;
    this.sprite = bmp;
    this.width = bmp.getWidth() / Sprite_Columns;
    this.height = bmp.getHeight() / Sprite_Rows;
    this.xposition = 1100;
}
private void update() {
    //Here we check whether the bitmap touches the bound or not.
    //if (xposition > game.getWidth() - width - xspeed) {
    //    xspeed = -5;
    //}
    //if (xposition + xspeed < 0) {
    //    xspeed = 5;
    // }
    xposition = xposition + xspeed;
    currentframe = (currentframe + 1) % Sprite_Columns;
}
public void onDraw(Canvas canvas) {
    update();
    // Here we cut our bitmap, such that we get the frames from left to right in the columns
    int smallrectX = currentframe * width;

    //choosing the second row of our sprite sheet, quite confusing y-axis though
    int smallrectY = height;

    // Making two rectangles, the frame of the spritesheet and
    // the position to put it in!
    Rect smallrect = new Rect(smallrectX, smallrectY, smallrectX + width, smallrectY + height);
    Rect position = new Rect(xposition, yposition, xposition + width, yposition + height);

    // making a drawing
    canvas.drawBitmap(sprite, smallrect, position, null);
}

}

还有我的游戏面板:

public class GamePanel extends SurfaceView implements SurfaceHolder.Callback {
private Sprite sprite;
private Missles missles;
private SurfaceHolder holder;
private GamePanelThread thread;
private Bitmap bmp;
private Bitmap missle;
private List<Sprite> spriteslist = new ArrayList<Sprite>();
private Bitmap background;
private Bitmap scaledbmp;
private int xposition = 0;
private int xspeed = 1;

public GamePanel(Context context,int resource) {
    super(context);
    //TODO Auto generated constructor stub
    // unpacking sprites and missles
    bmp = BitmapFactory.decodeResource(getResources(), resource);
    missle = BitmapFactory.decodeResource(getResources(), R.mipmap.angle_sprite);

    sprite = new Sprite(this,bmp);
    missles = new Missles(this,missle);

    // Making the surfaceholder and the thread for the gameloop
    holder = getHolder();
    holder.addCallback(this);
    thread = new GamePanelThread(holder, this);

    // This statement improves the performance
    setFocusable(true);
}


@Override
public void surfaceCreated(SurfaceHolder holder) {

    //Here i just creat the scaled background
    background = BitmapFactory.decodeResource(getResources(), R.mipmap.cool_background);
    float scale = (float)background.getHeight()/(float)getHeight();
    int newWidth = Math.round(background.getWidth()/scale);
    int newHeight = Math.round(background.getHeight()/scale);
    scaledbmp = Bitmap.createScaledBitmap(background, newWidth, newHeight, true);
    createSprites();

    // starting the thread
    thread.setRunning(true);
    thread.start();
}

private Sprite createSprite(int resouce) {
    Bitmap bmp = BitmapFactory.decodeResource(getResources(), resouce);
    return new Sprite(this, bmp);
}

private void createSprites() {
    spriteslist.add(createSprite(R.mipmap.angle_sprite));
    spriteslist.add(createSprite(R.mipmap.monster_girl_sprite));
    spriteslist.add(createSprite(R.mipmap.flyingwoman_sprite));
}

@Override
protected void onDraw(Canvas canvas) {
    //Drawing the background and sprites as it is a blackboard.
    canvas.drawBitmap(scaledbmp,0,0,null);
    sprite.onDraw(canvas);
    for (Sprite sprite : spriteslist) {
        missles.onDraw(canvas);
    }
    missles.onDraw(canvas);
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format,
                           int width, int height) {
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    // the purpose here is to tell the thread to shut down.
    boolean retry = false;
    while (retry) {
        try {
            thread.join();
            retry = false;
        } catch (InterruptedException e) {

        }
    }
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    if(event.getAction() == MotionEvent.ACTION_DOWN){
        sprite.up = true;
        return true;
    }
    if(event.getAction() == MotionEvent.ACTION_UP){
        sprite.up = false;
        return true;
    }


    return super.onTouchEvent(event);
}

}

还有游戏循环:

public class GamePanelThread extends Thread {

private int FPS = 10;
private boolean running;
private SurfaceHolder surfaceholder;
private GamePanel game;

public GamePanelThread(SurfaceHolder surfaceholder, GamePanel game){

    super();
    this.surfaceholder = surfaceholder;
    this.game = game;

}
public void setRunning(boolean running) {
    this.running = running;
}

@Override
public void run(){
    long startTime;
    long sleepTime;
    //tijd van gameloop
    long ticksPS = 1000 / FPS;
    while(running){
        startTime = System.nanoTime();
        Canvas canvas = null;
    try {
        canvas = surfaceholder.lockCanvas();
        synchronized (surfaceholder)
        {
            game.onDraw(canvas);
        }
    } finally {
        if (canvas != null) {
            surfaceholder.unlockCanvasAndPost(canvas);
        }
    sleepTime = ticksPS - (System.nanoTime()- startTime);//laatste deel is hoeveel seconden om 1 loop om te gaan;
    try{
        if(sleepTime>0) {
            this.sleep(sleepTime);
        } else {
            sleep(10);
        }
        } catch (Exception e) {}
    }
}


}

}

【问题讨论】:

  • 学习面向对象编程。用生命、速度和方向使所有精灵成为自己的对象。然后使用 ArrayLists 遍历它们以呈现它们。
  • @micheal 我知道如何制作列表并绘制列表中的所有精灵,但我的主要想法是在某个时间间隔内一张一张地绘制它们。但是当我到达列表的末尾时,它不会重新启动循环。基斯
  • 你的游戏循环在哪里?最好你有一个线程每秒运行大约 20-30(滴答声)次,计算发生的一切,更新位置,计算碰撞。渲染线程只是从游戏线程中读取数据并相应地在屏幕上绘制。
  • 我有一个游戏循环,我也应该发布这个吗?
  • 是的。然后我们可以看到你的游戏循环是如何与你的渲染线程交互的。

标签: java arraylist android-studio sprite


【解决方案1】:

要跟踪无限数量的精灵将需要无限数量的内存并花费无限的时间来绘制。 IE 不行。

您想要的是创建一些对象,将其绘制在屏幕上,并在它离开屏幕后悄悄地回收它。

您需要查找的主题是“对象池”。

我可能会有 5-10 枚导弹的阵列。他们每个人都有一个位图、一个位置和一个布尔“isAlive”标志。当我想创建一个导弹时,我会寻找一个 isAlive==false 的导弹并激活它。我只需要更新、绘制和检查 isAlive 对象的碰撞。一旦它们离开屏幕,设置 isAlive=false 并且它们可以再次被重复使用。

这可能会用于无限跑步游戏中的很多东西。

【讨论】:

  • 请记住,尽管您也需要一个位图池。为每个精灵一遍又一遍地重新加载相同的位图是没有用的。所有导弹可以共享同一个位图。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-01
相关资源
最近更新 更多