如何使用游戏循环每五秒在屏幕上出现和消失一个对象

Posted

技术标签:

【中文标题】如何使用游戏循环每五秒在屏幕上出现和消失一个对象【英文标题】:How to appear and disappear an object on screen using game loop for every five second 【发布时间】:2012-09-05 12:53:03 【问题描述】:

我正在尝试学习 android 中的游戏开发。首先,我尝试每五秒钟使用游戏循环在屏幕上出现和消失一个对象。但我没有成功。我读过不同的教程和论坛。我在教程中应用了所有东西,但对象仍在连续绘制。它并没有消失。我没有得到我所缺少的东西?请指导我。

完整代码在这里:

MainGameActivity.java

package com.example.showandhideobject;

import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;

public class MainGameActivity extends Activity 

    @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 MainGamePanel(this));
      

MainGamePanel .java

package com.example.showandhideobject;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MainGamePanel extends SurfaceView implements
        SurfaceHolder.Callback 

    private MainGameThread thread;
    private ImageObject image;

    // private long gameStartTime;

    public MainGamePanel(Context context) 
        super(context);
        // adding the callback (this) to the surface holder to intercept events
        getHolder().addCallback(this);
        // create the game loop thread
        thread = new MainGameThread(getHolder(), this);

        Bitmap imageBitMap = BitmapFactory.decodeResource(getResources(),
                R.drawable.rose);
        image = new ImageObject(imageBitMap, 100, 150);
        image.setAppeared(false);
        image.setDisappearTime(System.currentTimeMillis());

        // make the GamePanel focusable so it can handle events
        setFocusable(true);
    

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

    @Override
    public void surfaceCreated(SurfaceHolder holder) 
        // at this point the surface is created and
        // we can safely start the game loop

        thread.setRunning(true);
        thread.start();

    

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) 
    

    public void update() 

        Log.i("Image Status:::::::::::::    ",
                Boolean.valueOf(image.isAppeared()).toString());

        if (!image.isAppeared()
                && System.currentTimeMillis() - image.getDisappearTime() >= 5000) 

            Log.i("Image Object:::::::  ", "Showing");
            image.setAppeared(true);
            image.setAppearTime(System.currentTimeMillis());

        
        if (image.isAppeared()
                && (System.currentTimeMillis() - image.getAppearTime() >= 5000)) 

            Log.i("Image Object:::::::  ", "Not Showing");
            image.setAppeared(false);
            image.setDisappearTime(System.currentTimeMillis());
        
    

    public void render(Canvas canvas) 

        if (image.isAppeared()) 
            image.draw(canvas);
        
    


MainGameThread.java

package com.example.showandhideobject;

import android.graphics.Canvas;
import android.util.Log;
import android.view.SurfaceHolder;

public class MainGameThread extends Thread 

    // Surface holder that can access the physical surface
    private SurfaceHolder surfaceHolder;

    // The actual view that handles inputs
    // and draws to the surface
    private MainGamePanel gamePanel;

    // flag to hold game state
    private boolean running;

    public boolean isRunning() 
        return running;
    

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

    public MainGameThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) 
        super();
        this.surfaceHolder = surfaceHolder;
        this.gamePanel = gamePanel;
    

    @Override
    public void run() 
        Canvas canvas;

        while (isRunning()) 
            canvas = null;
            // try locking the canvas for exclusive pixel editing
            // in the surface
            try 
                canvas = this.surfaceHolder.lockCanvas();
                synchronized (surfaceHolder) 
                    Log.i("With in :::::::::", "Game Loop");
                    // update game state
                    gamePanel.update();
                    // render state to the screen and draw the canvas on the
                    // panel

                    gamePanel.render(canvas);
                    // gamePanel.onDraw(canvas);
                
             finally 
                // in case of an exception the surface is not left in an
                // inconsistent state
                if (canvas != null) 
                    surfaceHolder.unlockCanvasAndPost(canvas);
                
             // end finally
        
    

ImageObject.java

package com.example.showandhideobject;

import android.graphics.Bitmap;
import android.graphics.Canvas;

public class ImageObject 

    private Bitmap bitmap; // the actual bitmap
    private int x; // the X coordinate
    private int y; // the Y coordinate
    private boolean isAppeared;
    private long appearTime;
    private long disappearTime;

    // Constructor for this class
    public ImageObject(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 isAppeared() 
        return isAppeared;
    

    public void setAppeared(boolean isAppeared) 
        this.isAppeared = isAppeared;
    

    public long getAppearTime() 
        return appearTime;
    

    public void setAppearTime(long appearTime) 
        this.appearTime = appearTime;
    

    public long getDisappearTime() 
        return disappearTime;
    

    public void setDisappearTime(long disappearTime) 
        this.disappearTime = disappearTime;
    

    /* Method to draw images on Canvas */
    public void draw(Canvas canvas) 
        canvas.drawBitmap(bitmap, x - (bitmap.getWidth() / 2),
                y - (bitmap.getHeight() / 2), null);
    

【问题讨论】:

乍一看,它似乎过度设计了。 您有一些日志消息:Log.i("Image ... 它们显示了什么? 【参考方案1】:

在这部分

if (image.isAppeared()) 
    image.draw(canvas);

你永远不会清理你的画布。你所做的实际上是在同一个地方一遍又一遍地绘制你的图像。

您可能需要在 cas isAppeared() is false 中重绘背景

编辑

您也可以在绘制图像之前使用 canvas.save(),当您不再需要该图像时使用 canvas.restore()。

【讨论】:

我刚刚使用了 canvas.drawColor(Color.CYAN);在 if 条件之外。 if (image.isAppeared()) image.draw(canvas); 谢谢 njzk2 :)【参考方案2】:

不要尝试过早优化,游戏渲染通常效率低下,因为几乎所有屏幕的大部分都预计会发生变化。

循环应该是:

    始终在画布上绘制背景 始终将所有游戏对象绘制到画布上,让它们决定它们是否可见,这将简化 MainGamePanel 类 最后总是显示画布(通过复制到图像)

扩展第 2 点:

/* Method to draw images on Canvas */  
public void draw(Canvas canvas)  
    if(!isAppeared) return; //let the object decide when it should be drawn
    canvas.drawBitmap(bitmap, x - (bitmap.getWidth() / 2),  
            y - (bitmap.getHeight() / 2), null);  
  

【讨论】:

【参考方案3】:

将MainGamePanel.java中的方法render改为

if (image.isAppeared() && canvas != null) 
        image.draw(canvas);

【讨论】:

以上是关于如何使用游戏循环每五秒在屏幕上出现和消失一个对象的主要内容,如果未能解决你的问题,请参考以下文章

在python中计算每五秒的平均值

C#当鼠标移动事件时,时间循环停止

出现Android键盘时Unity调整屏幕大小

如何让多个不同单词的数组在游戏屏幕上移动?

绿色加载屏幕后登录 Google Play 消失。如何解决?

SKSpriteNode 从屏幕上消失后如何删除或销毁它