2012-08-08 16 views
7

私はポンゲームを作っています。私はデバッグしている間に、私のボールとして赤い四角形の単純な44×44の.pngを使っています。ゲームはこの広場でうまくいく。XNAで四角以上の画像を描くことはできません

テクスチャを四角形以外のものに置き換えようとすると、ボールが画面に描画されていないとわかりません。その理由を理解できません。私は画像をPhotoshopで正確に同じサイズにして、.PNGまたは.JPGのいずれかを使用して同じ結果を得ていますが、私の人生のためにそれを理解することはできません。あなたはこの問題を引き起こしていると思いますか?

私のボールのコードは以下のテキストに残しました。私のボールの更新と描画のメソッドは、GameplayScreen(MSのGSMサンプルを使用)によって呼び出されています。

public class Ball : IGameEntity 
{ 
    #region Fields 

    private Random rand;    // Random var 
    private Texture2D texture;   // Texture for the ball 
    private double direction;   // Directon the ball is traveling in     
    private bool isVisible; 
    private bool hasHitLeftBat;   // Checked to see if the ball and bat have just collided 
    private bool hasHitRightBat;  // Checked to see if the ball and bat have just collided 
    private Vector2 ballPosition, resetBallPos, oldBallPos; 
    private Rectangle ballRect; 
    public float Speed; 
    private SpriteBatch spriteBatch; // Spritebatch 
    private bool isBallStopped; 
    private Vector2 origin;    // Locate the mid-point of the ball 
    public float RotationAngle; 
    private AIBat rightBat;    // Player's Bad 
    private Bat leftBat;    // AI Bat 
    private float ballRelativePos; 
    private Rectangle rectangle3;  // Used to draw the collison rectangle 
    private Texture2D blank;   // Texture to be drawn on the collision rectangle 

    GameplayScreen gameplayScreen;  // Creates an instance of the GameplayScreen 
    Game1 gameInstance;     // Creates an instance of the Game1 class 
    int selectedStage;     // Pass this into GameplayScreen for selecting easy, medium, or hard 


    #endregion 

    #region Constructors and Destructors 

    /// <summary> 
    /// Constructor for the ball 
    /// </summary> 
    public Ball(ContentManager contentManager, Vector2 ScreenSize, Bat bat, AIBat aiBat) 
    { 
     Speed = 15f; 
     texture = contentManager.Load<Texture2D>(@"gfx/balls/redBall"); 
     direction = 0; 
     ballRect = new Rectangle(0, 0, texture.Width /2, texture.Height /2); 
     resetBallPos = new Vector2(ScreenSize.X/2 + origin.X, ScreenSize.Y/2 + origin.Y); 
     ballPosition = resetBallPos; 
     rand = new Random(); 
     isVisible = true; 
     origin = new Vector2(texture.Width/2, texture.Height/2); 
     leftBat = bat; // Creates a new instance of leftBat so that I can access Position.X/Y for LeftBatPatcicles() 
     rightBat = aiBat;// Creates a new instance of leftBat so that can access Position.X/Y for RightBatPatcicles() 
     gameplayScreen = new GameplayScreen(null, selectedStage); 
     gameInstance = new Game1(); 
     Rectangle rectangle3 = new Rectangle(); 
     blank = contentManager.Load<Texture2D>(@"gfx/blank");    

     // pes = new ParticleEmitterService(game); 
    } 

    public Ball(Bat myBat) 
    { 
     leftBat = myBat;   // this assigns and instantiates the member bat 
            // with myBat which was passed from the constructor 
    } 

    #endregion 

    #region Methods 

    /// <summary> 
    /// Draws the ball on the screen 
    /// </summary> 
    public void Draw(SpriteBatch spriteBatch) 
    { 
     if (isVisible) 
     { 
      // Draws the rotaing ball 
      spriteBatch.Draw(texture, ballPosition, ballRect, Color.White, 
           RotationAngle, origin, .0f, SpriteEffects.None, 0); 

      spriteBatch.Draw(blank, rectangle3, Color.LightCoral); 
     } 
    } 

