#c# #xna #monogame
#c# #xna #monogame
Вопрос:
Я использую фреймворк MonoGame для создания платформерной игры. В игре есть некоторые базовые механики, такие как: гравитация и обнаружение столкновений, которые работают только с последним объектом в списке.
Вот код для игровой области игры (основной скрипт): `
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Survive.Engine;
using System.Collections.Generic;
namespace Game
{
public class MainGame : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Player player = new Player();
List<Box> boxes = new List<Box>();
public MainGame()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
Box box = new Box();
box.Init(new Vector2(100, 400), Content.Load<Texture2D>("Player"));
Box box2 = new Box();
box2.Init(new Vector2(132, 400), Content.Load<Texture2D>("Player"));
player.Init(new Vector2(100, 100), Content.Load<Texture2D>("Player"));
boxes.Add(box);
boxes.Add(box2);
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
for (int i = 0; i < boxes.Count; i )
{
if (player.Colliding(boxes[i]))
{
player.falling = false;
}
if (!player.Colliding(boxes[i]))
{
player.falling = true;
}
}
player.Update();
boxes.ForEach(k => k.Update());
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
player.Draw(spriteBatch);
for (int i = 0; i < boxes.Count; i )
{
boxes[i].Draw(spriteBatch);
}
spriteBatch.End();
base.Draw(gameTime);
}
}
}`
Вот класс объекта (из которого построен player и box):
`
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Game.Engine
{
public class Object2D
{
public int Health = 100;
public Vector2 Position;
public Texture2D Texture;
public Rectangle BoundingBox;
public bool Colliding(Object2D obj)
{
bool col = false;
if (BoundingBox.Intersects(obj.BoundingBox))
{
col = true;
}
return col;
}
public virtual void Init(Vector2 pos, Texture2D text)
{
Position = pos;
Texture = text;
}
public virtual void Update()
{
BoundingBox = new Rectangle((int)Position.X, (int)Position.Y, Texture.Width, Texture.Height);
}
public virtual void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(Texture, Position, Color.White);
}
}
}
`
Сценарий игрока:
`
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Survive.Engine;
using Microsoft.Xna.Framework.Input;
namespace Survive
{
public class Player : Object2D
{
public float vsp = 0;
public float grav = 0.1f;
public bool falling = true;
public bool jmping = false;
public override void Init(Vector2 pos, Texture2D text)
{
base.Init(pos, text);
}
public override void Update()
{
if (Keyboard.GetState().IsKeyDown(Keys.A))
{
Position.X -= 2;
}
if (Keyboard.GetState().IsKeyDown(Keys.D))
{
Position.X = 2;
}
if (falling)
{
vsp = grav;
Position.Y = vsp;
}
base.Update();
}
public override void Draw(SpriteBatch spriteBatch)
{
base.Draw(spriteBatch);
}
}
}`
Поле просто наследуется Object2D.cs
, код не был изменен.
Но в обновлении пусто MainGame.cs
, где мы проверяем наличие столкновения:
`
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
for (int i = 0; i < boxes.Count; i )
{
if (player.Colliding(boxes[i]))
{
player.falling = false;
}
if (!player.Colliding(boxes[i]))
{
player.falling = true;
}
}
player.Update();
boxes.ForEach(k => k.Update());`
Код работает, но только для второго объекта в нашем списке, когда я перехожу через первое добавленное поле, я просто падаю, поскольку применяется сила тяжести.
Я не уверен, почему он проверяет только последнее поле в списке полей.
Ответ №1:
Вы не останавливаете поиск, как только обнаружите коллизию. Измените этот код:
for (int i = 0; i < boxes.Count; i )
{
if (player.Colliding(boxes[i]))
{
player.falling = false;
}
if (!player.Colliding(boxes[i]))
{
player.falling = true;
}
}
…к чему-то вроде:
var isFalling=true; // assume the worst
for (int i = 0; i < boxes.Count; i )
{
if (player.Colliding(boxes[i]))
{
isFalling = false;
break;
}
}
player.falling = isFalling;
Комментарии:
1. Спасибо! Я попробую это.
2. Да, он просто не обнаруживает коллизию для первого добавленного поля, я только что провел тест, если удалить второе поле, оно обнаруживает коллизию для первого, но когда добавляется второе, оно обнаруживает его только для первого
3. К сожалению, он обнаруживает коллизию только для второго поля, когда добавляется второе