XNA Rectangle intersection
Ich habe vor kurzem angefangen auf die XNA-Entwicklung und habe einige (sehr begrenzte) Erfahrung mit in der Vergangenheit, habe ich beschlossen, zu versuchen und machen einen Pong-clone, um zu sehen, wie viel ich mich erinnern konnte. Das meiste, was ich wusste, kam zu mir zurück, aber ich habe Probleme mit der Kollisionserkennung zwischen die Schläger und den ball. Ich habe 3 Rechtecke legen Sie auf update-position zusammen mit den sprites, die ich verwende, und, wenn der ball das Rechteck schneidet mit einer Fledermaus Rechteck, ich multipliziere die X-Geschwindigkeit der ball von -1. Aber dadurch entsteht ein ungewöhnlicher Effekt, durch den der ball springt rund um die Fledermaus, wie gezeigt, in dieses video.Was mache ich hier falsch?
Hier ist der code für dieses Projekt (schlecht, ich weiß):
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 Pong
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
System.Random generator = new Random();
Texture2D ball;
Texture2D bat1;
Texture2D bat2;
Texture2D middle;
Vector2 midPos;
Vector2 bat1Pos;
Vector2 bat2Pos;
Vector2 ballPos;
Vector2 ballVelo;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
//Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
//Load sprites
ball = Content.Load<Texture2D>(@"sprites/pongball");
bat1 = Content.Load<Texture2D>(@"sprites/pongbat");
bat2 = Content.Load<Texture2D>(@"sprites/pongbat");
middle = Content.Load<Texture2D>(@"sprites/pongmiddle");
//Set default sprite positions
midPos.X = (Window.ClientBounds.Width / 2) - 5;
midPos.Y = 0;
bat1Pos.X = 10;
bat1Pos.Y = (Window.ClientBounds.Height/2) - 50;
bat2Pos.X = Window.ClientBounds.Width - 20;
bat2Pos.Y = (Window.ClientBounds.Height/2) - 50;
ballPos.X = (Window.ClientBounds.Width / 2) - 5;
ballPos.Y = (Window.ClientBounds.Height / 2) - 5;
//Generate random ball velocity
ballVelo.X = generator.Next(5,10);
ballVelo.Y = generator.Next(4, 7);
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
//Update rectangle values
Rectangle bat1Rect = new Rectangle((int)bat1Pos.X, (int)bat1Pos.Y, 10, 100);
Rectangle bat2Rect = new Rectangle((int)bat2Pos.X, (int)bat2Pos.Y, 10, 100);
Rectangle ballRect = new Rectangle((int)ballPos.X, (int)ballPos.Y, 10, 100);
//Move ball
ballPos += ballVelo;
//Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
if (Keyboard.GetState().IsKeyDown(Keys.Escape))
this.Exit();
//Bat 1 movement and restriction
if (Keyboard.GetState().IsKeyDown(Keys.Up))
bat1Pos.Y -= 4;
if (Keyboard.GetState().IsKeyDown(Keys.Down))
bat1Pos.Y += 4;
if (bat1Pos.Y <= 0)
bat1Pos.Y = 0;
if (bat1Pos.Y >= Window.ClientBounds.Height - 100)
bat1Pos.Y = Window.ClientBounds.Height - 100;
//Bat 2 movement and restriction
if (Keyboard.GetState().IsKeyDown(Keys.W))
bat2Pos.Y -= 4;
if (Keyboard.GetState().IsKeyDown(Keys.S))
bat2Pos.Y += 4;
if (bat2Pos.Y <= 0)
bat2Pos.Y = 0;
if (bat2Pos.Y >= Window.ClientBounds.Height - 100)
bat2Pos.Y = Window.ClientBounds.Height - 100;
//Ball movement restrictions
if (ballPos.X <= 0)
ballVelo.X *= -1;
if (ballPos.Y <= 0)
ballVelo.Y *= -1;
if (ballPos.X >= Window.ClientBounds.Width - 5)
ballVelo.X *= -1;
if (ballPos.Y >= Window.ClientBounds.Height - 5)
ballVelo.Y *= -1;
//Collision detection between bats and ball
if (ballRect.Intersects(bat1Rect))
{
ballVelo.X *= -1;
}
if (ballRect.Intersects(bat2Rect))
{
ballVelo.X *= -1;
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin();
spriteBatch.Draw(middle, midPos, Color.White);
spriteBatch.Draw(bat1, bat1Pos, Color.White);
spriteBatch.Draw(bat2, bat2Pos, Color.White);
spriteBatch.Draw(ball, ballPos, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
InformationsquelleAutor David | 2011-04-12
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ein Weg, um dieses wäre zu tun, nehmen Sie die folgende änderung Ihrer
ballRect.Intersect(barXRect))
if-Anweisungen:Diese Weise der linken Leiste wird nur das senden der ball rechts, und der Rechte Balken wird nur senden Sie es Links. Ich kann die bars rund um den falschen Weg, so könnte es am besten zu überprüfen, aber es bedeutet nur das verschieben der
* -1
auf die andere Fledermaus.Keine sorgen, bin froh, dass ich helfen konnte.
InformationsquelleAutor Lyise
Lyise die Lösung wird funktionieren, aber es greift nicht die eigentliche Ursache des Problems. In größeren spielen, benötigen Sie eine robustere Lösung, also werde ich erklären, die high-level-fix.
Das Problem ist, dass Sie ändern die X-Geschwindigkeit, während der ball noch innerhalb des bat. Im nächsten frame ist die wahrscheinlichste Ergebnis ist, dass der ball Weg bewegen, aber nicht genug, um die Ausfahrt der Fledermaus, so dass eine neue Kollision erkannt wird. Die Geschwindigkeit wird wieder geändert, und der Zyklus wird wiederholt, bis die Kugel verlässt die Fledermaus, indem Sie oben oder unten abweicht.
Die exakte Lösung erfordert den Transport, den ball aus dem Schläger und dann invertieren die Geschwindigkeit.
Optionen:
//Colliding from the right
impactCorrection = bat.Right - ball.Left;
//Colliding from the left
impactCorrection = bat.Left - ball.Right;
Für zusätzliche Punkte, die Sie vielleicht bewegen Sie den ball Weg
2 * impactCorrection
in X, so dass die Kugel reist immer den gleichen Abstand zu jedem Rahmen.InformationsquelleAutor Elideb