#region Using Statements
using System;
using System.Collections.Generic;
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.Net;
using Microsoft.Xna.Framework.Storage;
#endregion
namespace CellAuto
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
int screenWidth = 800;
int screenHeight = 600;
int screenSize = 800 * 600;
Texture2D CA;
Color[] caTexture;
Color[] caBuffer;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
caTexture = new Color[screenSize];
caBuffer = new Color[screenSize];
}
public void InitializeCA()
{
Random random = new Random();
Color black = Color.Black;
Color white = Color.White;
// Seed the CA with random values
for (int i = 0; i < screenSize; i++)
{
int RandomBinary = random.Next(2); // generate a random number between 0 and 1
if( 0 == RandomBinary ) // if 0, then add black
{
caTexture = black;
}
else // if 1, then add white
{
caTexture = white;
}
}
// Create the texture
CA = new Texture2D(graphics.GraphicsDevice, screenWidth, screenHeight, 1, TextureUsage.None, SurfaceFormat.Color);
// Set the new data to the texture
CA.SetData<Color>(caTexture);
}
public void GameOfLife()
{
// Update buffer using ruleset
for (int y = 0; y < screenHeight; y++)
{
for (int x = 0; x < screenWidth; x++)
{
caBuffer[y * screenWidth + x] = GameOfLifeRules(x, y);
}
}
// replace original with buffer
for (int i = 0; i < screenSize; i++)
{
caTexture = caBuffer;
}
}
private Color GameOfLifeRules(int X, int Y)
{
// Original game of life rules made image converge too quickly, so this is used.
int temp = LiveNeighborCount(X, Y);
if (0 <= temp && temp <= 2)
{
return Color.Black;
}
if (3 == temp)
{
return Color.White;
}
if (5 == temp)
{
return Color.Black;
}
if (6 <= temp)
{
return Color.White;
}
return caTexture[Y*screenWidth+X];
}
private int LiveNeighborCount(int X, int Y)
{
int retVal = 0;
// Test for bounds
int left = 0,
leftAbove = 0,
above = 0,
rightAbove = 0,
right = 0,
rightBelow = 0,
below = 0,
leftBelow = 0;
// Left
if (X > 0)
{
if (Color.White == caTexture[Y * screenWidth + X - 1])
{
left = 1;
}
}
// Left Above
if (X > 0 && Y > 0)
{
if (Color.White == caTexture[(Y - 1) * screenWidth + X - 1])
{
leftAbove = 1;
}
}
// Above
if (Y > 0)
{
if (Color.White == caTexture[(Y - 1) * screenWidth + X])
{
above = 1;
}
}
// Right Above
if (X+1 < screenWidth && Y > 0)
{
if (Color.White == caTexture[(Y - 1) * screenWidth + X + 1])
{
rightAbove = 1;
}
}
// Right
if (X+1 < screenWidth)
{
if (Color.White == caTexture[Y * screenWidth + X + 1])
{
right = 1;
}
}
// Right Below
if (X+1 < screenWidth && Y+1 < screenHeight)
{
if (Color.White == caTexture[(Y + 1) * screenWidth + X + 1])
{
rightBelow = 1;
}
}
// Below
if (Y + 1 < screenHeight)
{
if (Color.White == caTexture[(Y + 1) * screenWidth + X])
{
below = 1;
}
}
// Left Below
if (X > 0 && Y + 1 < screenHeight)
{
if (Color.White == caTexture[(Y + 1) * screenWidth + X - 1])
{
leftBelow = 1;
}
}
retVal = left + leftAbove + above + rightAbove + right + rightBelow + below + leftBelow;
return retVal;
}
/// <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
InitializeCA();
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
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
CA.Dispose();
// 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>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
// This updates the data in the CA so it actually evolves
// Uses the game of life rule
GameOfLife();
// Hack to refresh the texture, discard the previous one and create a new texture with the
// updated buffer
CA.Dispose();
CA = new Texture2D(graphics.GraphicsDevice, screenWidth, screenHeight, 1, TextureUsage.None, SurfaceFormat.Color);
CA.SetData<Color>(caTexture);
// Draw the sprites to screen
spriteBatch.Begin();
spriteBatch.Draw(CA, Vector2.Zero, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
Cellular Automaton in XNA - Need way to create changing textures
This is my first actual project using C# and XNA. I would really appreciate it if people could point out any flaws/hack code so I can learn.
It is a simple cellular automaton that is initially randomly seeded, then updated every frame. The part I feel is most hack-ish is where I recreate the texture each frame. It would be great to know a better way. If something isn't clear from the code ask away.
*edit* I guess what I really would like to know is, is there a bettere way to draw individual pixels to screen then creating a texture, destroying it and creating a new one. I suppose you could multiple textures and create a buffering system but that still would leave you with remaking alot of textures.
Also if anyone knows a performance analyzer for C# that would help also, didn't find anything that looked good when I looked.
[Edited by - bmanruler on January 28, 2008 12:03:11 PM]
Just change the data in the texture instead of creating and destroying it every frame. You can also just swap references to the buffers instead of copying every single pixel (in the CPU part of things).
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement