문제

저는 마우스를 드래그할 수 있는 매우 간단한 Java 애플리케이션을 작성했습니다. 마우스를 드래그한 길이에 따라 공이 해당 방향으로 발사되어 벽에 부딪혀 튕겨 나옵니다.

다음은 간단한 스크린샷입니다.
대체 텍스트 http://img222.imageshack.us/img222/3179/ballbouncemf9.png

화면의 각 원은 공 개체입니다.공의 움직임은 x 및 y 벡터로 분류됩니다.

public class Ball {
    public int xPos;
    public int yPos;
    public int xVector;
    public int yVector;

    public Ball(int xPos, int yPos, int xVector, int yVector) {
        this.xPos = xPos;
        this.yPos = yPos;
        this.xVector = xVector;
        this.yVector = yVector;
    }

    public void step()
    {
        posX += xVector;
        posY += yVector;

        checkCollisions();
    }

    public void checkCollisions()
    {
        // Check if we have collided with a wall
        // If we have, take the negative of the appropriate vector
        // Depending on which wall you hit
    }

    public void draw()
    {
        // draw our circle at it's position
    }
}

이것은 훌륭하게 작동합니다.모든 공은 벽에서 벽으로 이리저리 튕겨 나옵니다.

그러나 나는 중력의 효과를 포함할 수 있기를 원한다고 결정했습니다.나는 물체가 지구를 향해 9.8m/s의 속도로 가속된다는 것을 알고 있지만 이것이 어떻게 코드로 변환되어야 하는지 직접적으로 알지 못합니다.나는 yVector가 영향을 받을 것이라는 것을 알고 있지만 이것에 대한 나의 실험은 내가 원하는 효과를 얻지 못했습니다.

이상적으로는, 나는 이 프로그램에 중력 효과를 추가하고 공이 "지면"에 안착되기 전에 몇 번 튀는 것을 허용하고 싶습니다.

탄력 있고 탄력 있는 중력 효과를 어떻게 만들 수 있나요?각 단계에서 공의 속도 벡터를 어떻게 조작해야 합니까?그것이 다시 튀어오를 수 있도록 하기 위해 그것이 "지면"에 부딪혔을 때 무엇을 해야 합니까? 그러나 이전 시간보다 다소 짧습니까?

나를 올바른 방향으로 안내하는 데 도움을 주시면 감사하겠습니다.


다들 댓글 감사드립니다!이미 훌륭하게 작동하고 있습니다!

내 step()에서는 사람들이 제안한 것처럼 yVector에 중력 상수를 추가하고 있으며 이것이 내 checkCollision()입니다.

public void checkCollision()
{
    if (posX - radius < 0)              // Left Wall?
    {
        posX = radius;              // Place ball against edge
        xVector = -(xVector * friction);
    }
    else if (posX + radius > rightBound) // Right Wall?
    {
        posX = rightBound - radius;     // Place ball against edge
        xVector = -(xVector * friction);
    }

    // Same for posY and yVector here.
}

그러나 공은 계속 바닥에서 미끄러지거나 굴러갑니다.나는 이것이 단순히 바운스될 때마다 벡터의 백분율(90%)을 취하고 실제로 0이 아니기 때문이라고 가정합니다.xVector가 특정 절대값이 되면 이를 0으로 변경해야 하는지 확인하는 기능을 추가해야 합니까?

도움이 되었습니까?

해결책

당신이해야 할 일은 Yvector에서 작은 상수 (9.8 m/s를 나타내는)를 지속적으로 빼는 것입니다. 공이 내려 가면 (Yvector가 이미 부정적이면) 더 빨리 갈 것입니다. 올라갈 때 (YVECTOR는 양수) 속도가 느려집니다.

이것은 마찰을 설명하지 않으므로 물건은 거의 튀어 나와야합니다.

edit1 : 마찰을 설명하기 위해, 반전 될 때마다 (그리고 부호를 뒤집을 때마다) 절대 숫자를 약간 낮 춥니 다. yvector = -500에서 치는 것처럼, 부호를 뒤집을 때 +500 대신 +480을 만드십시오. 당신은 아마도 xvector와 똑같은 일을하여 좌우로 튀는 것을 막아야합니다.

edit2 : 또한 "공기 마찰"에 반응하기를 원한다면 조정마다 두 벡터를 매우 적은 양으로 줄입니다.

edit3 : 숫자가 얼마나 높은지에 대한 바닥에 롤업하는 것에 대해 두 가지 중 하나 일 수 있습니다. 숫자가 크고 끝나는 데 영원히 걸리는 것 같습니다. 또는 반올림이 있고 벡터는 항상 5 또는 무언가입니다. (5의 90%는 4.5이므로 최대 5 명을 반올림 할 수 있습니다).

