对于学校我需要在XNA制作这个游戏项目我选择制作基于马里奥的游戏。 但是我现在已经进行了几天的碰撞检测,但我仍然找不到问题。
以下是该项目的链接: ProjectMario
Oke所以这就是它的作用。
这是我的代码
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
答案 0 :(得分:0)
您可以使用构建碰撞功能,该功能基本上适用于游戏中的方形对象或构建bool函数,如果您的对象位于其他对象的同一位置或尝试移动它,则返回true。或者尝试使用youtube进行学习教程或者一些物理学:)。
答案 1 :(得分: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);
}
}