2016-12-13 4 views
0

3D 게임을 만들고 있습니다. 플레이어가 "카메라"입니다. 성취 된 성벽을 통과하지 않기를 바랍니다. 하지만 지금은 다른 모든 fps처럼 벽을 따라 "미끄러지 듯"움직일 수 있기를 바랍니다. 사전에 감사 : 여기에 코드입니다부드러운 3D 충돌 XNA를 얻을 수 없습니다.

protected override void Update(GameTime gameTime) 
    { 
     if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) 
      Exit(); 
     float dt = (float)gameTime.ElapsedGameTime.TotalSeconds; 

     keyState = Keyboard.GetState(); 

     camera.Update(gameTime); 

     if (keyState.IsKeyDown(Keys.W)) camera.moveVector.Z = 1; 
     if (keyState.IsKeyDown(Keys.S)) camera.moveVector.Z = -1; 
     if (keyState.IsKeyDown(Keys.A)) camera.moveVector.X = 1; 
     if (keyState.IsKeyDown(Keys.D)) camera.moveVector.X = -1; 
     if (keyState.IsKeyDown(Keys.Space)&&camera.Position.Y>=0.5f) camera.moveVector.Y = 0.5f; 

     if (camera.moveVector != Vector3.Zero) 
     { 
      //We don't want to make the player move faster when it is going diagonally. 
      camera.moveVector.Normalize(); 
      //Now we add the smoothing factor and speed factor 
      camera.moveVector *= (dt * camera.cameraSpeed); 


      Vector3 newPosition = camera.PreviewMove(camera.moveVector); 

      bool moveTrue = true; 


      if (newPosition.X < 0 || newPosition.X > Map.mazeWidth) moveTrue = false; 
      if (newPosition.Z < 0 || newPosition.Z > Map.mazeHeight) moveTrue = false; 
      foreach (BoundingBox boxes in map.GetBoundsForCell((int)newPosition.X, (int)newPosition.Z)) 
      { 
       if (boxes.Contains(newPosition) == ContainmentType.Contains) 
       { 
        moveTrue = false; 
       } 
      } 

      if (moveTrue) camera.Move(camera.moveVector); 


      base.Update(gameTime); 

는 그리고 여기에 움직임을 excecuting 코드입니다 :

 //Updating the look at vector 
     public void UpdateLookAt() 
     { 
      //Built a rotation matrix to rotate the direction we are looking 
      Matrix rotationMatrix = Matrix.CreateRotationX(cameraRotation.X) * Matrix.CreateRotationY(cameraRotation.Y); 

     // Build a look at offset vector 
     Vector3 lookAtOffset = Vector3.Transform(Vector3.UnitZ, rotationMatrix); 

     //Update our camera's look at the vector 
     cameraLookAt = (cameraPosition + lookAtOffset); 

    } 


    //Method to create movement and to check if it can move:) 
    public Vector3 PreviewMove(Vector3 amount) 
    { 
     //Create a rotation matrix to move the camera 
     Matrix rotate = Matrix.CreateRotationY(cameraRotation.Y); 

     //Create the vector for movement 
     Vector3 movement = new Vector3(amount.X, amount.Y, amount.Z); 
     movement = Vector3.Transform(movement, rotate); 

     // Give the value of the camera position +ze movement 
     return (cameraPosition+movement); 
    } 

    //Method that moves the camera when it hasnt'collided with anything 
    public void Move(Vector3 scale) 
    { 
     //Moveto the location 
     MoveTo(PreviewMove(scale), Rotation); 
    } 

이미 XNA에 의해 주어진 반전 방법을 사용하여 생각했다. 그러나 나는 정상을 찾을 수없는 것 같습니다. 그리고 저는 카메라를 벽과 평행하게 움직이려고했습니다. 그러나 나는 그것을 성취 할 수 없었다. 모든 도움이 적절합니다.

답변

0

포인트가 경계 상자와 교차하는 것을 발견했다면 엔트리 포인트가 6 개의면 중 어느면에 있는지 확인해야합니다. 다음과 같이 할 수 있습니다. 이전 카메라 위치와 새 점 사이의 선분을 만듭니다 하나

p = (1 - t) * oldPos + t * newPos 

, 당신은 얼굴에 대한 흥미 oldPosnewPos의 치수, 사용 (왼쪽/오른쪽 얼굴에 대한 예는 x 좌표를 보라). p은 얼굴에 따른 좌표입니다. 모든 얼굴에 대해 t을 계산하고 점이 이미있는 얼굴 (즉, 얼굴 법선과 얼굴에서 점까지의 내적이 음수 임)을 무시하고 최대 인 t의 얼굴을 찾습니다. 이것은 진입 점이있는 얼굴입니다. 그런 다음 경계 내에서 벗어나지 않도록 관련 좌표 (왼쪽/오른쪽면 등의 x 좌표)를 다시 적용하면됩니다 (예 : 오른쪽면의 경우 newPos.x = boundingBox.MaxX). 이것은 경계 상자 표면에 점을 투영 한 것과 같으며 교차가 발생할 경우 상자와 평행 한 이동 벡터의 구성 요소 만 사용하는 것과 같습니다.

, BTW 상기 식의 솔루션입니다 :

t = (p - oldPos)/(newPos - oldPos) 
+0

아픈 오늘 오후 덕분에 그것을 시도! – Jeromer