Java/Android 子弹对象流程

标签 java android canvas 2d bulletphysics

不知道是否有人能指出我正确的方向。

我希望能够将一个对象(如子弹)从静态位置移动到屏幕上的任何区域。

我对简单的水平和垂直移动没有任何问题。 IE。 x +/- 1 或 y +/- 1。 但是,当涉及到像子弹这样的物体可以在任何程度上移动/动画时,我不太确定如何通过使动画看起来平滑来做到这一点。例如,在 18、45 或 33 度角时,像 y+1、x+1、y+1..... 这样的算法不会使动画非常平滑。

提前致谢

P.s 也许已经有一些文档了?


更新

感谢所有回复的人。

这是我迄今为止根据您的评论编写的代码。

package com.bullet;

//imports go here

public class canvas extends SurfaceView implements OnTouchListener, SurfaceHolder.Callback{

    private Bitmap bullet;
    private int bulletStartX, bulletStartY;
    private int bulletX, bulletY;
    private int bulletEndX = -1;
    private int bulletEndY = -1;
    private int incX = 0;
    private int incY = 0;

    private SurfaceHolder holder;
    private Thread t;


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

        this.setBackgroundColor(Color.WHITE);
        setFocusable(true);
        setFocusableInTouchMode(true);
        setOnTouchListener(this);

        bulletStartX = 0;
        bulletStartY = 0;

        bulletX = bulletStartX;
        bulletY = bulletStartY;

        bullet = BitmapFactory.decodeResource(getResources(), R.drawable.bullet);

        holder = getHolder();
        holder.addCallback(this);
    }

    public void onDraw(Canvas canvas){
        if(bulletEndX != -1 && bulletEndY != -1){
            Log.e("here", "drawing bullet");
            Log.e("here", "x: " + bulletX + ", y: " + bulletY);
            canvas.drawBitmap(bullet, bulletX, bulletY, null);
        }
    }

    public void updateBullet(){

        Log.e("here", "inc bullet");

        bulletX += incX;
        bulletY += incY;

        if(bulletX > bulletEndX){
            bulletEndX = -1;
        }

        if(bulletY > bulletEndY){
            bulletEndY = -1;
        }

    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {

        int[] coordinates = {(int) event.getX(), (int) event.getY()};
        int motion = event.getAction();


        switch(motion){
            case MotionEvent.ACTION_DOWN:

                break;
            case MotionEvent.ACTION_MOVE:

                break;
            case MotionEvent.ACTION_UP:
                bulletX = bulletStartX;
                bulletY = bulletStartY;
                bulletEndX = (int) event.getX();
                bulletEndY = (int) event.getY();
                incX = (int) bulletEndX / 50;
                incY = (int) bulletEndY / 50;
                Log.e("here", "touch up");
                break;
        }


        return true;
    }

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

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        t = new GameThread(this, holder);
        t.start();  
    }

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

    }

    //Thread class
    class GameThread extends Thread{
        private canvas canvas;
        private SurfaceHolder holder;
        private boolean run = false;
        long delay = 70;

        public GameThread(canvas canvas, SurfaceHolder holder){
            this.holder = holder;
            this.canvas = canvas;
            startThread(true);
        }

        public boolean isRunning(){
            return this.run;
        }

        private void startThread(boolean run){
            this.run = run;
        }

        public void stopThread(){
            this.run = false;
        }

        @Override
        public void run(){
            while(run){
                    Canvas c = null;
                     try {
                           //lock canvas so nothing else can use it
                           c = holder.lockCanvas(null);
                           synchronized (holder) {
                                //clear the screen with the black painter.
                                //This is where we draw the game engine.
                                //Log.e("drawthread", "running");
                                if(bulletEndX != -1 && bulletEndY != -1){
                                    updateBullet();
                                    canvas.postInvalidate();
                                }
                                canvas.onDraw(c);

                                //Log.e("drawthread", "ran");
                                try {
                                    sleep(32);
                                    //Log.e("slept", "sleeping");
                                } catch (InterruptedException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                }
                         }
                     } finally {
                         // do this in a finally so that if an exception is thrown
                         // during the above, we don't leave the Surface in an
                         // inconsistent state
                         if (c != null) {
                             holder.unlockCanvasAndPost(c);
                         }
                     }
            }
        }
    }
}

绘图工作得很好,但有两个问题。

1. 与这个 java 示例 http://www.youtube.com/watch?v=-g5CyPQlIo4 相比,绘图相当缓慢且跳跃...

2.如果点击的是接近Y = 0的位置,那么由于ENDY/FRAME的值小于1,意味着向上舍入为0并且项目符号穿过屏幕顶部,而不是 Y 中偶尔的增量。

@SyntaxT3rr0r 你说得对,这可能是最好的方法。但是您知道有任何实现此类功能的文档吗?

再次感谢所有回复的人

最佳答案

我的理解是,您询问的是如何确定每帧移动子弹的 x&y 像素数,而不是询问 Android 上动画特定的实现细节。

简短的回答:用数学攻击它:P 以项目符号为例:

-您可以将动画切碎为“将动画分成 100 帧,尽可能快地播放它们”或“在大约 2 秒内播放动画,在这 2 秒内尽可能多地粉碎帧” ”。我将解释前者,因为这听起来像是您想要做的。

从起始 X 和 Y 以及结束 X 和 Y 开始:假设您想要从 0,0 移动到 200,400,并且想要在大约 100 帧动画中完成此操作。

将沿 X 轴行进的总距离除以帧数。对沿 Y 轴的总距离执行相同的操作。现在您就有了每一帧的 x 和 y 行进距离。对于本示例,您希望项目符号每帧横向移动 2 个像素(200 像素/100 帧),垂直每帧移动 4 个像素(400 像素/100 帧)。所以每一帧,添加 x +=2, y+=4。

关于Java/Android 子弹对象流程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6337389/

相关文章:

java - Android - 生成随机数时崩溃

java - android:gravity ="right"不适用于阿拉伯语和其他 RTL 语言的所有设备

android - C++ 的 JNI admob 事件监听器

javascript - Chart.js 不需要的 Canvas 大小调整

java - 如何从android中的xml标签获取特定值

android - 尝试使用 uiautomatorviewer 拍摄快照时出现“adb not installed”错误

java - 对焦后Android相机拍照失败

html - 使用 CSS 或 Canvas 生成背景图像

javascript - 将 Canvas 保存到DataURL 时为空白 png

java - 当我通过 CLI 发出 Maven 命令时,如何使用 Maven 调试 Intellij 2018.3.2