XNA

2012-08-08 18 views
7

में वर्ग से अधिक छवि खींच नहीं सकता है मैं एक पोंग गेम बना रहा हूं। मैं अपनी गेंद के रूप में एक लाल वर्ग के एक साधारण 44 x 44 .png का उपयोग कर रहा हूं, जबकि मैं डिबगिंग कर रहा हूं। खेल इस वर्ग के साथ ठीक काम करता है।XNA

जब मैं एक वर्ग के अलावा किसी अन्य चीज़ के साथ बनावट को प्रतिस्थापित करने का प्रयास करता हूं, तो मुझे स्क्रीन पर खींची गई गेंद दिखाई नहीं देती है, और मैं यह नहीं समझ सकता कि क्यों। मैं अपनी छवियों को फ़ोटोशॉप में सटीक आकार बना रहा हूं, और या तो पीएनजी या .जेपीजी का उपयोग कर रहा हूं और एक ही परिणाम प्राप्त कर रहा हूं, लेकिन मैं इसे अपने जीवन के लिए नहीं समझ सकता। आपको क्या लगता है कि इस मुद्दे का कारण हो सकता है?

मैंने नीचे दिए गए पाठ में अपनी गेंद के लिए कोड छोड़ा है। गेमप्लेस्क्रीन (एमएस 'जीएसएम नमूना का उपयोग करके) द्वारा मेरी गेंद के अपडेट और ड्रा विधियों को बुलाया जा रहा है।

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' पास कर रहे हैं, और गेंदरेट पैरामीटर को गेंद की स्थिति के अनुसार अपडेट किया जा रहा है ताकि आप आकर्षित करने की कोशिश कर रहे हों आपकी छवि का हिस्सा जो बनावट के आकार के बाहर है।

आप पूरे गेंद आकर्षित करने के लिए चाहते हैं, तो बस का उपयोग करें:

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); 

संपादित करें: आप अल रहे हैं तो आपके "स्केल" पैरामीटर के रूप में .0f गुजर रहा है, इसलिए जब यह आपकी गेंद खींचता है तो यह आकार में 0 पिक्सेल होगा, जिसका अनुमान है कि मैं इरादा व्यवहार नहीं कर रहा हूं। अपने पैमाने के लिए 1 एफ का उपयोग करके इसे इसके डिफ़ॉल्ट आकार में खींचा जाएगा।

+0

यह था! मुझे SourceRect को शून्य में बदलने की आवश्यकता है, और स्केल को 1 तक बदलें। मुझे नहीं लगता कि यह 0 पर क्यों था, लेकिन मुझे लगता है क्योंकि मेरा मूल बनावट सिर्फ एक बड़ा लाल ब्लॉक था, इससे कोई फर्क नहीं पड़ता कि यह कितना बड़ा था । –

3

2 चीजें हैं जो मैं देख रहा हूँ, मुझे नहीं लगता कि आप अपने आयत आयाम को आधा करने के लिए जब आप

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

फोन भी है, तो आप के ऊपर इस blank स्प्राइट ड्राइंग कर रहे हैं चाहते हैं अपने गेंद, ताकि अगर वे ओवरलैप हों, तो आपको गेंद दिखाई नहीं देगी, लेकिन अगर ऐसा है तो मुझे नहीं पता कि यह वर्ग के साथ क्यों काम करता है।

+0

क्षमा करें, मैंने आधे में बनावट काट दिया था क्योंकि मैं इसे परीक्षण के लिए छोटा बनाने की कोशिश कर रहा था। मुझे लगता है कि मैं उस रेखा को हटाना भूल गया था। मैं केवल रिक्त स्प्राइट (जो कि वास्तव में सिर्फ एक सफेद ब्लॉक है, रंगीन रंग। लाइटकॉरल) को उस स्थान पर खींच रहा है जहां गेंद और बल्ले टकराते हैं। तो एक बार जब वे टकराते हैं तो वहां "रिक्त" बनावट खींचती है, और उसके बाद इसे अगले बल्ले को मारने के बाद हटा दिया जाता है। –

0

कुछ मैंने देखा है कि लाइन में

resetBallPos = new Vector2(ScreenSize.X/2 + origin.X, ScreenSize.Y/2 + origin.Y); 

अपने निर्माता के अंदर चर 'मूल' इससे पहले कि आप वास्तव में इसे करने के लिए किसी भी मूल्य निर्दिष्ट के गुणों तक पहुँच रहा है है, हालांकि, आप इस मान के नीचे केवल कुछ पंक्तियों को मान देते हैं। मैं इस लाइन को ले जाऊंगा:

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

इसके ऊपर होने के लिए। मुझे लगता है कि आपकी समस्या को ठीक करना चाहिए; लाल ब्लॉक से उचित छवि में संक्रमण में, आपने सोचा होगा कि आपने और अधिक बदल दिया होगा।

इसके अलावा, एक साइड नोट के रूप में, जब आप एक्सएनए के साथ काम कर रहे हैं, तो मुख्य रूप से पीएनजी छवियों का उपयोग करने का प्रयास करें। वे छोटे हैं और बहुत जल्दी लोड करते हैं; इसके अतिरिक्त, वे पारदर्शी पृष्ठभूमि छवियों का समर्थन करते हैं।

+0

मैंने तब से मूल को रीसेटबॉल लाइन से ऊपर स्थानांतरित कर दिया है। मैं अभी भी इस गेंद को नहीं देख रहा हूँ। मैं आम तौर पर पीएनजी का हर समय उपयोग करता हूं, लेकिन मैंने सोचा कि मैं इस उदाहरण में जेपीजी का प्रयास करूंगा, यह सत्यापित करने के लिए कि यह पारदर्शिता के साथ कोई मुद्दा नहीं था। –

2

आप स्रोत आयत, जो निर्दिष्ट करता है जहां स्प्राइट मौजूद बनावट पर के रूप में Draw() में ballRect गुजर रहे हैं। यदि आप पूरे बनावट का उपयोग करना चाहते हैं, तो इसके बजाय null निर्दिष्ट करें। अन्यथा, सुनिश्चित करें कि ballRect का मान हमेशा बनावट के भीतर आता है।

स्क्रीन पर स्प्राइट की स्थिति का ट्रैक रखने के लिए आप इसका उपयोग कर रहे हैं।

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

इस गठन उत्पन्न बनावट की सीमा है, जो नमूना द्वारा clamped किया जा रहा है के बाहर का समन्वय करता है: अपने UpdatePosition समारोह से। एक बनावट जिसमें पूरी तरह से लाल पिक्सल होते हैं, यह काम पर प्रतीत होता है, क्योंकि बनावट के किनारे के चारों ओर पिक्सेल सभी लाल होते हैं। एक पारदर्शी सीमा वाले बनावट में, स्प्राइट को इसके बजाय उस पारदर्शी रंग पर क्लैंप किया जा रहा है।

संबंधित मुद्दे