玩家框以不受欢迎的方式继续穿墙,我尝试过让玩家一次以 0.1f(u) 的增量移动,但这严重降低了游戏的性能。有什么方法可以检测到玩家是否撞到墙,他们撞到了哪一侧以及如何防止他们撞到墙上?
这是我正在运行的代码(这当然是极简的)
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;
namespace Platformer
{
public class Player
{
double terminalVelocity;
//AnimatedTexture texture;
public Texture2D texture;
public Vector2 Position, Velocity;
public Rectangle boundingBox;
public Player(Texture2D tex, Vector2 pos, Vector2 vel, Rectangle bb)
{
texture = tex;
Position = pos;
Velocity = vel;
boundingBox = bb;
terminalVelocity = Math.Sqrt((2*bb.Width*bb.Height*Game1.gravity)/-9.8*2);
}
public void updateBoundingBoxes()
{
boundingBox.X = (int)Position.X;
boundingBox.Y = (int)Position.Y;
}
public void onUpdate()
{
updateBoundingBoxes();
Position.X += Velocity.X;
Position.Y += Velocity.Y;
//Velocity = Vector2.Zero;
Velocity.Y += Game1.gravity / 60;
Velocity.X /= 1.2f;
}
public void Draw(SpriteBatch sb)
{
updateBoundingBoxes();
sb.Begin();
sb.Draw(texture,boundingBox,GameLighting.currentColour());
sb.End();
}
}
public enum GameLightingState
{
Red, Dark, Orange, Blue, White
}
public class Platform : Object
{
Texture2D text;
public Rectangle rect;
public Platform(Texture2D t, Vector2 p, int sizeX, int sizeY)
{
text = t;
rect = new Rectangle((int)p.X, (int)p.Y, sizeX, sizeY);
}
public void onPlayerCollision(Player p)
{
p.Velocity.X = -p.Velocity.X / 2;
p.Velocity.Y = -p.Velocity.Y / 2;
}
public void Draw(SpriteBatch sb)
{
sb.Begin();
sb.Draw(text, rect, GameLighting.currentColour());
sb.End();
}
public void onUpdate()
{
}
}
public class GameLighting
{
public static Color currentColour()
{
return eToColour(Game1.currentLightingState);
}
public static Color eToColour(GameLightingState gls)
{
switch (gls)
{
case(GameLightingState.Red):
return Color.Red;
case (GameLightingState.Blue):
return Color.Blue;
case (GameLightingState.Orange):
return Color.Orange;
case (GameLightingState.Dark):
return Color.DarkGray;
case (GameLightingState.White):
return Color.White;
}
return Color.White;
}
}
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
public static float gravity = 9.80665f;
public static GameLightingState currentLightingState;
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
List<Platform> platforms;
List<Player> players;
int controlledPlayerIndex = 0;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
currentLightingState = GameLightingState.White;
platforms = new List<Platform>();
players = new List<Player>();
players.Add(new Player(this.Content.Load<Texture2D>("Images/dirt"), new Vector2(300,0), new Vector2(0,0), new Rectangle(300,0,20,20)));
platforms.Add(new Platform(this.Content.Load<Texture2D>("Images/dirt"),new Vector2(300,450),200,20));
platforms.Add(new Platform(this.Content.Load<Texture2D>("Images/dirt"), new Vector2(20,20), 20, 200));
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
foreach (Player p in players)
{
Boolean intersects = false;
Rectangle tempRectangle = new Rectangle((int)(p.Position.X + p.Velocity.X),(int) (p.Position.Y + p.Velocity.Y), p.boundingBox.Width, p.boundingBox.Height);
foreach (Platform pl in platforms)
{
intersects = intersects || tempRectangle.Intersects(pl.rect);
}
if (!intersects)
{
p.onUpdate();
}
}
if (Keyboard.GetState().IsKeyDown(Keys.Space))
{
players[controlledPlayerIndex].Velocity.Y -= 0.75f;
}
if (Keyboard.GetState().IsKeyDown(Keys.A))
{
players[controlledPlayerIndex].Velocity.X -= 0.75f;
}
if (Keyboard.GetState().IsKeyDown(Keys.D))
{
players[controlledPlayerIndex].Velocity.X += 0.75f;
}
// TODO: Add your update logic here
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
foreach (Platform p in platforms)
{
p.Draw(spriteBatch);
}
foreach (Player p in players)
{
p.Draw(spriteBatch);
}
base.Draw(gameTime);
}
}
}
*根据第一条评论更新了源代码
关于此代码的一个注意事项,您需要在 XNA 中运行它并在一个名为 Images 的文件夹中使用一个名为 mud.png 的图标,图片看起来如何并不重要,您只需要它来完全了解正在发生的事情