2014-01-16 2 views
-1

Итак, я искал часы без каких-либо результатов и действительно надеюсь, что вы могли бы мне помочь. У меня возникают проблемы с работой пересечения. Ничего не происходит, когда мои классы сталкиваются, что, вероятно, я слепой, но также очень новый для XNA. Я создал игру Shoot-Em-Up, и я хочу, чтобы игра заканчивалась, когда управляемый игроком шаттл сталкивается с противником.XNA - Пересечение классов - 2D

Использование классов; Game1.cs, Player.cs и Enemy.cs. Обратите внимание, что я только вставил информацию, которая, как мне кажется, необходима, чтобы понять это.

Game1.cs

protected override void LoadContent() 
{ 
    shuttle = new Player(Content.Load<Texture2D>(@"spaceship"), new Vector2(300, 400), new Vector2(24, 24), spriteBatch); 
} 

protected override void Update(GameTime gameTime) 
{ 
    if (random.Next(0, 70) < droprate) 
    { 
     int posX = random.Next(20, 580); 
     enemyList.Add(new Enemy(Content.Load<Texture2D>(@"enemy1"), new Vector2(posX, -50), new Vector2(24, 24), spriteBatch)); 
     droprate += 0.10; 
    } 

    foreach (Enemy e in enemyList) 
    { 
     if (shuttle.rectangle.Intersects(e.rectangle)) 
     Exit(); 
    } 
} 

Player.cs

public Rectangle rectangle; 

    public Player(Texture2D texture, Vector2 initialPos, Vector2 origin, SpriteBatch spriteBatch) : base(texture, initialPos, origin, spriteBatch) 
    { 
     this.rectangle = new Rectangle(Convert.ToInt32(initialPos.X), Convert.ToInt32(initialPos.Y), 48, 48); 
    } 
    public override void Update(GameTime gameTime) 
    { 

     KeyboardState keyboardState = Keyboard.GetState(); 
     if (keyboardState.IsKeyDown(Keys.Right)) 
     { 
      initialPos.X += 9; 
     } 
     if (keyboardState.IsKeyDown(Keys.Left)) 
     { 
      initialPos.X -= 9; 
     } 
     if (keyboardState.IsKeyDown(Keys.Up)) 
     { 
      initialPos.Y -= 5; 
     } 
     if (keyboardState.IsKeyDown(Keys.Down)) 
     { 
      initialPos.Y += 5; 
     } 

     initialPos.X = MathHelper.Clamp(initialPos.X, 18, screenWidth - 18); 
     initialPos.Y = MathHelper.Clamp(initialPos.Y, 24, screenHeight - 24); 
     base.Update(gameTime); 
    } 

Enemy.cs

public Rectangle rectangle; 

public Enemy(Texture2D texture, Vector2 initialPos, Vector2 origin, SpriteBatch spriteBatch) : base(texture, initialPos, origin, spriteBatch) 
{ 
    this.rectangle = new Rectangle(Convert.ToInt32(initialPos.X), Convert.ToInt32(initialPos.Y), 48, 48); 
} 
    public override void Update(GameTime gameTime) 
    { 
     initialPos.Y += 3.5f; 
     if (initialPos.X < 300) 
      initialPos.X += 0.41f; 
     if (initialPos.X > 300) 
      initialPos.X -= 0.41f; 
    } 
+1

ли игрок или врагов двигаться? Кажется, вы никогда не обновляете свои границы столкновений после их первоначального создания. –

+0

игрок/шаттл контролируется мной, а вражеские космические корабли постоянно движутся в нижней части экрана. –

+0

А вы когда-либо обновляете значение 'rectangle' для объектов' Enemy' и 'Player'? Вы используете метод 'Intersects()' правильно, что означает, что данные, которые вы ему даете, ошибочны. –

ответ

1
public override void Update(GameTime gameTime) 
{ 
    initialPos.Y += 3.5f; 
    if (initialPos.X < 300) 
     initialPos.X += 0.41f; 
    if (initialPos.X > 300) 
     initialPos.X -= 0.41f; 

Вы должны переместить элемент прямоугольник ваших игроков и вражеских классов , Вы устанавливаете их один раз в конструкторе. Исходный прямоугольник игрока внизу экрана никогда не пересечет начальные позиции врагов, отмеченные в верхней части.

Я даже не уверен, что такое initialPos, но если вы хотите сделать это таким образом, и спрайты перемещаются, вам нужно убедиться, что вы перемещаете hitboxes вместе с спрайтами.

public override void Update(GameTime gameTime) 
{ 
    initialPos.Y += 3.5f; 
    rectangle.Y += 3.5f; 
    if (initialPos.X < 300){ 
     initialPos.X += 0.41f; 
     rectangle.X += 0.41f; 
} 
    if (initialPos.X > 300) 
     initialPos.X -= 0.41f; 
     rectangle.X -= 0.41f; 
} 

Редактировать: Используйте RectangleF для точности с плавающей точкой.

Редактирование2: В играх, как правило, hitbox на фракции меньше размера спрайтов/моделей. Это остановит хиты от регистрации с открытого пространства в не прямоугольных спрайтах, таких как космические корабли. :)

