Clickable Tiles
I recently decided to learn and make small 2D game using XNA framework. So i started by editing an example in "XNA 4.0 Game Development by Example" book by Kurt Jaegers and atm i'm stuck at displaying sprites.. I would like to make something like mahjong solitaire where tiles are destroyed when you select two same pieces. So Im displaying a board with random pieces but dont know how to draw clicked tile in different color to show that i've selected it. That's main Game1 class:
public class Game1 : Microsoft.Xna开发者_开发百科.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D titleScreen;
Texture2D backgroundscreen;
Texture2D playingTiles;
Board gameBoard;
Vector2 gameBoardDisplayOrigin = new Vector2(70, 89);
enum GameStates { TitleScreen, Playing };
GameStates gameState = GameStates.TitleScreen;
Rectangle EmptyPiece = new Rectangle(247, 165, 40, 40);
const float MinTimeSinceLastInput = 0.25f;
float timeSinceLastInput = 0.0f;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
this.IsMouseVisible = true;
graphics.PreferredBackBufferWidth = 800;
graphics.PreferredBackBufferHeight = 600;
graphics.ApplyChanges();
gameBoard = new Board();
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
titleScreen = Content.Load<Texture2D>(@"Textures\TitleScreen");
backgroundscreen = Content.Load<Texture2D>(@"Textures\Background");
playingTiles = Content.Load<Texture2D>(@"Textures\MSuXTiles");
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
/// /// ******************* UPDATE *********************
/// ********************************************************
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// TODO: Add your update logic here
switch (gameState)
{
case GameStates.TitleScreen:
if (Keyboard.GetState().IsKeyDown(Keys.Space))
{
gameBoard.ClearBoard();
gameBoard.GenerateNewTiles();
//playerScore = 0;
gameState = GameStates.Playing;
}
break;
case GameStates.Playing:
timeSinceLastInput += (float)gameTime.ElapsedGameTime.TotalSeconds;
if (timeSinceLastInput >= MinTimeSinceLastInput)
{
HandleMouseInput(Mouse.GetState());
}
//gameBoard.GenerateNewTiles();
break;
}
base.Update(gameTime);
}
/// ********************** DRAW ************************
/// ********************************************************
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
if (gameState == GameStates.TitleScreen)
{
spriteBatch.Begin();
spriteBatch.Draw(titleScreen, new Rectangle(0, 0, this.Window.ClientBounds.Width,
this.Window.ClientBounds.Height), Color.White);
spriteBatch.End();
}
if (gameState == GameStates.Playing)
{
spriteBatch.Begin();
spriteBatch.Draw(backgroundscreen, new Rectangle(0, 0,
this.Window.ClientBounds.Width, this.Window.ClientBounds.Height), Color.White);
for (int x = 0; x < Board.BoardWidth; x++)
for (int y = 0; y < Board.BoardHeight; y++)
{
int pixelX = (int)gameBoardDisplayOrigin.X + (x * GameTile.TileWidth);
int pixelY = (int)gameBoardDisplayOrigin.Y + (y * GameTile.TileHeight);
//rysujemy tlo dla przezroczystych obrazkow
/*spriteBatch.Draw(
playingTiles,
new Rectangle(pixelX, pixelY, GameTile.TileWidth, GameTile.TileHeight),
EmptyPiece,
Color.White);*/
spriteBatch.Draw(
playingTiles,
new Rectangle(pixelX, pixelY, GameTile.TileWidth, GameTile.TileHeight),
gameBoard.GetSourceRect(x, y),
Color.White);
}
//this.Window.Title = playerScore.ToString();
spriteBatch.End();
}
base.Draw(gameTime);
}
//input handling
private void HandleMouseInput(MouseState mouseState)
{
int x = ((mouseState.X - (int)gameBoardDisplayOrigin.X) / GameTile.TileWidth);
int y = ((mouseState.Y - (int)gameBoardDisplayOrigin.Y) / GameTile.TileHeight);
if ((x >= 0) && (x < Board.BoardWidth) &&
(y >= 0) && (y < Board.BoardHeight))
{
if (mouseState.LeftButton == ButtonState.Pressed)
{
gameBoard.TintSelectedTile(x, y);
timeSinceLastInput = 0.0f;
}
if (mouseState.RightButton == ButtonState.Pressed)
{
timeSinceLastInput = 0.0f;
}
}
}
}
Board class :
class Board
{
Random rand = new Random();
public const int BoardWidth = 10;
public const int BoardHeight = 10;
private GameTile[,] boardOfTiles = new GameTile[BoardWidth, BoardHeight];
//constructor
public Board()
{
ClearBoard();
}
public void ClearBoard()
{
for (int x = 0; x < BoardWidth; x++)
for (int y = 0; y < BoardHeight; y++)
boardOfTiles[x, y] = new GameTile("Empty,Four");
}
//methods
public Rectangle GetSourceRect(int x, int y)
{
return boardOfTiles[x, y].GetSourceRect();
}
public string GetSquare(int x, int y)
{
return boardOfTiles[x, y].TileType;
}
public void SetSquare(int x, int y, string tileName)
{
boardOfTiles[x, y].SetTile(tileName);
}
public void RandomPiece(int x, int y)
{
boardOfTiles[x, y].SetTile(GameTile.TileTypes[rand.Next(0, GameTile.MaxTilesColumnIndex),
rand.Next(0, GameTile.MaxTilesRowIndex)]);
}
public void GenerateNewTiles()
{
for (int y = 0; y < Board.BoardHeight; y++)
for (int x = 0; x < Board.BoardWidth; x++)
{
if (GetSquare(x, y) == "Empty,Four")
{
RandomPiece(x, y);
}
}
}
} and GameTile class:
class GameTile
{
public static string[,] TileTypes =
{
{"Circle,One", "Circle,Two", "Circle,Three", "Circle,Four", "Circle,Five",
"Circle,Six", "Circle,Seven", "Circle,Eight", "Circle,Nine"},
{"Bamboo,One", "Bamboo,Two", "Bamboo,Three", "Bamboo,Four", "Bamboo,Five",
"Bamboo,Six", "Bamboo,Seven", "Bamboo,Eight", "Bamboo,Nine"},
{"Character,One", "Character,Two", "Character,Three", "Character,Four", "Character,Five",
"Character,Six", "Character,Seven", "Character,Eight", "Character,Nine"},
{"Honor,One", "Honor,Two", "Honor,Three", "Honor,Four", "Something1,Five",
"Something2,Six", "Something3,Seven", "Something4,Eight", "Something5,Nine"},
{"Dragon,One", "Dragon,Two", "Dragon,Three", "Empty,Four", "Something6,Five",
"Something7,Six", "Something8,Seven", "Something9,Eight", "Something10,Nine"},
{"Flower,One", "Flower,Two", "Flower,Three", "Flower,Four", "Something11,Five",
"Something12,Six", "Something13,Seven", "Something14,Eight", "Something15,Nine"},
{"Season,One", "Season,Two", "Season,Three", "Season,Four", "Something16,Five",
"Something17,Six", "Something18,Seven", "Something19,Eight", "Something20,Nine"}
};
public const int TileHeight = 40;
public const int TileWidth = 40;
public const int MaxTilesRowIndex = 9;
public const int MaxTilesColumnIndex = 7;
private const int textureOffsetX = 1;
private const int textureOffsetY = 1;
private const int texturePaddingX = 1;
private const int texturePaddingY = 1;
private string tileType = "";
public string TileType
{
get { return tileType; }
}
//konstruktory
public GameTile(string type)
{
tileType = type;
}
//metody
public void SetTile(string type)
{
tileType = type;
}
public Rectangle GetSourceRect()
{
int x = textureOffsetX;
int y = textureOffsetY;
foreach (string s in tileType.Split(','))
{
switch(s)
{
case "One":
//y = y;
break;
case "Two":
y = y + (TileHeight + texturePaddingY);
break;
case "Three":
y = y + 2 * (TileHeight + texturePaddingY);
break;
case "Four":
y = y + 3 * (TileHeight + texturePaddingY);
break;
case "Five":
y = y + 4 * (TileHeight + texturePaddingY);
break;
case "Six":
y = y + 5 * (TileHeight + texturePaddingY);
break;
case "Seven":
y = y + 6 * (TileHeight + texturePaddingY);
break;
case "Eight":
y = y + 7 * (TileHeight + texturePaddingY);
break;
case "Nine":
y = y + 8 * (TileHeight + texturePaddingY);
break;
case "Circle":
//x = x;
break;
case "Bamboo":
x = x + (TileWidth + texturePaddingX);
break;
case "Character":
x = x + 2 * (TileWidth + texturePaddingX);
break;
case "Honor":
x = x + 3 * (TileWidth + texturePaddingX);
break;
case "Dragon":
x = x + 4 * (TileWidth + texturePaddingX);
break;
case "Flower":
x = x + 5 * (TileWidth + texturePaddingX);
break;
case "Season":
x = x + 6 * (TileWidth + texturePaddingX);
break;
}
}
return new Rectangle(x, y, TileHeight, TileWidth);
}
}
and that's how it looks atm: http://i55.tinypic.com/2yuizbl.png
An easy thing you can do is, in the SpriteBatch.Draw()
call for the clicked, tile, change Color.White
into some other color--maybe a Red
. This will cause the tile to be shaded the new color.
If you'd prefer some other effect, you can render your clicked tile to a separate RenderTarget2D
, perform any enhancements you'd like to that render target, and then draw the render target to the back buffer.
精彩评论