2012-12-30 207 views
0

对于学校我需要在XNA中制作这个游戏项目我选择制作基于马里奥的游戏。 但是我现在一直在研究我的碰撞检测,但我仍然无法找到问题。XNA碰撞检测

这里是链接到项目: ProjectMario

奥凯所以这是它做什么。 enter image description here

这是我的代码

TileManager

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using Microsoft.Xna.Framework; 
using Microsoft.Xna.Framework.Audio; 
using Microsoft.Xna.Framework.Content; 
using Microsoft.Xna.Framework.GamerServices; 
using Microsoft.Xna.Framework.Graphics; 
using Microsoft.Xna.Framework.Input; 
using Microsoft.Xna.Framework.Media; 
using Microsoft.Xna.Framework.Net; 
using Microsoft.Xna.Framework.Storage; 

namespace mariospeed.ManagerClasses 
{ 
    class TileManager 
    { 
     int[,] tilemap; 
     int tilesize; 
     int mapSizeX; 
     int mapSizeY; 
     int tileindex; 
     Texture2D tex; 
     List<Texture2D> texlis; 
     public List<Rectangle> blocks; 
     public List<Rectangle> blocksTop; 
     public List<Rectangle> blocksLeft; 
     public List<Rectangle> blocksRight; 
     public List<Rectangle> tile; 
     public int mapX; 
     public int MapW; 



