4 Replies - 4217 Views - Last Post: 01 June 2010 - 08:25 AM

#1 ShadowsEdge19  Icon User is offline

  • D.I.C Addict

Reputation: 142
  • View blog
  • Posts: 664
  • Joined: 16-January 10

Help loading card textures

Posted 31 May 2010 - 02:25 PM

Hi, I'm writing a card game and I'm having trouble loading the textures from my content/cards folder in the format ClubsSix.bmp, HeartsJack.bmp, etc. The picture here Posted Image

shows where the runtime error occurs when the gameplayScreen tried to draw the cards, all the other attributes are working correctly.

Here are the 5 classes that enable the cards to be drawn from the player's hand.

Card class
#region File Description
//-----------------------------------------------------------------------------
// Card.cs
//-----------------------------------------------------------------------------
#endregion

#region Using Statements

using System;
using System.Configuration;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

#endregion

namespace OverTheTop.CardGameFramework
{
    /// <summary>
    /// Card suit values
    /// </summary>
    public enum Suit
    {
        Diamonds, Spades, Clubs, Hearts
    }

    /// <summary>
    /// Card face values
    /// </summary>
    public enum FaceValue
    {
        Ace = 1, Three = 3, Four = 4, Five = 5, Six = 6, Seven = 7, Eight = 8,
        Nine = 9, Ten = 10, Jack = 10, Queen = 10, King = 10, Two = 15
    }

    public class Card
    {
        // Objects for card information
        private readonly Suit suit;
        private readonly FaceValue faceVal;
        private bool isCardUp;

        private Texture2D cardTexture;
        private Texture2D cardSkin;

        #region Properties

        public Suit Suit 
        { 
            get 
            { 
                return suit; 
            } 
        }
        
        public FaceValue FaceVal 
        { 
            get 
            { 
                return faceVal; 
            } 
        }
        
        public bool IsCardUp { 
            get 
            { 
                return isCardUp; 
            } 
            set 
            { 
                isCardUp = value; 
            } 
        }

        public Texture2D CardTexture
        {
            get
            {
                return this.cardTexture;
            }
        }

        public Texture2D CardSkin
        {
            get
            {
                return this.cardSkin;
            }
        }

        #endregion

        /// <summary>
        /// Constructor for a new card.  Assign the card a suit, face value, and if the card is facing up or down
        /// </summary>
        /// <param name="suit"></param>
        /// <param name="faceVal"></param>
        /// <param name="isCardUp"></param>
        public Card(Suit suit, FaceValue faceVal, bool isCardUp)
        {
            this.suit = suit;
            this.faceVal = faceVal;
            this.isCardUp = isCardUp;
        }
        
        public void LoadContent(ContentManager content)
        {

            cardTexture = content.Load<Texture2D>("cards/" + this.Suit.ToString() + this.faceVal.ToString());
            cardSkin = content.Load<Texture2D>("cards/CardSkin");
        }

        /// <summary>
        /// Return the card as a string (i.e. "The Ace of Spades")
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return string.Format("{0} of {1}", faceVal, suit); 
        }

        public void Draw(SpriteBatch spriteBatch, int posX, int posY)
        {
            if (isCardUp)
            {
                Rectangle bounds = new Rectangle(posX, posY, cardTexture.Width, cardTexture.Height);
                spriteBatch.Draw(cardTexture, bounds, Color.White);
            }
            else
            {
                Rectangle bounds = new Rectangle(posX, posY, cardSkin.Width, cardSkin.Height);
                spriteBatch.Draw(cardSkin, bounds, Color.White);
            }
        }
    }
}



Hand class:

#region File Description
//-----------------------------------------------------------------------------
// Hand.cs
//-----------------------------------------------------------------------------
#endregion

#region Using Statements

using System;
using System.Configuration;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

#endregion

namespace OverTheTop.CardGameFramework
{
    public class Hand
    {
        // Creates a list of cards
        protected List<Card> cards = new List<Card>();
        public int NumCards { get { return cards.Count; } }
		public List<Card> Cards { get { return cards; } }

    }
}



Deck class:

#region File Description
//-----------------------------------------------------------------------------
// Deck.cs
//-----------------------------------------------------------------------------
#endregion

#region Using Statements

using System;
using System.Configuration;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

#endregion

namespace OverTheTop.CardGameFramework
{
    public class Deck
    {
        // Creates a list of cards
        protected List<Card> cards = new List<Card>();
        private Rectangle bounds;