디버그 문을 인쇄하고 벡터 번호가 어떤지 확인했습니다. 그들이 5 시쯤 어딘가에 가서 거기에 머물면 5로 반올림하는 대신 분수를 4로 자르는 함수를 사용할 수 있습니다. .

쉬운 "반올림"함수를 찾을 수 없으면 (0.9 * 벡터) -1을 사용할 수 있으며 기존 방정식에서 1을 빼면 같은 일을해야합니다.

다른 팁

공이 모두 땅 위에서 굴러다니면 속도가 특정 최소값보다 낮은지 확인하고 그렇다면 속도를 0으로 설정하세요.이러한 유형의 이상적인 모션 뒤에 숨어 있는 물리학을 살펴보고 실제 세계에서 일어나는 일과 비교해 보면 실제 공이 움직이지 않는다는 사실을 설명하는 데 단일 방정식을 사용할 수 없다는 것을 알 수 있습니다.

그런데, 당신이 하고 있는 일은 수치 적분을 위한 오일러 방법이라고 합니다.다음과 같이 진행됩니다.

  • 운동의 운동 방정식으로 시작하십시오.
    x(t) = x0 + vx*t + 0.5*axt^2
    y(t) = y0 + vy
    t + 0.5*ayt^2
    vx(t) = vx0 + 도끼

    vy(t) = vy0 + ay*t
    여기서 x와 y는 위치, vx와 vy는 속도, ax와 ay는 가속도, t는 시간입니다.x0, y0, vx0 및 vy0은 초기 값입니다.이는 외부 힘이 없을 때 물체의 운동을 설명합니다.

  • 이제 중력을 적용합니다.
    ay = -9.8m/s^2
    이 시점에서는 까다로운 작업을 수행할 필요가 없습니다.우리는 언제든지 이 방정식을 사용하여 각 공의 위치를 ​​풀 수 있습니다.

  • 이제 공기 마찰을 추가합니다.구형 공이기 때문에 마찰 계수 c를 갖는다고 가정할 수 있습니다.공기 마찰을 모델링하는 방법에는 일반적으로 두 가지 선택이 있습니다.이는 속도에 비례하거나 속도의 제곱에 비례할 수 있습니다.사각형을 사용해 봅시다:
    도끼 = -cvx^2
    아이 = -c
    vy^2 - 9.8
    이제 가속도는 일정하지 않은 속도에 따라 달라지므로 적분해야 합니다.이 문제를 직접 해결할 수 있는 방법이 없기 때문에 이것은 좋지 않습니다.수치적으로 통합해야 합니다.

  • 우리는 이산적인 시간 단계를 취합니다. dt.오일러 방법의 경우 위 방정식에서 모든 t 발생을 dt로 바꾸고 초기 값 x0, y0 등 대신 이전 시간 단계의 값을 사용합니다.이제 방정식은 다음과 같습니다(의사 코드).

    // 이전 값 저장
    xold = x;
    욜드 = y;
    vxold = vx;
    vyold = vy;

    // 가속 업데이트
    도끼 = -cvxold^2;
    아이 = -c
    vyold^2 - 9.8;

    // 속도 업데이트
    vx = vxold + 도끼dt;
    vy = vyold + 에이
    dt;

    // 위치 업데이트
    x = xold + vxold*dt + 0.5*axdt^2;
    y = 욜드 + 비올드
    dt + 0.5*ay*dt^2;

이는 근사치이므로 정확하지는 않지만 괜찮아 보일 것입니다.문제는 시간 단계가 클수록 오류가 증가한다는 것입니다. 따라서 실제 공이 어떻게 움직이는지 정확하게 모델링하려면 dt에 매우 작은 값을 사용해야 하며, 이는 컴퓨터의 정확도에 문제를 일으킬 수 있습니다.이를 해결하려면 더 복잡한 기술이 있습니다.그러나 중력과 마찰처럼 보이는 동작을 동시에 보고 싶다면 오일러의 방법이 좋습니다.

슬라이스 할 때마다 공을 아래로 방향으로 가속하여 중력의 영향을 적용해야합니다. Bill K가 제안한 바와 같이, 그것은 당신의 "yvector"에서 뺄셈을하는 것만 큼 간단합니다. 공이 바닥에 닿으면 yvector = -yvector이므로 이제 위쪽으로 이동하지만 여전히 아래쪽으로 가속화됩니다. 공이 결국 튀는 것을 멈추게하려면 기본적으로 "yvector = -yvector"대신에 약간의 속도를 제거하여 충돌을 약간 비탄성으로 만들어야합니다. "yvector = -0.9로 만드십시오. * yvector ".

public void step()
{
    posX += xVector;
    posY += yVector;

    yVector += g //some constant representing 9.8

    checkCollisions();
}

CheckCollisions ()에서는지면에서 튀어 나올 때 Yvector를 0에서 1 사이의 숫자로 반전시키고 곱해야합니다. 이것은 당신에게 원하는 효과를 줄 것입니다

탄도 운동입니다. 그래서 당신은 x 축에 선형 움직임과 y 축에서 균일 한 가속 운동을 얻었습니다.

기본 아이디어는 y 축이 방정식을 따른다는 것입니다.

y = y0 + v0 * t + (0.5)*a*t^2

또는 C 코드에서 예를 들어 :

float speed = 10.0f, acceleration = -9.8f, y = [whatever position];

y += speed*t + 0.5f*acceleration*t^2;

여기서 나는 tiem 매개 변수화를 사용합니다. 그러나 당신은 torricelli를 사용할 수 있습니다 :

v = sqrt(v0^2 + 2*acceleration*(y-y0));

그리고이 모델에서는 v와 y의 마지막 값을 유지해야합니다.

마지막으로, DT (Time 's Different)가 1/60 초 (60fps)로 고정 된 첫 번째 모델을 사용하여 비슷한 일을했습니다.

글쎄, 두 모델 모두 좋은 실제 결과를 제공하지만 예를 들어 SQRT ()는 비싸다.

당신은 정말로 중력이하는 일을 시뮬레이션하고 싶습니다. 시간이 지남에 따라 행동하는 힘을 만들어 물체의 속도를 바꾸는 것입니다. 한 단계마다, 위젯의 바닥을 향해 "당기"하기 위해 공의 속도를 약간 변경합니다.

비 화려 / 튀는 공 정착 문제를 처리하려면 "지상"충돌이 엄격한 반사와 다른 효과를 발휘해야합니다. 공에서 약간의 에너지를 제거하여 공에서 약간의 에너지를 제거해야합니다. 지면에 부딪친 후 더 작은 속도.

이러한 유형의 탄력 시각화에서 일반적으로하고 싶은 또 다른 일은 땅에 약간의 마찰을 주므로 항상 땅에 부딪 칠 때 결국 멈출 수 있습니다.

나는 "Bill K"가 말한 것에 동의하고, 당신이 그들이 "정착"하기를 원한다면 시간이 지남에 따라 X와 Y 벡터를 줄여야한다고 덧붙일 것입니다 (저항을 적용). 이것은 한 번에 매우 적은 양이어야하므로 벡터를 INT에서 부동 소수점 유형으로 변경하거나 몇 초마다 1만큼만 줄여야 할 수도 있습니다.

당신이 원하는 것은 xVector와 yVector의 값을 변경하여 중력과 마찰을 시뮬레이션하는 것입니다.이것은 정말 간단합니다.(모든 변수를 부동 소수점으로 변경해야 합니다.그릴 때가 되면 수레를 둥글게 둥글게 만드세요.)

단계 함수에서 공의 위치를 ​​업데이트한 후 다음과 같이 해야 합니다.

yVector *= 0.95;
xVector *= 0.95;
yVector -= 2.0;

이렇게 하면 X 및 Y 속도가 약간 줄어들어 공이 결국 움직이지 않게 된 다음 Y 값에 지속적인 하향 "가속"이 적용되어 "감속"보다 빠르게 누적되어 공이 떨어지게 됩니다.

이것은 당신이 정말로 하고 싶은 일의 대략적인 것입니다.당신이 정말로 원하는 것은 공의 가속도를 나타내는 벡터를 유지하는 것입니다.그런 다음 모든 단계에서 해당 벡터에 일정한 중력 벡터를 곱하여 공의 가속도를 약간 변경합니다.하지만 더 현실적인 물리 시뮬레이션을 찾고 있지 않는 한, 원하는 것보다 더 복잡하다고 생각합니다.

다시 튀어 오를 수 있도록 "지상"에 부딪 칠 때해야 할 일

완벽한 충돌을 가정하면 (즉, 모든 에너지가 보존 됨) 어떤 벽에 히트 한 벽에 따라 속도 스칼라 중 하나의 부호를 뒤집어야합니다.

예를 들어, 공이 오른쪽 또는 왼쪽 벽에 닿는 경우 X 스칼라 구성 요소를 다시 말하고 y 스칼라 구성 요소를 동일하게 남겨 둡니다.

 this.xVector = -this.xVector;

볼이 상단 또는 하단 벽에 닿는 경우 Y 스칼라 구성 요소를 뒤집고 X 스칼라 구성 요소를 동일하게 남겨 둡니다.

 this.yVector = -this.yVector;

그러나 이전 시간보다 다소 짧습니까?

이 시나리오에서는 벽과 충돌 할 때 일부 에너지가 손실되므로 벽에 맞을 때마다 일부 속도를 취할 수있는 손실 계수를 추가하십시오.

 double loss_factor = 0.99;
 this.xVector = -(loss_factor * this.xVector);
 this.yVector = -(loss_factor * this.yVector;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top