    /// <summary> 
    /// Updates position of the ball. Used in Update() for GameplayScreen. 
    /// </summary> 
    public void UpdatePosition(GameTime gameTime) 
    { 
     ballRect.X = (int)ballPosition.X; 
     ballRect.Y = (int)ballPosition.Y; 
     oldBallPos.X = ballPosition.X; 
     oldBallPos.Y = ballPosition.Y; 

     ballPosition.X += Speed * ((float)Math.Cos(direction)); 

     ballPosition.Y += Speed * ((float)Math.Sin(direction)); 
     bool collided = CheckWallHit(); 


     // Stops the issue where ball was oscillating on the ceiling or floor 
     if (collided) 
     { 
      ballPosition.X = oldBallPos.X + Speed * (float)1.5 * (float)Math.Cos(direction); 
      ballPosition.Y = oldBallPos.Y + Speed * (float)Math.Sin(direction); 
     } 

     // As long as the ball is to the right of the back, check for an update 
     if (ballPosition.X > leftBat.BatPosition.X) 
     { 
      // When the ball and bat collide, draw the rectangle where they intersect 
      BatCollisionRectLeft(); 
     } 

     // As longas the ball is to the left of the back, check for an update 
     if (ballPosition.X < rightBat.BatPosition.X) 
     { // When the ball and bat collide, draw the rectangle where they intersec 
      BatCollisionRectRight(); 
     } 

     // The time since Update was called last. 
     float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds; 

     // Rotation for the ball 
     RotationAngle += elapsed; 
     float circle = MathHelper.Pi * 2; 
     RotationAngle = RotationAngle % circle; 

     //  base.Update(gameTime); 
     gameInstance.update(); 

    } 


    /// <summary> 
    /// Checks for the current direction of the ball 
    /// </summary> 
    public double GetDirection() 
    { 
     return direction; 
    } 

    /// <summary> 
    /// Checks for the current position of the ball 
    /// </summary> 
    public Vector2 GetPosition() 
    { 
     return ballPosition; 
    } 

    /// <summary> 
    /// Checks for the current size of the ball (for the powerups) 
    /// </summary> 
    public Rectangle GetSize() 
    { 
     return ballRect; 
    } 



    /// <summary> 
    /// Checks to see if ball went out of bounds, and triggers warp sfx. Used in GameplayScreen. 
    /// </summary> 
    public void OutOfBounds() 
    { 
     AudioManager.Instance.PlaySoundEffect("Muzzle_shot"); 
    } 

    /// <summary> 
    /// Speed for the ball when Speedball powerup is activated 
    /// </summary> 
    public void PowerupSpeed() 
    { 
     Speed += 20.0f; 
    } 

    /// <summary> 
    /// Check for where to reset the ball after each point is scored 
    /// </summary> 
    public void Reset(bool left) 
    { 
     if (left) 
     { 
      direction = 0; 
     } 
     else 
     { 
      direction = Math.PI; 
     } 

     ballPosition = resetBallPos; // Resets the ball to the center of the screen 
     isVisible = true; 
     Speed = 15f; // Returns the ball back to the default speed, in case the speedBall was active 
     if (rand.Next(2) == 0) 
     { 
      direction += MathHelper.ToRadians(rand.Next(30)); 
     } 
     else 
     { 
      direction -= MathHelper.ToRadians(rand.Next(30)); 
     } 
    } 

    /// <summary> 
    /// Shrinks the ball when the ShrinkBall powerup is activated 
    /// </summary> 
    public void ShrinkBall() 
    { 
     ballRect = new Rectangle(0, 0, texture.Width/2, texture.Height/2); 
    } 

    /// <summary> 
    /// Stops the ball each time it is reset. Ex: Between points/rounds 
    /// </summary> 
    public void Stop() 
    { 
     isVisible = true; 
     Speed = 0; 
     isBallStopped = true; 
    } 

    /// <summary> 
    /// Checks for collision with the ceiling or floor. 2*Math.pi = 360 degrees 
    /// </summary> 
    private bool CheckWallHit() 
    { 
     while (direction > 2 * Math.PI) 
     { 
      direction -= 2 * Math.PI; 
      return true; 
     } 

     while (direction < 0) 
     { 
      direction += 2 * Math.PI; 
      return true; 
     } 

     if (ballPosition.Y <= 0 || (ballPosition.Y > resetBallPos.Y * 2 - ballRect.Height)) 
     { 
      direction = 2 * Math.PI - direction; 
      return true; 
     } 
     return true; 
    } 

    /// <summary> 
    /// Used to determine the location where the particles will initialize when the ball and bat collide 
    /// </summary> 
    private void BatCollisionRectLeft() 
    { 
     // For the left bat 
     if (ballRect.Intersects(leftBat.batRect)) 
     { 
      rectangle3 = Rectangle.Intersect(ballRect, leftBat.batRect); 
     } 
    } 

