反射圆/矩形问题

时间:2017-08-07 08:42:18

标签: java collision game-physics

我正在尝试重新突破,但是在角落和球之间的互动让我头疼不已。从窗户的边缘反弹,块体工作得很好,从窗户的角落反弹也很完美。为简单起见,所有块都是轴对齐的。交换x和y移动仅适用于8个案例中的2个。对于其他6个,必须反转一个或两个向量才能使碰撞正确,但我无法想出一种方法以简单的方式做到这一点。编写8个if语句不正确,容易引起错误。

Ball类是Ellipse2D.Double类的扩展。
Block类是Rectangle类的扩展。

我看过的每个问题/答案/教程要么过于复杂(不是AA rects,矩形不在固定位置),简化(处理好像两个碰撞碰撞)或完全脱离主题(检测碰撞/重叠) ,球对球处理)。

这是我得到的:

public void move(Paddle p, List<Block> b) {
    //called every frame

    this.x += dx;
    this.y += dy;

    checkCollisionsWalls();
    // checkCollisionPaddle(p);
    checkCollisionBlocks(b);

    if (this.dir == 90 || this.dir == 270)
        this.dir++;
    // make sure ball wont get stuck between two walls of window

}

private void checkCollisionBlocks(List<Block> b) {

    for (Block block : b) {

        if (this.intersects(block)) {

            if (this.x + this.width / 2 >= block.x && this.x + this.width / 2 <= block.x + block.width) {

                System.out.println("Top / Bot reflect");
                this.dy *= -1;
                break;
            }

            if (this.y + this.height / 2 >= block.y && this.y + this.height / 2 <= block.y + block.height) {
                System.out.println("Left / Right reflect");
                this.dx *= -1;
                break;
            }

            // if execution got here we must have hit a corner
            reflectCorner();

        }
    }
}

private void reflectCorner() {

    if (dx > dy) {
        this.dy *= -1;
    } else {
        this.dx *= -1;
    }

    if (Math.abs(dx) == Math.abs(dy)) {
        this.dy *= -1;
        this.dx *= -1;
    }

    double temp = this.dx;
    this.dx = this.dy;
    this.dy = temp;
    temp = 0;

}

dx和dy是Ball类中的全局变量,实际上所有代码都是(仍然)在Ball类中。

编辑: 很抱歉看到问一个明确问题的部分,我对它有点了解......

这个当前代码发生了什么: 从任何方向击中右下角时​​,反射效果很好 击中左上角会导致球卡在直肠内。然后它沿边缘漂移到右下角
在平行于x轴移动的同时触摸右上角和在平行于y轴移动时触摸左下角时,球反射两次,在正y或正x方向上每次反弹一个像素(正交的轴正在移动) 所有其他反射都很好。

应该怎么做: reflectCorner()方法适用于所有角落,就像右下角一样,不会产生如上所述的结果。

问题: 如果没有过于复杂的if-structures,我该怎么做呢?

如有必要,我可以提供我使用的测试设置。

1 个答案:

答案 0 :(得分:0)

我终于设法让它在各方面都有效。首先,我通过检查球的中心和任何角落之间的距离是否小于/等于球的半径来计算击中了哪个角。然后我交换x和y运动。对于所有需要的两个角落,对于后两个角落,我必须根据球的角落和方向反转其中一个角落。

最后:

    <?xml version="1.0" encoding="utf-8"?>

    <android.support.v4.widget.DrawerLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            xmlns:tools="http://schemas.android.com/tools"
            android:id="@+id/drawer_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/white">

            <android.support.constraint.ConstraintLayout
                    android:id="@+id/content_frame"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:background="@android:color/white"
                    tools:context="appname.coname.com.appname" >

                    <android.support.v7.widget.Toolbar
                            android:id="@+id/global_header"
                            android:minHeight="?attr/actionBarSize"
                            android:background="@android:color/white"
                            android:layout_width="match_parent"
                            android:layout_height="64dp"
                            android:elevation="4dp">

                            <TextView
                                    android:id="@+id/global_header_title"
                                    android:layout_width="wrap_content"
                                    android:layout_height="wrap_content"
                                    android:text="@string/app_name"
                                    android:textSize="22sp"
                                    android:textColor="@color/colorPrimaryDark"
                                    android:layout_gravity="left"
                                    android:paddingLeft="10dp" />

                            <ImageView
                                    android:id="@+id/header_logo"
                                    android:layout_width="wrap_content"
                                    android:layout_height="wrap_content"
                                    android:layout_marginRight="15dp"
                                    android:layout_gravity="end"
                                    android:src="@drawable/menu_icon" />

                    </android.support.v7.widget.Toolbar>

                    <TextView
                            android:id="@+id/sample_text"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:background="#ffffff"
                            android:textColor="#000000"
                            android:text="Hello, World!"
                            app:layout_constraintBottom_toBottomOf="parent"
                            app:layout_constraintLeft_toLeftOf="parent"
                            app:layout_constraintRight_toRightOf="parent"
                            app:layout_constraintTop_toTopOf="parent" />


                    </android.support.constraint.ConstraintLayout>

            <ListView
                    android:id="@+id/left_drawer"
                    android:layout_width="240dp"
                    android:layout_height="match_parent"
                    android:layout_marginTop="64dp"
                    android:layout_gravity="start"
                    android:choiceMode="singleChoice"
                    android:divider="@android:color/transparent"
                    android:dividerHeight="0dp"
                    android:background="@android:color/white" />


    </android.support.v4.widget.DrawerLayout>

更多我不是自己的,而且相对紧凑。不过,如果有人有更简单的想法,你仍然可以回答,我会测试它。