Edit3: ИЛИ

public override void Update(GameTime gameTime) 
{ 
    initialPos.Y += 3.5f; 

    if (initialPos.X < 300) initialPos.X += 0.41f; 
    if (initialPos.X > 300) initialPos.X -= 0.41f; 


    rectangle.X -= Convert.ToInt32(initialPos.X); 
    rectangle.Y += Convert.ToInt32(initialPos.Y); 

} 

редактировать 4: Будет ли прямоугольники двигаться вообще?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Diagnostics; 

namespace TestBench{ 
    class Program{ 
     static void Main(string[] args){ 
     float f = 0.0F; 
     int Y = 0; 

     for (int i = 0; i < 10; i++) { 
      f += 0.41F; 
      Y = Convert.ToInt32(f); 

      Debug.WriteLine("Float: " + f + " Int32 " + Y); 

     } 

     } 
    } 
} 

Результаты:

Float: 0.41 Int32 0 
Float: 0.82 Int32 1 
Float: 1.23 Int32 1 
Float: 1.64 Int32 2 
Float: 2.05 Int32 2 
Float: 2.46 Int32 2 
Float: 2.87 Int32 3 
Float: 3.28 Int32 3 
Float: 3.69 Int32 4 
Float: 4.1 Int32 4 
+0

да, я понимаю, что вы имеете в виду. Но я не могу, чтобы пучки прямоугольника не могли быть выражены в поплавке. Это должно быть в int, как мне обойти это? –

+0

Используйте прямоугольник F: http://msdn.microsoft.com/en-us/library/system.drawing.rectanglef(v=vs.110).aspx – RW4

+0

@ TheC4Fox, XNA не имеет RectangleF. То, что вы могли бы сделать, @ArvinAshrafi, просто сохраняет позиции как плавающие, как вы делаете, и в конце каждого вызова обновления конвертируйте значения float в прямоугольник, как вы это делаете, когда вы инициализировали Players/Enemy: 'this. rectangle = new Rectangle (Convert.ToInt32 (initialPos.X), Convert.ToInt32 (initialPos.Y), 48, 48); ' – davidsbro

0

Если вы хотите использовать значение с плавающей запятой, вы можете просто конвертировать значения с плавающей точкой в ​​initialPos в прямоугольнике каждый раз. InitialPos сохранит свою точность, и прямоугольник будет просто округлять значения float. Или вы можете создать свою собственную структуру RectangleF, которая работает со всеми другими объектами XNA (давая некоторую оценку @ TheC4Fox, поскольку я заимствовал ее идею о прямоугольниках с плавающей запятой ... просто сделал это так, чтобы RectangleF был совместим с другими функциями XNA легко. +1 за ваш ответ bro, так как он ответил на оригинал OP Q). Например:

public struct RectangleF 
{ 
    float w = 0; 
    float h = 0; 
    float x = 0; 
    float y = 0; 

    public float Height 
    { 
     get { return h; } 
     set { h = value; } 
    } 

    //put Width, X, and Y properties here 

    public RectangleF(float X, float Y, float width, float height) 
    { 
     w = width; 
     h = height; 
     x = X; 
     y = Y; 
    } 

    public bool Intersects(Rectangle refRectangle) 
    { 
     Rectangle rec = new Rectangle((int)x, (int)y, (int)w, (int)h); 
     if (rec.Intersects(refRectangle)) return true; 
     else return false; 
    } 
} 

Тогда вы бы заявить об этом в классах игроков и Enemy:

public RectangleF rectangle; 

public Enemy(Texture2D texture, Vector2 initialPos, Vector2 origin, SpriteBatch spriteBatch) : base(texture, initialPos, origin, spriteBatch) 
{ 
    this.rectangle = new RectangleF(initialPos.X, initialPos.Y, 48, 48); 
} 
public override void Update(GameTime gameTime) 
{ 
    rectangle.Y += 3.5f; 
    if (rectangle.X < 300) 
     rectangle.X += 0.41f; 
    if (rectangle.X > 300) 
     rectangle.X -= 0.41f; 
} 

HTH