【问题标题】:Android draw using SurfaceView and ThreadAndroid 使用 SurfaceView 和 Thread 绘制
【发布时间】:2012-06-12 23:16:21
【问题描述】:

我正在尝试使用 3 个类在我的屏幕上画一个球。我已经阅读了一些关于此的内容,并且发现了一个代码 sn-p 可以在一页上使用 3 个类,Playing with graphics in Android

我修改了代码,这样我就有了一个在撞墙时会移动并改变方向的球,如下图所示(这是使用链接中的代码)

现在我喜欢将课程分成 3 个不同的页面,以免让所有内容变得如此拥挤,所有内容都以相同的方式设置。

这是我的 3 个课程。

  1. BallActivity.java
  2. Ball.java
  3. BallThread.java

package com.brick.breaker;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;


public class BallActivity extends Activity {

private Ball ball;

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

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

    ball = new Ball(this);
    setContentView(ball);
}

@Override
protected void onPause() {

    super.onPause();

    setContentView(null);
    ball = null;

    finish();
}

}

package com.brick.breaker;

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

public class Ball extends SurfaceView implements SurfaceHolder.Callback {

private BallThread ballThread = null;

private Bitmap bitmap;

private float x, y;
private float vx, vy;

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

    bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ball);

    x = 50.0f;
    y = 50.0f;

    vx = 10.0f;
    vy = 10.0f;

    getHolder().addCallback(this);
    ballThread = new BallThread(getHolder(), this);
}

protected void onDraw(Canvas canvas) {

    update(canvas);

    canvas.drawBitmap(bitmap, x, y, null);
}

public void update(Canvas canvas) {

    checkCollisions(canvas);

    x += vx;
    y += vy;
}

public void checkCollisions(Canvas canvas) {

    if(x - vx < 0) {

        vx = Math.abs(vx);

    } else if(x + vx > canvas.getWidth() - getBitmapWidth()) {

        vx = -Math.abs(vx);
    }

    if(y - vy < 0) {

        vy = Math.abs(vy);

    } else if(y + vy > canvas.getHeight() - getBitmapHeight()) {

        vy = -Math.abs(vy);
    }
}

public int getBitmapWidth() {

    if(bitmap != null) {

        return bitmap.getWidth();

    } else {

        return 0;
    }
}

public int getBitmapHeight() {

    if(bitmap != null) {

        return bitmap.getHeight();

    } else {

        return 0;
    }
}

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

}

public void surfaceCreated(SurfaceHolder holder) {

    ballThread.setRunnable(true);
    ballThread.start();

}

public void surfaceDestroyed(SurfaceHolder holder) {

    boolean retry = true;
    ballThread.setRunnable(false);

    while(retry) {

        try {

            ballThread.join();
            retry = false;

        } catch(InterruptedException ie) {

            //Try again and again and again
        }

        break;
    }

    ballThread = null;

}

}

package com.brick.breaker;

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

public class BallThread extends Thread {

private SurfaceHolder sh;
private Ball ball;

private Canvas canvas;

private boolean run = false;

public BallThread(SurfaceHolder _holder,Ball _ball) {

    sh = _holder;
    ball = _ball;
}

public void setRunnable(boolean _run) {

    run = _run;
}

public void run() {

    while(run) {

        canvas = null;

        try {

            canvas = sh.lockCanvas(null);

            synchronized(sh) {

                ball.onDraw(canvas);
            }

        } finally {

            if(canvas != null) {

                sh.unlockCanvasAndPost(canvas);
            }

        }

    }
}

public Canvas getCanvas() {

    if(canvas != null) {

        return canvas;

    } else {

        return null;
    }
}
}

这是一张显示这些课程结果的图片。

我试图解决这个问题,但由于我对 Android 开发还很陌生,所以我想我可以寻求帮助。

有谁知道是什么原因导致球被这样画? 该代码与链接中的代码几乎相同,我尝试尝试找到解决方案但没有运气。

【问题讨论】:

    标签: android surfaceview ondraw


    【解决方案1】:

    好吧,正如您在图像上看到的,您只画了球。相反,您需要在每次绘制球之前重新绘制黑色背景(或任何您想要的)。

    或者,您可以只在前一个位置绘制黑色区域,但以后使用更多对象时可能会遇到问题。

    here's a nice sample,和你做的差不多

    【讨论】:

    • 是的,解决了我的问题,在 onDraw 方法上我添加了行 canvas.drawColor(Color.BLACK);在我画球之前,屏幕会充满黑色,消除不需要的绿色球。谢谢很多=)
    • 顺便说一句,为了获得更流畅和更快的动画效果,我建议使用 opengl。画布仅用于简单的东西,尤其是现在大多数设备仍然没有 GPU 帮助处理图形内容,因为大多数设备仍然使用“旧”的 android 版本(姜饼)。
    • 优秀的建议=) 我将弄乱上面的代码,然后创建一个新项目并执行相同的逻辑,但使用 openGL。谢谢你的小费:)
    • 有些人更喜欢使用第三方库,这些库使用 opengl 来制作动画和游戏,例如 libgdx(也可以在桌面上运行!)和andengine。
    • 另外,从 honeycomb 开始,opengl 的另一种替代方法是 renderscript :android-developers.blogspot.co.il/2011/02/…developer.android.com/guide/topics/renderscript/index.html
    【解决方案2】:

    快速浏览一下,我不得不说你只是在同一个表面上绘图,从不要求你的表面视图重绘自己。在 finally 块的末尾,在 IF 语句中使用:postInvalidate(); 这应该会导致表面视图重绘自身。

    【讨论】:

      【解决方案3】:

      放这个

      public void onDraw(Canvas canvas){
         canvas.drawColor(Color.BLACK);
      
      .....
      
      }
      

      【讨论】:

        【解决方案4】:

        看看我是如何完成钟摆模拟的 http://som-itsolutions.blogspot.in/2012/06/android-graphics-and-animation-pendulum.html

        您可以从以下位置克隆此项目的源代码 https://github.com/sommukhopadhyay/pendulumsimulation

        【讨论】:

          【解决方案5】:

          [编辑]答案是错误的,但评论很有帮助,所以我会留下这个答案:

          不是你问的问题,而是你的代码有问题。在 Android 中,您只能在 UI 线程中写入屏幕。这是运行所有 Activity 回调等的线程。通过从 BallThread 写入屏幕,您的程序可能会出现许多奇怪的故障。

          【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多