     public TileManager() 
     { 
      tilemap = new int[,] 
      { 
       {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
       {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
       {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
       {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0}, 
       {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, 
       {0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1,1,0,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0}, 
       {0,0,0,0,0,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
       {1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
       {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
       {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
       {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
       {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} 
      }; 


      tilesize = 28; 
      texlis = new List<Texture2D>(); 
      mapSizeX = tilemap.GetLength(1); 
      mapSizeY = tilemap.GetLength(0); 
      blocks = new List<Rectangle>(); 
      blocksTop = new List<Rectangle>(); 
      blocksLeft = new List<Rectangle>(); 
      blocksRight = new List<Rectangle>(); 
      tile = new List<Rectangle>(); 
      mapX = 0; 



      for (int x = 0; x < mapSizeX; x++) 
      { 
       for (int y = 0; y < mapSizeY; y++) 
       { 
        if (tilemap[y, x] == 1) 
        { 
         blocks.Add(new Rectangle(x * tilesize - mapX, y * tilesize, 28, 30)); 

        } 
       } 
      } 

      foreach (Rectangle block in blocks) 
      { 
       blocksTop.Add(new Rectangle(block.Center.X, block.Top, block.Width, block.Height)); 
      } 
      foreach (Rectangle block in blocks) 
      { 
       blocksLeft.Add(new Rectangle(block.Left, block.Y, 1, block.Height)); 
      } 
      foreach (Rectangle block in blocks) 
      { 
       blocksRight.Add(new Rectangle(block.Right, block.Y, block.Width/2, block.Height)); 
      } 


      for (int x = 0; x < mapSizeX; x++) 
      { 
       for (int y = 0; y < mapSizeY; y++) 
       { 
        tile.Add(new Rectangle(x * tilesize, y * tilesize, 28, 30)); 
       } 
      } 

      MapW = tilesize * mapSizeX; 


     } 
      // 

     public void LoadContent(Texture2D tex1, Texture2D tex2) 
     { 
      texlis.Add(tex1); 
      texlis.Add(tex2); 

     } 

     public void Draw(SpriteBatch sp) 
     { 

      for (int i = 0; i < mapSizeX; i++) 
      { 
       for (int j = 0; j < mapSizeY; j++) 
       { 
        tileindex = tilemap[j, i]; 
        tex = texlis[tileindex]; 


        sp.Draw(tex, new Rectangle(i * 28 - mapX, j * 30, 28, 30), Color.White); 

       } 

      } 

     } 

    } 
} 

Mario Class 

    using System; 
using System.Collections.Generic; 
using System.Linq; 
using Microsoft.Xna.Framework; 
using Microsoft.Xna.Framework.Audio; 
using Microsoft.Xna.Framework.Content; 
using Microsoft.Xna.Framework.GamerServices; 
using Microsoft.Xna.Framework.Graphics; 
using Microsoft.Xna.Framework.Input; 
using Microsoft.Xna.Framework.Media; 
using mariospeed.GameScenes; 


namespace mariospeed.GameComponents 
{ 
    /// <summary> 
    /// This is a game component that implements IUpdateable. 
    /// </summary> 
    public class Mario : Microsoft.Xna.Framework.DrawableGameComponent 
    { 

     Texture2D texture2; 
     public Vector2 cameraPosition; 
     public Vector2 worldPosition; 
     public Rectangle rectangle; 
     public Rectangle footBounds; 
     public Rectangle leftRec; 
     public Rectangle rightRec; 
     KeyboardState keystate; 
     KeyboardState oldkeys; 
     public string facing; 
     public string state; 
     public bool jump; 
     float jumpSpeed; 
     public float gravity; 

     public float speed; 
     float time; 
     public string prevstate; 
     Point frameSize; 
     Point sheetSize; 
     Point currentFrame; 
     public Rectangle source; 
     float interval; 
     // 
     Texture2D charr; 
     Vector2 charPos; 
     bool jumping; //Is the character jumping? 
     public float startY, jumpspeed = 0; //startY to tell us //where it lands, jumpspeed to see how fast it jumps 
     protected Texture2D texture; 
     protected Vector2 position = new Vector2(); 

     protected const int WIDTH = 64; 
     protected const int HEIGHT = 80; 

     protected Rectangle screenBounds; 

     protected List<Rectangle> frames; // hierin de grenzen v/d frames 
     private int activeFrame; 
     public Mario(Game game, Texture2D texture) 
      : base(game) 
     { 
      this.texture = texture; 
      screenBounds = new Rectangle(0, 0, 
       Game.Window.ClientBounds.Width, Game.Window.ClientBounds.Height); 

      frames = new List<Rectangle>(); 

      CreateFrames(); 
      activeFrame = 0; 
      PutInStartPosition(); 

      charr = texture; //Load image 
      charPos = new Vector2(230, 450);//Char loc, X/Y 
      startY = charPos.Y;//Starting position 
      jumping = false;//Init jumping to false 
      jumpspeed = 0;//Default no speed 

      // 
      cameraPosition = new Vector2(0, 0); 
      worldPosition = new Vector2(40, 0); 
      startY = worldPosition.Y; 
      facing = "right"; 
      prevstate = state; 
      state = "stand"; 
      jump = false; 
      gravity = 0f; 
      speed = 5f; 
      frameSize = new Point(28, 30); 
      sheetSize = new Point(6, 7); 
      currentFrame = new Point(0, 0); 
      time = 0f; 
      interval = 100f; 
      // 
     } 
     public void PutInStartPosition() 
     { 
      position.X = 10; 
      position.Y = (screenBounds.Height - (texture.Height+18)); 

     } 

     public Vector2 marioPosition() 
     { 
      return position; 
     } 
     public void CreateFrames() 
     { 

      frames.Add(new Rectangle(0, 0, WIDTH, HEIGHT)); 
      frames.Add(new Rectangle(WIDTH, 0, WIDTH, HEIGHT)); 
      frames.Add(new Rectangle(2*WIDTH, 0, WIDTH, HEIGHT)); 
      // frames.Add(new Rectangle(3*WIDTH, 0, WIDTH, HEIGHT)); 

     } 




     /// <summary> 
     /// Allows the game component to perform any initialization it needs to before starting 
     /// to run. This is where it can query for any required services and load content. 
     /// </summary> 
     public override void Initialize() 
     { 
      // TODO: Add your initialization code here 

      base.Initialize(); 
     } 

     /// <summary> 
     /// Allows the game component to update itself. 
     /// </summary> 
     /// <param name="gameTime">Provides a snapshot of timing values.</param> 
     public override void Update(GameTime gameTime) 
     { 
      time += (float)gameTime.ElapsedGameTime.TotalSeconds; 
      oldkeys = keystate; 
      keystate = Keyboard.GetState(); 
      cameraPosition.Y += gravity; 
      worldPosition.Y += gravity; 
      if (keystate.IsKeyDown(Keys.Right)) 
      { 
       cameraPosition.X += speed; 
       worldPosition.X += speed; 

       facing = "right"; 


      } 
      if (keystate.IsKeyDown(Keys.Left)) 
      { 
       cameraPosition.X -= speed; 
       worldPosition.X -= speed; 

       facing = "left"; 


      } 
      if (oldkeys.IsKeyDown(Keys.Left) && !keystate.IsKeyDown(Keys.Left)) 
      { 
       state = "stand"; 
      } 

      if (oldkeys.IsKeyDown(Keys.Right) && !keystate.IsKeyDown(Keys.Right)) 
      { 
       state = "stand"; 
      } 



      if (state == "stand") 
      { 

       if (keystate.IsKeyDown(Keys.Left)) 
       { 
        state = "walk"; 
        MoveAnimation(gameTime); 
       } 
       if (keystate.IsKeyDown(Keys.Right)) 
       { 
        state = "walk"; 
        MoveAnimation(gameTime); 
       } 
      } 

      if (state == "walk") 
      { 
       activeFrame = (activeFrame + 1) % frames.Count; 
       gravity = 5f; 

      } 
      if (state == "stand") 
      { 
       activeFrame = 0; 
       gravity = 5f; 
       StandAnimation(); 
      } 

      // 

      if (jump) 
      { 
       state = "jump"; 
       cameraPosition.Y += jumpSpeed; 
       worldPosition.Y += jumpSpeed; 
       jumpSpeed += 1f; 
       if (jumpSpeed == 0) 
       { 
        jumpSpeed = 0; 
        jump = false; 
        state = "fall"; 
       } 

      } 
      else 
      { 
       if (worldPosition.Y == startY) 
       { 
        if (keystate.IsKeyDown(Keys.Space) && !oldkeys.IsKeyDown(Keys.Space)) 
        { 
         jumpSpeed -= 18f; 
         jump = true; 
         gravity = 0f; 
        } 
       } 
      } 

      if (state == "fall") 
      { 
       gravity = 5f; 
       JumpAnimation(); 
      } 
      if (state == "jump") 
      { 
       JumpAnimation(); 
      } 
      if (worldPosition.Y > startY) 
      { 
       state = "fall"; 

      } 



      rectangle = new Rectangle((int)worldPosition.X, (int)worldPosition.Y, WIDTH, HEIGHT); 
      footBounds = new Rectangle(rectangle.Center.X, rectangle.Center.Y, rectangle.Width, 1); 
      rightRec = new Rectangle(rectangle.Center.X, rectangle.Y, rectangle.Width/2, rectangle.Height); 
      leftRec = new Rectangle(rectangle.Left, rectangle.Y, 1, rectangle.Height); 



      base.Update(gameTime); 

     } 
     public override void Draw(GameTime gameTime) 
     { 
      SpriteBatch sBatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch)); 
      if (facing == "right") 
      { 
       sBatch.Draw(texture, cameraPosition, frames[activeFrame], Color.White, 0f, new Vector2(rectangle.Width/2, rectangle.Height/2), 1.0f, SpriteEffects.None, 0); 
        } 

      if (facing == "left") 
      { 
       sBatch.Draw(texture, cameraPosition, frames[activeFrame], Color.White, 0f, new Vector2(rectangle.Width/2, rectangle.Height/2), 1.0f, SpriteEffects.FlipHorizontally, 0); 

      } 
      //sBatch.Draw(texture, position, frames[activeFrame], Color.White); 

      base.Draw(gameTime); 
     } 

     public void MoveAnimation(GameTime gt) 
     { 

      time += (float)gt.ElapsedGameTime.TotalMilliseconds; 
      currentFrame.Y = 3; 

      frameSize = new Point(33, 33); 
      if (time > interval) 
      { 
       currentFrame.X++; 
       if (currentFrame.X > 4) 
       { 
        currentFrame.X = 1; 
       } 
       source = new Rectangle(currentFrame.X * frameSize.X, currentFrame.Y * 25, frameSize.X, frameSize.Y); 
       time = 0f; 
      } 
     } 

     public void JumpAnimation() 
     { 

      currentFrame.Y = 5; 
      currentFrame.X = 1; 
      frameSize = new Point(33, 33); 
      source = new Rectangle(currentFrame.X * frameSize.X, currentFrame.Y * frameSize.Y, frameSize.X, frameSize.Y); 

     } 

     public void FallAnimation() 
     { 
      currentFrame.X = 5; 
      currentFrame.X = 2; 
      frameSize = new Point(33, 33); 
      source = new Rectangle(currentFrame.X * frameSize.X, currentFrame.Y * frameSize.Y, frameSize.X, frameSize.Y); 
     } 
     public void StandAnimation() 
     { 
      currentFrame.X = 1; 
      currentFrame.Y = 2; 
      frameSize = new Point(33, 33); 
      source = new Rectangle(currentFrame.X * frameSize.X, currentFrame.Y * 19, frameSize.X, frameSize.Y); 

     } 

    } 
} 

And The Collision Detection Method 

    public void Collision() 
     { 


      foreach (Rectangle top in map.blocksTop) 
      { 
       if (top.Intersects(mario.footBounds)) 
       { 
        mario.gravity = 0f; 
        mario.state = "stand"; 
        mario.startY = mario.worldPosition.Y; 
       } 
      } 

      foreach (Rectangle left in map.blocksLeft) 
      { 
       if (left.Intersects(mario.rightRec)) 
       { 
        if (mario.footBounds.Y >= left.Y) 
        { 

         mario.worldPosition.X -= 5f; 
         mario.cameraPosition.X -= 5f; 
        } 
       } 
      } 

      foreach (Rectangle right in map.blocksRight) 
      { 
       if (right.Intersects(mario.leftRec)) 
       { 
        if (mario.footBounds.Y >= right.Y) 
        { 
         mario.worldPosition.X += 5f; 
         mario.cameraPosition.X += 5f; 
        } 
       } 
      } 

     } 

有人能告诉我,我做错了什么?

亲切的问候 Trustos

+1

你不能指望人们有时间下载并阅读完整的项目。提供更多详细信息或提供关于碰撞检测的哪个部分是问题的代码 – cppanda

+0

请仅包含您认为有问题的代码,并解释这些问题可能是什么,您希望代码执行的内容以及实际执行的内容。因为很少有人有机会下载它。 – user1306322

回答

0

您可以使用碰撞功能的建设基本上是方形的物体在你的游戏或建立一个布尔函数,返回真,如果你的对象是对其他物体或尝试的相同位置穿过它。或者尝试youtube碰撞教程或一些物理以及:)。

0

下面是一个简单的方法来做一个侧面滚动瓷砖碰撞。如果角色真的很快,这将无法使用。假设你的游戏运行速度为60 fps,以获得更好的结果。

在两个轴上分开测试。从Y开始。如果目的地的瓷砖被占用,请将Y夹在顶部或底部。

然后以相同的方式做X.它非常基本,但适合这种情况。

Tile tileY = GetTileAt(Position.X, Position.Y + Velocity.Y); 

if (tileY.IsOccupied) 
{ 
    if (Velocity.Y >= 0) // Player is falling down 
    { 
     // Set position (feet) on top of the tile 
     Position.Y = tileY.Y; 
    } 
    else 
    { 
     // Set position bellow the tile 
     Position.Y = tileY.Y + TILE_HEIGHT + CHARACTER_HEIGHT; 
    } 
} 

// Similar for X, but use the update Y position to fetch the tile 
Tile tileX = GetTileAt(Position.X + Velocity.X, Position.Y); 
if (tileX.IsOccupied) 
{ 
    if (Velocity.X >= 0) // Player is going right 
    { 
     Position.X = tileX.X - (CHARACTER_WIDTH/2); 
    } 
    else 
    { 
     Position.X = tileX.X + TILE_WIDTH + (CHARACTER_WIDTH/2); 
    } 
}