    /// <summary> 
    ///Checks for collision of Right Bat 
    /// </summary> 
    private void BatCollisionRectRight() 
    { 
     // for the right bat 
     if (ballRect.Intersects(rightBat.batRect)) 
     { 
      rectangle3 = Rectangle.Intersect(ballRect, rightBat.batRect); ; 
     } 
    } 

答えて

1

イメージ全体を描画する必要がない場合を除き、描画呼び出しでは何もSourceRectパラメータとして渡すべきではありません。

あなたのボールを描こうとしているときにあなたのSourceRectとして 'ballRect'を渡していて、ballRectパラメータがボールの位置に従って更新されているので、テクスチャのサイズの外側にある画像の部分。

あなたが全体のボールを描きたい場合は、単に使用:

spriteBatch.Draw(texture, ballPosition, null, Color.White, 
          RotationAngle, origin, .0f, SpriteEffects.None, 0); 

あなただけのボールの左上の象限を描画したい場合、あなたはSourceRectとして、以下の長方形に渡すことができます。

Rectangle sourceRect = new Rectangle(0, 0, texture.Width/2, texture.Height/2); 

次に、あなたがあなたのドローコールにそれを使用することができます。

spriteBatch.Draw(texture, ballPosition, sourceRect, Color.White, 
          RotationAngle, origin, .0f, SpriteEffects.None, 0); 

EDIT:あなたはアルです.0fを "scale"パラメータとして渡します。ボールを描くときは0ピクセルになりますが、これは意図した動作ではないと思います。あなたのスケールに1fを使用すると、デフォルトのサイズで描画されます。

+0

これはそれでした!私はSourceRectをnullに変更し、スケールを1に変更する必要がありました。私は元のテクスチャがちょうど大きな赤いブロックであったので、それは0であったとは思いません。 。 –

3

2私は気付いてる事、私はあなたがまた、あなたがあなたの上にこのblankスプライトを描画している

ballRect = new Rectangle(0, 0, texture.Width /2, texture.Height /2); 

を呼び出すときに、あなたの矩形dimentionsを半分にしたいとは思いませんボールが重なるとボールが見えなくなりますが、そのような場合にはなぜそれが正方形で働くのか分かりません。私が気づい

+0

申し訳ありませんが、テクスチャを小さくするために、テクスチャを半分にカットしました。私はその行を削除することを忘れたと思う。 私は、ボールとバットが衝突する場所でブランクのスプライト(実際には白いブロックで、Color.LightCoralで塗りつぶされている)だけを描画しています。一度衝突すると、そこに「空白」のテクスチャが描画され、次のバットに当たったら削除されます。 –

0

何かがラインにあなたのコンストラクタの内部

​​

は、あなたが実際にそれに任意の値を代入する前に変数「起源」のプロパティにアクセスしているということです。ただし、この値のわずか数行下に値を割り当てます。私はこの行を移動します:

origin = new Vector2(texture.Width/2, texture.Height/2); 

それ以上であること。私はそれがあなたの問題を解決すべきだと思います。赤いブロックから適切なイメージへの移行では、あなたは思った以上に変わったかもしれません。

また、XNAで作業しているときは、主にPNG画像を使用してください。それらは小さく、非常に迅速に負荷をかけます。さらに、透明な背景画像もサポートしています。

+0

私は以来、resetballpos行の上に原点を再配置しました。私はまだこのボールを見ていない。 私はいつもPNGを使用していますが、透明性の問題ではないことを確認するために、この例ではJPGを試してみると思いました。 –

2

あなたはスプライトはテクスチャに存在する場所を指定するソース矩形、としてDraw()ballRectを渡しています。テクスチャ全体を使用する場合は、nullを代わりに指定してください。それ以外の場合は、ballRectの値が常にテクスチャ内にあることを確認してください。

スプライトの位置を画面上に保存するために使用しているようです。。あなたのUpdatePosition関数から:

ballRect.X = (int)ballPosition.X; 
ballRect.Y = (int)ballPosition.Y; 

これはサンプラーによってクランプされているテクスチャの境界の外のテクスチャ座標を生産しています。全体的に赤のピクセルからなるテクスチャでは、テクスチャのエッジの周りのピクセルがすべて赤であるため、これが機能するように見えます。透明な境界線を持つテクスチャでは、代わりにその透明色にスプライトが固定されます。

関連する問題