使用自定义的SurfaceView和线程为Android游戏编程(例如) [英] Using a custom SurfaceView and thread for Android game programming (example)

查看:152
本文介绍了使用自定义的SurfaceView和线程为Android游戏编程(例如)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用SurfaceView,但 lockCanvas(空)是混乱的,并且应用程序冻结时,我退出了活动。此外,未显示任何内容,即使我用的是教程工作完全没有问题,我不明白我在做什么错。请大家帮帮忙。

I am trying to use SurfaceView, but the lockCanvas(null) is confusing, and the app freezes when I exit the activity. Also, nothing is displayed, even though the tutorial I was using was working perfectly fine, and I don't understand what I am doing wrong. Please help.

推荐答案

解决的办法可能就是 setWillNotDraw(假); 不叫

The solution is probably that setWillNotDraw(false); was not called.

因此​​,参考实现,正常工作将是以下内容:

Therefore, a referential implementation that works properly would be the following:

public class GameSurfaceView extends SurfaceView implements SurfaceHolder.Callback
{
    private SurfaceHolder holder;

    private MyThread myThread;

    private GameController gameController;

    private Paint paint;

    private int width;
    private int height;

    public GameSurfaceView(Context context, GameController gameController, int width, int height)
    {
        super(context);
        holder = getHolder(); 

        holder.addCallback(this);

        this.gameController = gameController;
        this.width = width;
        this.height = height;
        paint = new Paint();
        //initialize paint object parameters

        setWillNotDraw(false); //this line is very important!
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder)
    {
    }

    @Override
    // This is always called at least once, after surfaceCreated
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
    {
        if (myThread == null)
        {
            myThread = new MyThread(holder, gameController);
            myThread.setRunning(true);
            myThread.start();
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder)
    {
        boolean retry = true;
        myThread.setRunning(false);
        while (retry)
        {
            try
            {
                myThread.join();
                retry = false;
            }
            catch (InterruptedException e)
            {
                Log.d(getClass().getSimpleName(), "Interrupted Exception", e);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        System.out.println(event.getX() + " " + event.getY());
        gameController.onTouchEvent(event); //handle user interaction
        return super.onTouchEvent(event);
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
        canvas.drawText("Hello world!", width/20, 20, paint);
        gameController.draw(canvas);
    }

    public Thread getThread()
    {
        return thread;
    }

    public class MyThread extends Thread
    {
        private SurfaceHolder holder;
        private boolean running = false;

        private GameController gameController;

        public MyThread(SurfaceHolder holder, GameController gameController)
        {
            this.holder = holder;
            this.gameController = gameController;
        }

        @Override
        public void run()
        {
            Canvas canvas = null;
            while (running)
            {
                gameController.update(); //update the time between last update() call and now
                try
                {
                    canvas = holder.lockCanvas(null);
                    synchronized (holder)
                    {
                        postInvalidate();
                    }
                }
                finally
                {
                    if (canvas != null)
                    {
                        holder.unlockCanvasAndPost(canvas);
                    }
                }
            }

        }

        public void setRunning(boolean b)
        {
            running = b;
        }
    }
}

表面本身并不真的想解答一下它的宽度和高度,因此更容易,如果我们从外面的测量,并提供它从外面我们的自定义视图:

The surface itself doesn't really want to answer what its width and height is, therefore it's easier if we get its measurements from the outside, and provide it for our custom View from the outside:

//Fragment onCreateView()
    Display display = getActivity().getWindowManager().getDefaultDisplay();
    RelativeLayout rl = (RelativeLayout)view.findViewById(R.id.gameplay_container);
    rl.addView(new GameSurfaceView(this.getActivity().getApplicationContext(), gameController, display.getWidth(), display.getHeight()));
    return view;
}

现在,我们能够借鉴到我们自己的线程的SurfaceView,而且我们也能够单独所有的游戏相关的逻辑在GameController。该GameController负责输入处理和游戏事件更新,按如下:

Now we are able to draw onto the SurfaceView from our own Thread, and we are also able to seperate all game-related logic in a GameController. The GameController is responsible for input handling and game event updates, as per the following:

    public void update()
    {
        long delta = getTimeManager().getDeltaTime(System.currentTimeMillis());
        long timeChunk;
        if (isGameOver == false)
        {
            for (long i = 0; i < delta; i += 20)
            {
                long iNext = i + 20;
                if (iNext > delta)
                {
                    timeChunk = delta - i;
                }
                else
                {
                    timeChunk = iNext - i;
                }
                // ...update game entities based on the miliseconds provided in timeChunk
    }

和获取时间(即通过了自previous更新时间)的增量数额如下:

And to get the delta amount of time (the time that passed by since the previous update) is the following:

    long temp = currentTimeMillis - oldTime;
    this.oldTime = currentTimeMillis;
    return temp;

我希望这将有助于你以后:)

I hope that will be helpful to you later :)

这篇关于使用自定义的SurfaceView和线程为Android游戏编程(例如)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