		// Returns the card at the given position
		public Card this[int position] { get { return (Card)cards[position]; } }

        /// <summary>
        /// One complete deck with every face value and suit
        /// </summary>
        public Deck()
        {
            foreach (Suit suit in Enum.GetValues(typeof(Suit)))
            {
                foreach (FaceValue faceVal in Enum.GetValues(typeof(FaceValue)))
                {
                    cards.Add(new Card(suit, faceVal, true));
                }
            }
        }

        
        public void LoadContent(ContentManager content)
        {
            foreach (Card card in cards)
            {
                card.LoadContent(content);
            }
        }

        
        public void DrawDeck(SpriteBatch spriteBatch, Texture2D texture, int posX, int posY) 
        {
            int i;
            for (i = 0; i < 2; i++)
            {
                bounds = new Rectangle(posX + (4 * i), posY + (4 * i), texture.Width, texture.Height);
                spriteBatch.Draw(texture, bounds, Color.White);
            }
        }
    }
}



OTTGame class:

#region File Description
//-----------------------------------------------------------------------------
// OTTGame.cs
//-----------------------------------------------------------------------------
#endregion

#region Using Statements

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework.Content;
using OverTheTop.CardGameFramework;

#endregion

namespace OverTheTop.GameFramework
{
	public class OTTGame
	{
		#region Fields

        // private Deck and Player objects for the current deck, dealer, and player
		private Deck deck;
        protected List<Player> players = new List<Player>();
        public int numPlayers;
        public List<Player> Players { get { return players; } }

        private Player player;

		#endregion

		#region Properties

        // public properties to return the current player, dealer, and current deck
        public int NumPlayers { get { return numPlayers; } }
        public Deck CurrentDeck { get { return deck; } }

		#endregion

		#region Main Game Constructor

        /// <summary>
        /// Main Constructor for BlackJack Game
        /// </summary>
        /// <param name="initBalance"></param>
        public OTTGame(int numPlayers)
		{
            int i;
            Random random = new Random();
            
            int num = random.Next(2);
            this.numPlayers = numPlayers;

            for (i = 0; i < numPlayers; i++)
            {
                player = new Player();

                if (i == 1)
                    player.IsAI = false;
                else
                    player.IsAI = true;

                players.Add(player);
            }
		}

		#endregion

		#region Game Methods

        /// <summary>
        /// Deals a new game.  This is invoked through the Deal button in BlackJackForm.cs
        /// </summary>
		public void DealNewGame()
		{
            // Create a new deck and then shuffle the deck
            deck = new Deck();
            
            deck.Shuffle();

			// Reset the player and the dealer's hands in case this is not the first game
            foreach (Player p in players)
            {
                p.NewHand();

                // Deal seven cards to each person's hand
                for (int i = 0; i < 7; i++)
                {
                    Card c = deck.Draw();

                    if (p.IsAI)
                        c.IsCardUp = false;

                    p.Hand.Cards.Add(c);
                }

                // Give the player a handle to the current deck
                p.CurrentDeck = deck;
            }
		}

		#endregion
	}
}



GameplayScreen Class:

#region File Description
//-----------------------------------------------------------------------------
// GameplayScreen.cs
//-----------------------------------------------------------------------------
#endregion

#region Using Statements

using System;
using System.Threading;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using OverTheTop.GameFramework;
using OverTheTop.CardGameFramework;

#endregion

namespace OverTheTop
{
    /// <summary>
    /// This screen implements the actual game logic. It is just a
    /// placeholder to get the idea across: you'll probably want to
    /// put some more interesting gameplay in here!
    /// </summary>
    class GameplayScreen : GameScreen
    {
        #region Fields

        ContentManager content;

        private Texture2D cardSkin;

        OTTGame ottGame;

        int noOfPlayers;

        #endregion

        #region Initialization

        /// <summary>
        /// Constructor.
        /// </summary>
        public GameplayScreen(int noOfPlayers)
        {
            this.noOfPlayers = noOfPlayers;
            ottGame = new OTTGame(noOfPlayers);
            ottGame.DealNewGame();
        }

        /// <summary>
        /// Load graphics content for the game.
        /// </summary>
        public override void LoadContent()
        {
            if (content == null)
                content = new ContentManager(ScreenManager.Game.Services, "Content");

            //Load the deck content and all cards in it
            ottGame.CurrentDeck.LoadContent(content);
            
            //Load the card skin for the 3 displayable deck cards
            cardSkin = content.Load<Texture2D>("cards/CardSkin");
        }


