2012-04-05 2 views
3

저는 개인 프로젝트에서 일하고 있는데 XNA와 C# (저는 Visual Basic과 C++에서 약간의 경험이 있습니다)에 대해서도 매우 익숙합니다. 이 프로젝트는 실제 게임을 시작하기 전에 코드와 알고리즘을 테스트하는 것입니다.XNA 4.0 룸 알고리즘 찾기 문제

내가 겪고있는 문제는 내가 입력 할 때지도에서 구를 만들려고하는데, 왜냐하면 내가 구를 만들었 기 때문에 구가 서로 또는 플레이어 위에 스폰되고 싶지 않기 때문입니다. 매우 기본적인 충돌 감지 시스템.

문제는 특히 원점에서 방을 찾을 수 있어야하는 경우에도 찾기 실에서 이상한 직사각형을 반환합니다. 또한 때로는 다른 구형 위에 구를 스폰합니다. 플레이어를 구체로 옮기면 충돌이 발생합니다.

 if (currentKeyState.IsKeyDown(Keys.Enter) && newBallDelay == 0) 
     { 
      Npcs newBall = new Npcs(); 
      //find room 
      Rectangle rect; 
      if (findRoom(newBall, ref rect)) 
      { 
       newBall.postion = new Vector2(rect.X, rect.Y); 
       characters.Add(newBall); //adds to a list of Npcs which is drawn in a foreach loop 
       newBallDelay = 1; //prevents from adding too many spheres at once 
      } 
     } 

bool findRoom(Npcs newObject, ref Rectangle rectObject) 
    { 
     Rectangle player = new Rectangle((int)spritelocation.X, (int)spritelocation.Y, (int)sprite.Bounds.Width/4, (int)sprite.Bounds.Height/4); 
     Rectangle check; 
     for (int i = 0; i < characters.Count; i++) 
     { 
      check = new Rectangle((int)characters[i].postion.X, (int)characters[i].postion.Y, (int)characters[i].size.X, (int)characters[i].size.Y); 
      for (int j = 0; j < 50; j++) 
      { 
       rectObject = new Rectangle(i * (int)newObject.size.X * 2, j * (int)newObject.size.Y * 2, (int)newObject.size.X, (int)newObject.size.Y); //size.X and size.Y are the height and width of the object, this creates rectangular grid to check through. 
       if (!rectObject.Intersects(player) && !rectObject.Intersects(check)) 
        return (true); 
      } 
     } 

     return (false); 
    } 

를 호출하는 나는 그것이 관련이 의심하지만 newballdelay, 나는이

 if (newBallDelay > 0) 
     { 
      newBallDelay++; 
      if (newBallDelay == 50) 
       newBallDelay = 0; 
     } 

감사에 대한 갱신이이 - 문제가 거짓말을해야하는 위치 여기

입니다 볼 시간을내어. 다시 사이트를 처음 접해 보니 코드 작성시 새로운 것을 고려해야하므로 팁이나 조언을 부탁드립니다.

편집 : 루프 내부 수정. 오히려 j를 확인하고 증가시키는 것이 었습니다. 그래도 같은 문제.

편집 2 : FindRoom 알고리즘은 그 자리에 무언가가 있는지에 관계없이 두 위치 중 하나를 반환하는 것으로 보입니다.

편집 3 : 스프라이트를 올바르게 감지하려면 스프라이트 사각형의 높이와 너비를 4로 나누어야합니다.

여기에 도움이된다면 (죄송이 지저분이고, 나는 아직도 배우고 적절한 규칙을 준수하지 않는 경우)

public class Game1 : Microsoft.Xna.Framework.Game 
{ 
    GraphicsDeviceManager graphics; 
    SpriteBatch spriteBatch; 

    Texture2D sprite; 
    Texture2D background; 
    Texture2D sphere; 

    bool walking = false; 
    int walkSpeed = 2; 
    int newBallDelay = 0; 
    //bool jump = false; 

    int runSpeed = 5; 
    int frame = 0; 
    Random rand = new Random(); 

    int walkdir = 3; //0 = down, 1 = left, 2 = right, 3 = up 
    Vector2 spritelocation = new Vector2(0,0); 

    int imageH = 0; 
    int imageW = 0; 
    float elapsed = 0; 

    private const int Frames = 4; 
    private float frameSpeed = 0.15f; 

    List<Npcs> characters = new List<Npcs>(); 
    Npcs ball = new Npcs(); 
    Npcs ball2 = new Npcs(); 
    Camera2d cam = new Camera2d(); 

    private SpriteBatch batch; 
    SpriteFont Font1; 
    Vector2 FontPos; 

    public Game1() 
    { 

     graphics = new GraphicsDeviceManager(this); 
     Content.RootDirectory = "Content"; 
    } 

    protected override void Initialize() 
    { 
     // TODO: Add your initialization logic here 
     IsMouseVisible = true; 
     Window.AllowUserResizing = true; 
     base.Initialize(); 
    } 

