2012-04-05 12 views
3

私は個人的なプロジェクトに取り組んでいます。私はまだXNAとC#(私はVisual BasicとC++でいくつかの経験があります)にはまだまだです。このプロジェクトは、実際のゲームを始める前にコードとアルゴリズムをテストするだけです。XNA 4.0ルームアルゴリズムの発見問題

私が持っている問題は、私が入力したときにマップ上に球をスポーンしようとしていますが、私は球が他人の上に出現することを望んでいません。非常に基本的な衝突検出システム。

特に、findルームは、起源で部屋を見つけることができるだけであるにもかかわらず、いくつかの奇妙な長方形を返します。また、時には別のものの上に球をスポーンするだけです。プレーヤーを球に移動させるとクラッシュするでしょう。

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

感謝のアップデートでこれを持っている - 問題があるべきであるのはここ

です見る時間がかかる。もう一度私はこのサイトを初めて知り、コーディング時に自分自身を新しいものにすべきだと思うので、ヒントや助言をいただければ幸いです。

編集:inner for loopを修正しました。むしろjを調べて増分していた。しかし、同じ問題。

編集2:FindRoomアルゴリズムは、スポットに何かがあるかどうかにかかわらず、2つのポジションのいずれかを返すようです。

編集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

私はトムのコメントがまだ問題であるかもしれないと信じています。 – kailoon

0

...フォローする最良の方法は、あなたがすぐに奇妙な振る舞い何かを見ることができますので、おそらくファイルに重要な数字をロギング、段階的にデバッグすることだろうと思う

が初期化されますint j = 0を使用するが、i++を使用する。これはcharactersの配列サイズを超えませんか?これは問題かもしれません。

+0

おっと、愚かな間違い。私がそれを修正したときにも同じ問題。 – Denora

0

これで、findRoomの無意味なレンダリングに関する作業として、私はコリジョンコードを一新しました。私は球のスポーンポイントを決定するためにランダム変数を使用しました。誰も助けてくれてありがとう。それは有り難いです。