        /// <summary>
        /// Unload graphics content used by the game.
        /// </summary>
        public override void UnloadContent()
        {
            content.Unload();
        }


        #endregion

        #region Draw


        /// <summary>
        /// Draws the gameplay screen.
        /// </summary>
        public override void Draw(GameTime gameTime)
        {
            spriteBatch.Begin();

            // Draw the deck cards
            ottGame.CurrentDeck.DrawDeck(spriteBatch,cardSkin,300,300);

            switch (noOfPlayers)
            {
                case 2:

                    for (int i = 0; i < ottGame.Players.Count; i++)
                    {
                        List<Card> cards = ottGame.Players[i].Hand.Cards;
                        for (int j = 0; j < cards.Count; j++)
                        {
                            switch (i)
                            {
                                case 0:
                                    cards[j].Draw(spriteBatch, (250 + (j * 35)), 450);
                                    break;
                                case 1:
                                    cards[j].Draw(spriteBatch, (540 - (j * 35)), 260);
                                    break;
                            }
                        }
                    }
                    break;
            }

            spriteBatch.End();
        }

        #endregion
    }
}



I've tried looking at the ToString methods of the Suit and FaceVal enums in the Card class but I think the Faceval is either returning the value number and not the enum itself i.e. Jack = 10 is returning just 10, which would account for the cardTexture from not being selected but not for the cardSkin texture as that is also playing up, but it works just fine when loaded through GameplayScreen to represent the 3 deck cards.

Is This A Good Question/Topic? 0
  • +

Replies To: Help loading card textures

#2 Kilorn  Icon User is offline

  • XNArchitect
  • member icon




Reputation: 1325
  • View blog
  • Posts: 3,504
  • Joined: 03-May 10

Re: Help loading card textures

Posted 31 May 2010 - 04:46 PM

I don't see anywhere in your code that cardSkin.Width is defined.
Was This Post Helpful? 0
  • +
  • -

#3 ShadowsEdge19  Icon User is offline

  • D.I.C Addict

Reputation: 142
  • View blog
  • Posts: 664
  • Joined: 16-January 10

Re: Help loading card textures

Posted 31 May 2010 - 04:49 PM

View PostKilorn, on 31 May 2010 - 03:46 PM, said:

I don't see anywhere in your code that cardSkin.Width is defined.


That has nothing to do with my game since Texture2D defines the Width and Height of all variables already in the XNA framework. It's not the Width or Height of the cardTexture but the texture itself that is missing.
Was This Post Helpful? 0
  • +
  • -

#4 lesPaul456  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 173
  • View blog
  • Posts: 729
  • Joined: 16-April 09

Re: Help loading card textures

Posted 31 May 2010 - 06:24 PM

NullReference exceptions are pretty common for most programmers, so you're going to need to learn to debug your code...

Place a breakpoint at the the Card.LoadContent method, to see if it's being invoked (which I'm guessing is the problem).

If not, place a breakpoint in the Deck.LoadContent method, at the foreach loop. Since LoadContent is generally only called once, you'll need to make sure that the card list is fully populated before that point. If you add any cards after, you'll need to make sure you "manually" invoke their LoadContent method.

If the breakpoint is never reached, go up further the hierarchy, and place a breakpoint at the GameplayScreen.LoadContent method, and see why the Deck.LoadContent isn't being called.

Remember to check out the "Locals Window" to examine the value of the values of the objects currently in scope, and the "Immediate Window" to see the value of any object.

By starting at the error, and working you're way back, you'll eventually make it to the source of the problem.
Usually it's some goofy mistake you overlooked.
Was This Post Helpful? 0
  • +
  • -

#5 ShadowsEdge19  Icon User is offline

  • D.I.C Addict

Reputation: 142
  • View blog
  • Posts: 664
  • Joined: 16-January 10

Re: Help loading card textures

Posted 01 June 2010 - 08:25 AM

I found the problem, I have been trying to load the content of all 52 cards in the Deck, however the content gets loaded AFTER the Player's Hand has been given 7 cards each, removing them from the deck. So I'm trying to load the content of only 38 cards in the 2 Player mode after 14 cards are removed, but the Deck loads only 38 cards instead and the cards in the Player's Hand hasn't been given any content by the time it wants to draw them.

I've managed to fix this by copying the LoadContent for the Deck and placing it in the Hand class and loading the content for each player in the GameplayScreen class.

This post has been edited by ShadowsEdge19: 01 June 2010 - 09:01 AM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1