    protected override void LoadContent() 
    { 
     // Create a new SpriteBatch, which can be used to draw textures. 
     ball.size = (new Vector2(50, 50)); 
     ball.postion = (new Vector2(50, 50)); 
     characters.Add(ball); 

     ball2.size = (new Vector2(50, 50)); 
     ball2.postion = (new Vector2(160, 80)); 
     characters.Add(ball2); 
     spriteBatch = new SpriteBatch(GraphicsDevice); 
     sprite = Content.Load<Texture2D>("sprite\\scaled"); 
     background = Content.Load<Texture2D>("sprite\\grass"); 
     sphere = Content.Load<Texture2D>("sprite\\ball"); 
     imageW = sprite.Bounds.Width; 
     imageH = sprite.Bounds.Height; 
     cam.Pos = new Vector2(350, 50); 
     //cam.Rotation = 0.5f; 
     // cam.Zoom = 2.0f // Example of Zoom in 
     // cam.Zoom = 0.5f // Example of Zoom out 

     spriteBatch = new SpriteBatch(GraphicsDevice); 
     Font1 = Content.Load<SpriteFont>("LucidaConsole"); 

     batch = new SpriteBatch(this.graphics.GraphicsDevice); 

     FontPos = new Vector2(graphics.GraphicsDevice.Viewport.Width - 90, 20); 
    } 

    protected override void UnloadContent() 
    { 
     // TODO: Unload any non ContentManager content here 
    } 

    protected override void Update(GameTime gameTime) 
    { 
     // Allows the game to exit 
     if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) 
      this.Exit(); 
     getInput(); 
     // TODO: Add your update logic here 

     elapsed += (float)gameTime.ElapsedGameTime.TotalSeconds; 

     //Delay for ball 
     if (newBallDelay > 0) 
     { 
      newBallDelay++; 
      if (newBallDelay == 50) 
       newBallDelay = 0; 
     } 

     checkCollsion(); 

     base.Update(gameTime); 
    } 

    protected override void Draw(GameTime gameTime) 
    { 
     graphics.PreferredBackBufferWidth = 1366; 
     graphics.PreferredBackBufferHeight = 728; 
     graphics.GraphicsDevice.Clear(Color.CornflowerBlue); 

     // TODO: Add your drawing code here 
     //// if using XNA 4.0 
     spriteBatch.Begin(SpriteSortMode.BackToFront,BlendState.AlphaBlend,null,null,null,null, cam.get_transformation(null)); 

     //spriteBatch.Draw(background, new Vector2(-2000,-2000), new Rectangle(0,0,4000,4000), Color.White); 

     for (int i = 0; i < characters.Count(); i++) 
     { 
      spriteBatch.Draw(sphere, characters[i].postion, new Rectangle(0, 0, (int)Math.Round(characters[i].size.X), (int)Math.Round(characters[i].size.Y)), Color.White); 
     } 

     elapsed += (int)gameTime.ElapsedGameTime.TotalSeconds; 
     while (elapsed > frameSpeed && walking) 
     { 
      frame++; 
      elapsed = 0; 
      frame = frame % Frames; 
     } 

     if (!walking) 
      spriteBatch.Draw(sprite, spritelocation, new Rectangle(0, walkdir * (imageH/4), (imageW/4), (imageH/4)), Color.White); 
     else 
      spriteBatch.Draw(sprite, spritelocation, new Rectangle(frame * (imageW/4), walkdir * (imageH/4), (imageW/4), (imageH/4)), Color.White); 

     spriteBatch.End(); 

     base.Draw(gameTime); 

    } 


    protected void getInput() //Recieves keyboard input 
    { 
    KeyboardState currentKeyState = Keyboard.GetState(); 
     if (currentKeyState.IsKeyDown(Keys.Up)) 
     { 
      walkdir = 3; 
      walking = true; 
      if ((currentKeyState.IsKeyDown(Keys.LeftShift))) 
      { 
       frameSpeed = 0.05f; 
       spritelocation.Y -= runSpeed; 
       cam.Move(new Vector2(0, -runSpeed)); 
      } 
      else 
      { 
       frameSpeed = 0.15f; 
       spritelocation.Y -= walkSpeed; 
       cam.Move(new Vector2(0, -walkSpeed)); 
      } 
     } 
     else if (currentKeyState.IsKeyDown(Keys.Down)) 
     { 
      walkdir = 0; 
      walking = true; 
      if ((currentKeyState.IsKeyDown(Keys.LeftShift))) 
      { 
       frameSpeed = 0.05f; 
       spritelocation.Y += runSpeed; 
       cam.Move(new Vector2(0, runSpeed)); 
      } 
      else 
      { 
       frameSpeed = 0.15f; 
       spritelocation.Y += walkSpeed; 
       cam.Move(new Vector2(0, walkSpeed)); 
      } 
     } 
     else if (currentKeyState.IsKeyDown(Keys.Right)) 
     { 
      walkdir = 2; 
      walking = true; 
      if ((currentKeyState.IsKeyDown(Keys.LeftShift))) 
      { 
       frameSpeed = 0.05f; 
       spritelocation.X += runSpeed; 
       cam.Move(new Vector2(runSpeed, 0)); 
      } 
      else 
      { 
       frameSpeed = 0.15f; 
       spritelocation.X += walkSpeed; 
       cam.Move(new Vector2(walkSpeed, 0)); 
      } 
     } 
     else if (currentKeyState.IsKeyDown(Keys.Left)) 
     { 
      walkdir = 1; 
      walking = true; 
      if ((currentKeyState.IsKeyDown(Keys.LeftShift))) 
      { 
       frameSpeed = 0.05f; 
       spritelocation.X -= runSpeed; 
       cam.Move(new Vector2(-runSpeed, 0)); 
      } 
      else 
      { 
       frameSpeed = 0.15f; 
       spritelocation.X -= walkSpeed; 
       cam.Move(new Vector2(-walkSpeed, 0)); 
      } 
     } 
     else 
     { 
      walking = false; 
      frameSpeed = 1f; 
     } 

     if (currentKeyState.IsKeyDown(Keys.Enter) && newBallDelay == 0) 
     { 
      Npcs newBall = new Npcs(); 
      //find room 
      Rectangle rect = new Rectangle(0,0,(int)newBall.size.X,(int)newBall.size.Y); 
      if (findRoom(newBall, ref rect)) 
      { 
       newBall.postion = new Vector2(rect.X, rect.Y); 
       characters.Add(newBall); 
       newBallDelay = 1; 
      } 
     } //if enter key is hit 
    } //get input 


