Java/Android 子弹对象流程

发布于 2024-11-15 07:01:37 字数 5682 浏览 5 评论 0原文

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

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

我对简单的水平和垂直运动没有任何问题。即 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 你的权利,这可能是最好的方法。但是您知道有任何实现此类操作的文档吗?

再次感谢所有回复的人

Wonder if anyone could point me in the right direction.

I want to be able to animate an object like a bullet from a static position to any area on the screen.

I have no problem with simple horizontal and vertical movements. I.e. x +/- 1 or y +/- 1.
But when it comes to an object like a bullet could move/animate at any degree I'm not quite sure how to do this by making the animation look smooth. For example at 18, 45, or 33 degree angle an algorithm like y+1, x+1, y+1..... Is not going to make the animation very smooth.

Thanks in advance

P.s maybe there is some documentation out there already?


Update

Thanks to everyone who has replied.

This is the code I have so far based on your comments.

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);
                         }
                     }
            }
        }
    }
}

The drawing works pretty well, however there are two problems.

1. the drawing is fairly slow and jumpy... compared to something like this java example http://www.youtube.com/watch?v=-g5CyPQlIo4

2. If the click is on a position to close to Y = 0 then due to the value of ENDY / FRAME being less that 1, means that the round up is to 0 and the bullet travels across the top of the screen, rather than the ocassionaly increment in Y.

@SyntaxT3rr0r your right, that is prob the best way to go about it. But do you know of any documentation for implementing something like this?

Thanks again to everyone who replied

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

吃颗糖壮壮胆 2024-11-22 07:01:37

我的理解是,您询问的是如何确定每帧移动子弹的 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。

My understanding is that you're asking how to determine how many x&y pixels to move the bullet per frame, as opposed to asking about implementation details specific to animating on Android.

The short answer: Attack it with Math :P
With the example of the bullet:

-You can either chop up the animation as "divide up the animation into 100 frames, play them as fast as we can" or "Play the animation in about 2 seconds, smash as many frames in those 2 seconds as you can." I'm going to explain the former, because that sounds like what you're trying to do.

Start out with a starting X & Y, and an ending X & Y: Let's pretend you want to move from 0,0 to 200,400, and you want to do it in about 100 frames of animation.

Divide up the total distance travelled along the X axis by the number of frames. Do the same with total distance along Y axis. Now you have the distance to travel x & y for each frame. For this example, you want the bullet to move 2 pixels per frame (200 pixels / 100 frames) sideways, and 4 pixels per frame (400 pixels / 100 frames) vertically. So every frame, add x +=2, y+=4.

空宴 2024-11-22 07:01:37

我建议您阅读以下文章:

查看动画 和 < a href="http://developer.android.com/guide/topics/graphics/animation.html" rel="nofollow">属性动画

I suggest you to read the following articles:

View Animation and Property Animation

千纸鹤带着心事 2024-11-22 07:01:37

我认为目前的形式无法回答这个问题。首先你是如何制作动画的?你使用图形API吗? GL?和引擎?

如果是图形 API,我会将画布旋转适当的角度并将项目符号沿 y 轴向上移动。

对于 GL,你可以做同样的事情。

有关引擎,请参阅教程

I don't think this can be answered in it's current form. First how are you animating? are you using the graphics API? GL? AndEngine?

If is graphics API I would rotate the canvas the appropriate degree and move the bullet up the y axis.

For GL you can do the same thing.

For and engine, refer to the tutorials.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文