bool findRoom(Npcs newObject, ref Rectangle rectObject) 
{ 
    Rectangle player = new Rectangle((int)spritelocation.X, (int)spritelocation.Y,  (int)sprite.Bounds.Width/4, (int)sprite.Bounds.Height/4); 
    Rectangle check; 
    for (int i = 0; i < characters.Count; i++) 
    { 
     check = new Rectangle((int)characters[i].postion.X, (int)characters[i].postion.Y, (int)characters[i].size.X, (int)characters[i].size.Y); 
     for (int j = 0; j < 50; j++) 
     { 
      rectObject = new Rectangle(i * (int)newObject.size.X * 2, j * (int)newObject.size.Y * 2, (int)newObject.size.X, (int)newObject.size.Y); //size.X and size.Y are the height and width of the object, this creates rectangular grid to check through. 
      if (!rectObject.Intersects(player) && !rectObject.Intersects(check)) 
       return (true); 
     } 
    } 

    return (false); 
} 


    void checkCollsion(Npcs character, int index) 
    { 
     Rectangle char1 = new Rectangle((int)character.postion.X, (int)character.postion.Y, (int)character.size.X, (int)character.size.Y); 
     Rectangle char2 = new Rectangle(); 
     for (int i = 0; i < characters.Count(); i++) 
     { 
      if (i != index) 
      { 
       char2 = new Rectangle((int)characters[i].postion.X, (int)characters[i].postion.Y, (int)characters[i].size.X, (int)characters[i].size.Y); 
       if (char1.Intersects(char2)) 
       { 
        characters[i].hit(walkdir, (int)character.speed); 
        checkCollsion(characters[i], i); 
       } 
      } 
     } 
     character.speed = 0.0f; 
    } 

    void checkCollsion() 
    { 
     Rectangle char1 = new Rectangle((int)spritelocation.X, (int)spritelocation.Y, (int)sprite.Bounds.Width/4 - 10, (int)sprite.Bounds.Height/4 - 15); 
     Rectangle char2 = new Rectangle(); 
     for (int i = 0; i < characters.Count(); i++) 
     { 
       char2 = new Rectangle((int)characters[i].postion.X, (int)characters[i].postion.Y, (int)characters[i].size.X, (int)characters[i].size.Y); 
       if (char1.Intersects(char2)) 
       { 
        characters[i].hit(walkdir, runSpeed); 

        checkCollsion(characters[i], i); 
       } 

     } 
    } 
} 

답변

3

난 더 이상 가능한 실수를 볼 수 없습니다 내 모든 코드,하지만 문맥을 모른다.

나는 당신은 루프 내부있어 신속 이상한 행동 무언가를 볼 수 있도록 아마도 파일에 중요한 숫자를 기록, 단계적으로 디버깅 할 것이다 따라야 할 가장 좋은 방법 ...

+0

사각형이 시작되는 곳의 X, Y 부분과 문제가 발생하지 않는 곳을 확인하면됩니다. – Denora

+0

내부 루프는 int j = 0을 초기화하지만 i++을 사용 중입니다. 이것은 characters 배열 크기를 넘지 않습니까? – kailoon

+0

나는 Tom의 코멘트가 여전히 문제일지도 모른다. – kailoon

0

가 초기화되는 생각 int j = 0이지만 i++을 사용하십시오. 이것은 characters 배열 크기를 넘지 않습니까? 이것은 문제 일 수 있습니다.

+0

으악, 어리석은 실수. 그래도 고칠 때 같은 문제가 ... – Denora

0

좋아, findRoom을 무의미하게 렌더링하는 작업으로 내 충돌 코드를 기초부터 수정했습니다. 또한 임의의 변수를 사용하여 구의 스폰 지점을 결정했습니다. 여러분 모두를 도와 주셔서 감사합니다. 감사합니다.