I want use a depth image to lighting a RawColor image but it not seems good
i want know whats wrong with my code , or its all depth image can do :|
the output image shape like Cone instead of circle and there are many noise on it , what i want to know is my code wrong or its not right way to do this?!
for that i get normal for each pixel and add it to a texture and send it to pixel shader to use for lighting. result image and code are added here
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D depth;
Texture2D image;
Texture2D texNormal;
Vector3 cameraPos = new Vector3(0.5f, 0.5f, -0.0999f);
Effect mEffect;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
graphics.PreferredBackBufferWidth = 1000;
graphics.PreferredBackBufferHeight = 1000;
graphics.ApplyChanges();
base.Initialize();
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
depth = Content.Load<Texture2D>("depth");
image = Content.Load<Texture2D>("image");
texNormal = getNormalFromDepth(depth);
mEffect = Content.Load<Effect>("depthEffect");
// TODO: use this.Content to load your game content here
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
if (Keyboard.GetState().IsKeyDown(Keys.W))
{
cameraPos.Y += 0.01f;
}
if (Keyboard.GetState().IsKeyDown(Keys.S))
{
cameraPos.Y -= 0.01f;
}
if (Keyboard.GetState().IsKeyDown(Keys.A))
{
cameraPos.X -= 0.01f;
}
if (Keyboard.GetState().IsKeyDown(Keys.D))
{
cameraPos.X += 0.01f;
}
if (Keyboard.GetState().IsKeyDown(Keys.Up))
{
cameraPos.Z += 0.01f;
}
if (Keyboard.GetState().IsKeyDown(Keys.Down))
{
cameraPos.Z -= 0.01f;
}
// TODO: Add your update logic here
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
GraphicsDevice.Textures[1] = texNormal;
mEffect.Parameters["LightPos"].SetValue(cameraPos);
// TODO: Add your drawing code here
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, mEffect);
spriteBatch.Draw(image, new Rectangle(0, 0, 500, 500), Color.White);
spriteBatch.End();
spriteBatch.Begin();
spriteBatch.Draw(texNormal, new Rectangle(500, 0, 500, 500), Color.White);
spriteBatch.Draw(image, new Rectangle(500, 500, 500, 500), Color.White);
spriteBatch.Draw(depth, new Rectangle(0, 500, 500, 500), Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
Texture2D getNormalFromDepth(Texture2D depth)
{
Texture2D output = new Texture2D(GraphicsDevice, depth.Width, depth.Height);
Color[] outbyte = new Color[depth.Width * depth.Height];
Color[] colors1D = new Color[depth.Width * depth.Height];
depth.GetData(colors1D);
Color[,] colors2D = new Color[depth.Width, depth.Height];
for (int x = 0; x < depth.Width; x++)
{
for (int y = 0; y < depth.Height; y++)
{
colors2D[x, y] = colors1D[x + y * depth.Width];
}
}
for (int x = 0; x < depth.Width; x++)
{
for (int y = 0; y < depth.Height; y++)
{
float left = GetHeight(colors2D, ref depth, x - 1, y);
float right = GetHeight(colors2D, ref depth, x + 1, y);
float top = GetHeight(colors2D, ref depth, x, y - 1);
float bottom = GetHeight(colors2D, ref depth, x, y + 1);
// Compute gradient vectors, then cross them to get the normal.
Vector3 dx = new Vector3(1, 0, (right - left) * 1);
Vector3 dy = new Vector3(0, 1, (bottom - top) * 1);
Vector3 normal = Vector3.Cross(dx, dy);
normal.Normalize();
// Store the result.
float alpha = colors2D[x, y].A;
outbyte[y * depth.Width + x] = new Color(new Vector4(normal, alpha));
}
}
output.SetData(outbyte);
return output;
}
float GetHeight(Color[,] depth, ref Texture2D depthImage, int x, int y)
{
if (x < 0)
{
x = 0;
}
else if (x >= depthImage.Width)
{
x = depthImage.Width - 1;
}
if (y < 0)
{
y = 0;
}
else if (y >= depthImage.Height)
{
y = depthImage.Height - 1;
}
Color mColor = (depth[x, y]);
float output = (mColor.R + mColor.G + mColor.B) / 3;
return output;
}
}
and shader Code is here
sampler normalSampler : register(s1);
sampler imageSampler : register(s0);
float3 LightPos = (1,0,-0.5);
float3 AmbientColor = (0.1,0.1,0.1);
float3 LightColor = (0.9,0.9,0.9);
float4 main(float4 color : COLOR0 ,float2 texCoord : TEXCOORD0):COLOR0
{
float4 output = float4(1,1,1,1);
float4 normal = tex2D(normalSampler,texCoord);
float4 imageColor = tex2D(imageSampler,texCoord);
float3 tex3DCoord = float3(texCoord.x,texCoord.y,0);
float3 lighting = AmbientColor;
float3 lightDir = (LightPos - tex3DCoord);
lighting += ( LightColor* max(dot(normal.xyz, lightDir), 0));
output = float4 (imageColor*lighting,1);
return output;
}
technique Technique1
{
pass Pass1
{
PixelShader = compile ps_2_0 main();
}
}
Related
I have two classes, Main and Grid. Grid simply makes a grid of square pixels. In my Main class, I want to get the list that was create in the Grid class. I managed to figure it out, but I'm wondering if there's a way to optimize the code.
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Diagnostics;
using System.Collections.Generic;
namespace teeeest
{
public class Grid
{
Texture2D image;
Color color;
int rows;
int columns;
float outerThickness;
float innerThickness;
Vector2 size;
Vector2 origin;
Vector2 dotSize;
List<Pixel> pixels = new List<Pixel>(0);
public Grid(Texture2D image, int rows, int columns, float outerThickness, float innerThickness, Vector2 size, Vector2 origin, Vector2 dotSize, Color color)
{
this.dotSize = dotSize;
this.origin = origin;
this.color = color;
this.image = image;
this.rows = rows;
this.columns = columns;
this.outerThickness = outerThickness;
this.innerThickness = innerThickness;
this.size = size;
}
public void Update()
{
float sizeX = size.X / (columns - 1);
float sizeY = size.Y / (rows - 1);
for (int i = 0; i < rows; i++)
{
for (int g = 0; g < columns; g++)
{
Pixel p = new Pixel(image, 3, new Vector2((g * sizeX) + origin.X, sizeY * i + origin.Y), new Vector2(image.Width / 2, image.Height / 2), color);
pixels.Add(p);
}
}
}
public virtual void Draw(SpriteBatch hspritebatch, List<Grid> grids)
{
foreach (Pixel p in pixels)
{
hspritebatch.Draw(
texture: p.getImage(),
position: p.getPosition(),
sourceRectangle: null,
p.getColor(),
rotation: 0,
origin: new Vector2(image.Width / 2, image.Height),
scale: new Vector2(dotSize.X * .02f, dotSize.Y * .02f),
SpriteEffects.None,
0);
}
}
public Texture2D getImage()
{
return image;
}
public Vector2 getPosition()
{
return origin;
}
public Vector2 getOrigin()
{
return new Vector2(image.Width / 2, image.Height);
}
public Color getColor()
{
return color;
}
public List<Pixel> getList()
{
Update(); # This seems unnecessary. Is it?
return pixels;
}
}
}
The problem lies in the getList() function. In order to return the correct pixel list that was edited in the Update function, my solution there is to call that function right before returning the list. However, this seems costly for no reason. Is there a way around this without calling the Update function, or is this the only way?
I realize there's been posts similar to this, but I just don't understand them. I'm very much a beginner at coding. Here is my Main class.
using System;
using System.Diagnostics;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
namespace teeeest
{
public class Game1 : Game
{
private GraphicsDeviceManager _graphics;
private SpriteBatch _spriteBatch;
private SpriteFont font;
private Texture2D ball;
private Texture2D square;
private Color color = Color.White * .1f;
private Vector2 MouseCoords;
private Vector2 winMiddle;
private Vector2 ballOrigin;
private bool leftDown;
private bool eDown;
private int winWidth;
private int winHeight;
List<Line> lines = new List<Line>(0);
List<Grid> grids = new List<Grid>(0);
List<Pixel> pixels = new List<Pixel>(0);
List<Pixel> test = new List<Pixel>(0);
public Game1()
{
_graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
_graphics.PreferredBackBufferWidth = 800;
_graphics.PreferredBackBufferHeight = 600;
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
ball = Content.Load<Texture2D>("ball");
square = Content.Load<Texture2D>("square");
font = Content.Load<SpriteFont>("File");
ballOrigin = new Vector2(ball.Width / 2, ball.Height / 2);
winWidth = _graphics.PreferredBackBufferWidth;
winHeight = _graphics.PreferredBackBufferHeight;
winMiddle = new Vector2(winWidth / 2, winHeight / 2);
}
protected override void Update(GameTime gameTime)
{
lines.Clear();
grids.Clear();
pixels.Clear();
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
if (Mouse.GetState().LeftButton == ButtonState.Released)
{
leftDown = false;
}
if (Mouse.GetState().LeftButton == ButtonState.Pressed && !leftDown)
{
Pixel g = new Pixel(ball, 5, MouseCoords, new Vector2(ball.Width / 2, ball.Height / 2), Color.Blue);
pixels.Add(g);
}
if (Keyboard.GetState().IsKeyUp(Keys.E))
{
eDown = false;
}
if (Keyboard.GetState().IsKeyDown(Keys.E) && !eDown)
{
color *= 1.1f;
eDown = true;
}
MouseCoords = new Vector2(Mouse.GetState().X, Mouse.GetState().Y);
Grid q = new Grid(ball, 10, 10, 7, 3, new Vector2(500, 500), new Vector2(30, 30), new Vector2(.2f, .2f), Color.White);
grids.Add(q);
# Here is where I'm calling the getList() function.
System.Console.WriteLine(q.getList()[7].getPosition());
# Here is where I'm calling the getList() function.
foreach (Line s in lines)
{
s.Update();
}
foreach (Grid gh in grids)
{
gh.Update();
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
_spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
foreach (Line l in lines)
{
l.Draw(_spriteBatch, lines);
}
foreach (Grid g in grids)
{
g.Draw(_spriteBatch, grids);
}
foreach (Pixel p in pixels)
{
_spriteBatch.Draw(
texture: p.getImage(),
position: p.getPosition(),
sourceRectangle: null,
p.getColor(),
rotation: 0,
origin: p.getOrigin(),
scale: new Vector2(.02f, .02f),
SpriteEffects.None,
0);
}
_spriteBatch.DrawString(font,
MouseCoords.ToString(),
new Vector2 (winWidth - 100, 10),
Color.White,
rotation: 0,
origin: new Vector2(0, 0),
scale: new Vector2(1, 1),
SpriteEffects.None,
0);
_spriteBatch.End();
base.Draw(gameTime);
}
}
}
You could only call Update() when the List is EMPTY?
public List<Pixel> getList()
{
if (pixels.Count == 0)
{
Update(); // now it only gets called when pixels is EMPTY
}
return pixels;
}
This type of check may need to be done in Update() as well if it can be called directly from other places so you don't end up with more Pixel instances in it than you were expecting.
How detect collision with sprite animation?
SpriteManager.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using System.IO;
namespace Mini
{
public class SpriteManager
{
protected Texture2D Texture;
public Vector2 Position = Vector2.Zero;
protected Dictionary<string, AnimationClass> Animations =
new Dictionary<string, AnimationClass>();
protected int FrameIndex = 0;
protected Vector2 Origin;
private int height;
private int width;
private string animation;
public string Animation
{
get { return animation; }
set
{
animation = value;
FrameIndex = 0;
}
}
public int Height
{
get { return height; }
}
public int Width
{
get { return width; }
}
public Rectangle Rectangle
{
get { return Animations[Animation].Rectangles[FrameIndex]; }
}
public Texture2D Texture2D
{
get { return Texture; }
}
public SpriteManager(Texture2D Texture, int Frames, int animations)
{
this.Texture = Texture;
width = Texture.Width / Frames;
height = Texture.Height / animations;
Origin = new Vector2(width / 2, height / 2);
}
public void AddAnimation(string name, int row,
int frames, AnimationClass animation)
{
Rectangle[] recs = new Rectangle[frames];
Color[][] frameImageData = new Color[frames][];
Texture2D[][] frameImage = new Texture2D[frames][];
for (int i = 0; i < frames; i++)
{
recs[i] = new Rectangle(i * width,
(row - 1) * height, width, height);
frameImageData[i] = new Color[width * height];
}
animation.Frames = frames;
animation.Rectangles = recs;
Animations.Add(name, animation);
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(Texture, Position,
Animations[Animation].Rectangles[FrameIndex],
Animations[Animation].Color,
Animations[Animation].Rotation, Origin,
Animations[Animation].Scale,
Animations[Animation].SpriteEffect, 0f);
}
public bool IntersectPixels(SpriteManager b)
{
Rectangle rectangleA = this.Rectangle;
Rectangle rectangleB = b.Rectangle;
int top = Math.Max(rectangleA.Top, rectangleB.Top);
int bottom = Math.Min(rectangleA.Bottom, rectangleB.Bottom);
int left = Math.Max(rectangleA.Left, rectangleB.Left);
int right = Math.Min(rectangleA.Right, rectangleB.Right);
Color[] dataA = new Color[rectangleA.Width * rectangleA.Height];
this.Texture.GetData(0, rectangleA, dataA, 0, rectangleA.Width * rectangleA.Height);
Color[] dataB = new Color[rectangleB.Width * rectangleB.Height];
b.Texture.GetData(0, rectangleB, dataB, 0, b.Width * b.Height);
Stream s = File.Create("t.png");
b.Texture2D.SaveAsPng(s, rectangleB.Width, rectangleB.Height);
for (int y = top; y < bottom; y++)
{
for (int x = left; x < right; x++)
{
Color colorA = dataA[(x - rectangleA.Left) + (y - rectangleA.Top) * rectangleA.Width];
Color colorB = dataB[(x - rectangleB.Left) + (y - rectangleB.Top) * rectangleB.Width];
if (colorA.A != 0 && colorB.A != 0)
{
return true;
}
}
}
return false;
}
}
}
With this code, the collision is detected every few frames of animation anywhere
IntersectPixels is to detect collisions.
I'm building a game using xna and I've created a terrain using VertexElementNormalTexture. I understand I can add position, the normal and texture coordinates to the vertex element but is there anyway to add which texture I want to use. I'm testing it on my Lumia phone so it's being built without the use of custom shaders because they're unsupported by the phone making most of the tutorials on the web out of date. I believe the basiceffects only support one texture per effect so if I make a number of effects how do I get the vertex to know which effect to use? the grasseffect, watereffect, etc.
The code I've got so far is below.
Thank you.
using System;
using System.Collections.Generic;
using System.Linq;
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.Input.Touch;
using Microsoft.Xna.Framework.Media;
using Microsoft.Devices.Sensors;
namespace WindowsPhoneGame2
{
public class Game1 : Microsoft.Xna.Framework.Game
{
#region // Variables
public struct VertexPositionColorNormal
{
public Vector3 Position;
public Color Color;
public Vector3 Normal;
public readonly static VertexDeclaration VertexDeclaration = new VertexDeclaration
(
new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
new VertexElement(sizeof(float) * 3, VertexElementFormat.Color, VertexElementUsage.Color, 0),
new VertexElement(sizeof(float) * 3 + 4, VertexElementFormat.Vector3, VertexElementUsage.Normal, 0)
);
}
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
RasterizerState rasterizerState;
// terrain
BasicEffect grassEffect;
Texture2D grassTexture;
BasicEffect waterEffect;
Texture2D waterTexture;
VertexDeclaration vertexDeclaration;
VertexPositionNormalTexture[] vertices;
short[] indices;
VertexBuffer myVertexBuffer;
IndexBuffer myIndexBuffer;
private float[,] heightData;
private int terrainWidth;
private int terrainLength;
int nScale = 16;
Vector3 terrainPosition;
Texture2D heightMap;
Matrix viewMatrix;
Matrix projectionMatrix;
Matrix worldMatrix;
// aircraft model
private Model aircraftModel;
private Vector3 aircraftPosition;
Matrix aircraftMatrix;
// shell model
private Model shellModel;
private Vector3 bulletPosition;
Matrix bulletMatrix;
bool blBulletFiring;
private Vector3 torpedoPosition;
Matrix torpedoMatrix;
bool blTorpedoFiring;
float nTorpedoScale;
// display
private SpriteFont font;
float nHeightData;
int nBullets = 0;
int nTorpedoes = 0;
// tilt gesture
private float rollAngle;
private float pitchAngle;
private float yawAngle;
Accelerometer accelerometer;
private const int _num = 5;
private double[] _y = new double[_num];
private int _index = 0;
private const int _num2 = 5;
private double[] _y2 = new double[_num2];
private int _index2 = 0;
Texture2D explosionTexture;
List<ParticleData> particleList = new List<ParticleData>();
public struct ParticleData
{
public float BirthTime;
public float MaxAge;
public Vector2 OrginalPosition;
public Vector2 Accelaration;
public Vector2 Direction;
public Vector2 Position;
public float Scaling;
public Color ModColor;
}
Random random = new Random();
#endregion
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
TouchPanel.EnabledGestures = GestureType.Tap | GestureType.Hold;
loadTextures();
loadAccelerometer();
loadCamera();
loadEffect();
loadTerrain();
}
protected override void UnloadContent()
{
}
private void loadTextures()
{
aircraftModel = Content.Load<Model>("Ship");
shellModel = Content.Load<Model>("Shell");
explosionTexture = Content.Load<Texture2D>("explosion");
heightMap = Content.Load<Texture2D>("heightmap");
grassTexture = Content.Load<Texture2D>("Grass");
waterTexture = Content.Load<Texture2D>("Water");
font = Content.Load<SpriteFont>("DisplayText");
}
private void loadAccelerometer()
{
rollAngle = 0;
if (accelerometer == null)
{
accelerometer = new Accelerometer();
accelerometer.TimeBetweenUpdates = TimeSpan.FromMilliseconds(20);
accelerometer.CurrentValueChanged += new EventHandler<SensorReadingEventArgs<AccelerometerReading>>(accelerometer_CurrentValueChanged);
}
accelerometer.Start();
}
private void loadCamera()
{
aircraftPosition = new Vector3(heightMap.Width * nScale * 2 / 2, 0, 400);
projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, graphics.GraphicsDevice.Viewport.AspectRatio, 10.0f, 8000.0f);
worldMatrix = Matrix.CreateTranslation(0, 0, 0);
terrainPosition = new Vector3(0, 0, 0);
}
private void loadEffect()
{
//grass effect
grassEffect = new BasicEffect(GraphicsDevice);
//grassEffect.VertexColorEnabled = true;
grassEffect.LightingEnabled = true; // Turn on the lighting subsystem.
grassEffect.DirectionalLight0.DiffuseColor = new Vector3(0.1f, 0.1f, 0.1f);
grassEffect.DirectionalLight0.Direction = new Vector3(0, 5, -10);
grassEffect.TextureEnabled = true;
grassEffect.Texture = grassTexture;
//water effect
waterEffect = new BasicEffect(GraphicsDevice);
waterEffect.LightingEnabled = true; // Turn on the lighting subsystem.
waterEffect.DirectionalLight0.DiffuseColor = new Vector3(0.1f, 0.1f, 0.1f);
waterEffect.DirectionalLight0.Direction = new Vector3(0, 5, -10);
waterEffect.TextureEnabled = true;
waterEffect.Texture = waterTexture;
}
private void loadTerrain()
{
LoadHeightData();
SetUpVertices();
SetUpIndices();
CalculateNormals();
CopyToBuffers();
}
private void LoadHeightData()
{
terrainWidth = heightMap.Width;
terrainLength = heightMap.Height;
Color[] heightMapColors = new Color[terrainWidth * terrainLength];
heightMap.GetData(heightMapColors);
heightData = new float[terrainWidth, terrainLength];
for (int x = 0; x < terrainWidth; x++)
for (int y = 0; y < terrainLength; y++)
heightData[x, y] = heightMapColors[x + y * terrainWidth].R / 5.0f;
}
private void SetUpVertices()
{
vertices = new VertexPositionNormalTexture[terrainWidth * terrainLength];
for (int x = 0; x < terrainWidth; x++)
{
for (int y = 0; y < terrainLength; y++)
{
vertices[x + y * terrainWidth].Position = new Vector3(x * nScale * 2, y * nScale, heightData[x, y] * nScale) + terrainPosition;
}
}
}
private void SetUpIndices()
{
indices = new short[(terrainWidth - 1) * (terrainLength - 1) * 6];
int counter = 0;
for (int y = 0; y < terrainLength - 1; y++)
{
for (int x = 0; x < terrainWidth - 1; x++)
{
short lowerLeft = (short)(x + y * terrainWidth);
short lowerRight = (short)((x + 1) + y * terrainWidth);
short topLeft = (short)(x + (y + 1) * terrainWidth);
short topRight = (short)((x + 1) + (y + 1) * terrainWidth);
indices[counter++] = topLeft;
indices[counter++] = lowerRight;
indices[counter++] = lowerLeft;
indices[counter++] = topLeft;
indices[counter++] = topRight;
indices[counter++] = lowerRight;
}
}
}
private void CalculateNormals()
{
for (int i = 0; i < vertices.Length; i++)
vertices[i].Normal = new Vector3(0, 0, 0);
for (int i = 0; i < indices.Length / 3; i++)
{
int index1 = indices[i * 3];
int index2 = indices[i * 3 + 1];
int index3 = indices[i * 3 + 2];
Vector3 side1 = vertices[index1].Position - vertices[index3].Position;
Vector3 side2 = vertices[index1].Position - vertices[index2].Position;
Vector3 normal = Vector3.Cross(side1, side2);
vertices[index1].Normal += normal;
vertices[index2].Normal += normal;
vertices[index3].Normal += normal;
}
for (int i = 0; i < vertices.Length; i++)
vertices[i].Normal.Normalize();
}
private void CopyToBuffers()
{
myVertexBuffer = new VertexBuffer(graphics.GraphicsDevice, VertexPositionNormalTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
myVertexBuffer.SetData(vertices);
myIndexBuffer = new IndexBuffer(graphics.GraphicsDevice, typeof(short), indices.Length, BufferUsage.WriteOnly);
myIndexBuffer.SetData(indices);
}
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// Adjust camera position
viewMatrix = Matrix.CreateLookAt(new Vector3(aircraftPosition.X, aircraftPosition.Y - 10, aircraftPosition.Z + 5), new Vector3(aircraftPosition.X, aircraftPosition.Y + 5, aircraftPosition.Z ), new Vector3(0, 1, 0));
// Adjust aircraft position
aircraftMatrix = Matrix.CreateRotationY(rollAngle) * Matrix.CreateRotationX(pitchAngle) * Matrix.CreateRotationZ(yawAngle) * Matrix.CreateTranslation(aircraftPosition);
aircraftPosition.Y += 10.0f;
// Check against height data for collision
int x = (int)aircraftPosition.X / (nScale * 2);
int y = ((int)aircraftPosition.Y - (int)terrainPosition.Y) / nScale;
if(y < 128) nHeightData = heightData[(int)x, (int)y];
if (nHeightData > aircraftPosition.Z / nScale)
{
aircraftPosition = new Vector3(terrainWidth * nScale * 2 / 2, 0, 400);
terrainPosition = new Vector3(0, 0, 0);
}
// edit weapons fire positions
if (blBulletFiring)
{
bulletPosition.Y += 20;
fireBullet();
}
if (blTorpedoFiring)
{
if (torpedoPosition.Z > 5)
{
torpedoPosition.Z -= 6;
torpedoPosition.Y += 10;
nTorpedoScale = 0.8f;
}
else
{
torpedoPosition.Y += 16;
nTorpedoScale = 1.5f;
}
fireTorpedo();
}
// detect any gestures
while (TouchPanel.IsGestureAvailable)
{
GestureSample gs = TouchPanel.ReadGesture();
switch (gs.GestureType)
{
case GestureType.Tap:
blBulletFiring = true;
bulletPosition = new Vector3(aircraftPosition.X - 0.05f, aircraftPosition.Y, aircraftPosition.Z);
AddExplosion(new Vector2(gs.Position.X, gs.Position.Y), 12, 80.0f, 1500.0f, gameTime);
// AddExplosion(new Vector2(aircraftPosition.X * -1, aircraftPosition.Y * -1), 12, 80.0f, 1500.0f, gameTime);
break;
case GestureType.Hold:
blTorpedoFiring = true;
torpedoPosition = new Vector3(aircraftPosition.X, aircraftPosition.Y, aircraftPosition.Z);
break;
}
}
if (particleList.Count > 0)
UpdateParticles(gameTime);
base.Update(gameTime);
}
private void UpdateParticles(GameTime gameTime)
{
float now = (float)gameTime.TotalGameTime.TotalMilliseconds;
for (int i = particleList.Count - 1; i >= 0; i--)
{
ParticleData particle = particleList[i];
float timeAlive = now - particle.BirthTime;
if (timeAlive > particle.MaxAge)
{
particleList.RemoveAt(i);
}
else
{
float relAge = timeAlive / particle.MaxAge;
particle.Position = 0.5f * particle.Accelaration * relAge * relAge + particle.Direction * relAge + particle.OrginalPosition;
float invAge = 1.0f - relAge;
particle.ModColor = new Color(new Vector4(invAge, invAge, invAge, invAge));
Vector2 positionFromCenter = particle.Position - particle.OrginalPosition;
float distance = positionFromCenter.Length();
particle.Scaling = (50.0f + distance) / 200.0f;
particleList[i] = particle;
}
}
}
private void AddExplosion(Vector2 explosionPos, int numberOfParticles, float size, float maxAge, GameTime gameTime)
{
for (int i = 0; i < numberOfParticles; i++)
AddExplosionParticle(explosionPos, size, maxAge, gameTime);
}
private void AddExplosionParticle(Vector2 explosionPos, float explosionSize, float maxAge, GameTime gameTime)
{
ParticleData particle = new ParticleData();
particle.OrginalPosition = explosionPos;
particle.Position = particle.OrginalPosition;
particle.BirthTime = (float)gameTime.TotalGameTime.TotalMilliseconds;
particle.MaxAge = maxAge;
particle.Scaling = 0.25f;
particle.ModColor = Color.White;
float particleDistance = (float)random.NextDouble() * explosionSize;
Vector2 displacement = new Vector2(particleDistance, 0);
float angle = MathHelper.ToRadians(random.Next(360));
displacement = Vector2.Transform(displacement, Matrix.CreateRotationZ(angle));
particle.Direction = displacement * 2.0f;
particle.Accelaration = -particle.Direction;
particleList.Add(particle);
}
private void fireBullet()
{
nBullets++;
bulletMatrix = Matrix.CreateScale(0.1f) * Matrix.CreateRotationZ(MathHelper.ToRadians(90)) * Matrix.CreateTranslation(bulletPosition);
if (bulletPosition.Y > aircraftPosition.Y + 200)
{
blBulletFiring = false;
}
}
private void fireTorpedo()
{
nTorpedoes++;
torpedoMatrix = Matrix.CreateScale(nTorpedoScale) * Matrix.CreateRotationZ(MathHelper.ToRadians(90)) * Matrix.CreateTranslation(torpedoPosition);
if (torpedoPosition.Y > aircraftPosition.Y + 1000)
{
blTorpedoFiring = false;
}
}
public void accelerometer_CurrentValueChanged(object sender, SensorReadingEventArgs<AccelerometerReading> e)
{
_y[_index++] = e.SensorReading.Acceleration.Y;
if (_index >= _num) _index = 0;
double ysum = 0.0;
for (int i = 0; i < _num; i++)
ysum += _y[i];
double x = ysum / _num;
// Cap it at -0.5 and 0.5
if (x > 0.1)
{
if (rollAngle >= -0.9)
{
rollAngle -= 0.05f;
yawAngle += 0.02f;
}
if (aircraftPosition.X >= 5) aircraftPosition.X -= rollAngle * -5;
}
else if (x <= -0.1)
{
if (rollAngle <= 0.9)
{
rollAngle += 0.05f;
yawAngle -= 0.02f;
}
if (aircraftPosition.X <= terrainWidth * nScale * 2 - 6) aircraftPosition.X += rollAngle * 5;
}
else
{
if (rollAngle > 0.05)
{
rollAngle -= 0.05f;
yawAngle += 0.02f;
}
else if (rollAngle < -0.05)
{
rollAngle += 0.05f;
yawAngle -= 0.02f;
}
else
{
rollAngle = 0;
yawAngle = 0;
}
}
_y2[_index2++] = e.SensorReading.Acceleration.X;
if (_index2 >= _num2) _index2 = 0;
double ysum2 = 0.0;
for (int i = 0; i < _num2; i++)
ysum2 += _y2[i];
double x2 = ysum2 / _num2;
// Cap it at -0.5 and 0.5
if (x2 > -0.4)
{
if(pitchAngle >= -0.6) pitchAngle -= 0.025f;
if (aircraftPosition.Z > 6) aircraftPosition.Z -= pitchAngle * -10;
}
else if (x2 <= -0.5)
{
if (pitchAngle <= 0.6) pitchAngle += 0.025f;
if (aircraftPosition.Z <= 500) aircraftPosition.Z += pitchAngle * 10;
}
else
{
if (pitchAngle > 0.05) pitchAngle -= 0.05f;
else if (pitchAngle < -0.05) pitchAngle += 0.05f;
else pitchAngle = 0;
}
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.CornflowerBlue, 1.0f, 0);
GraphicsDevice.BlendState = BlendState.Opaque;
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
rasterizerState = new RasterizerState();
rasterizerState.FillMode = FillMode.Solid;
rasterizerState.CullMode = CullMode.None;
GraphicsDevice.RasterizerState = rasterizerState;
Vector3 oldPosition = terrainPosition;
loadTerrain();
DrawTerrain();
terrainPosition.Y += nScale * terrainLength - nScale;
loadTerrain();
DrawTerrain();
terrainPosition.Y += nScale * terrainLength - nScale;
loadTerrain();
DrawTerrain();
terrainPosition.Y -= nScale * terrainLength - nScale;
if (aircraftPosition.Y >= terrainPosition.Y)
{ }
else
{
terrainPosition = oldPosition;
}
if (blBulletFiring) DrawBullet(shellModel, bulletMatrix, viewMatrix, projectionMatrix);
if(blTorpedoFiring) DrawTorpedo(shellModel, torpedoMatrix, viewMatrix, projectionMatrix);
DrawAircraft(aircraftModel, aircraftMatrix, viewMatrix, projectionMatrix);
DrawDisplay();
DrawExplosion();
base.Draw(gameTime);
}
private void DrawTerrain()
{
grassEffect.World = worldMatrix;
grassEffect.View = viewMatrix;
grassEffect.Projection = projectionMatrix;
foreach (EffectPass pass in grassEffect.CurrentTechnique.Passes)
{
pass.Apply();
GraphicsDevice.Indices = myIndexBuffer;
GraphicsDevice.SetVertexBuffer(myVertexBuffer);
GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList, vertices, 0, vertices.Length, indices, 0, indices.Length / 3);
}
}
private void DrawBullet(Model model, Matrix world, Matrix view, Matrix projection)
{
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.LightingEnabled = true;
effect.DirectionalLight0.DiffuseColor = new Vector3(0.9f, 0.0f, 0.0f);
effect.DirectionalLight0.Direction = new Vector3(0, 1, -1);
effect.World = world;
effect.View = view;
effect.Projection = projection;
}
mesh.Draw();
}
}
private void DrawTorpedo(Model model, Matrix world, Matrix view, Matrix projection)
{
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.LightingEnabled = true;
effect.DirectionalLight0.DiffuseColor = new Vector3(0.0f, 0.0f, 0.0f);
effect.DirectionalLight0.Direction = new Vector3(0, 1, -1);
effect.World = world;
effect.View = view;
effect.Projection = projection;
}
mesh.Draw();
}
}
private void DrawAircraft(Model model, Matrix world, Matrix view, Matrix projection)
{
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
// effect.EnableDefaultLighting();
effect.LightingEnabled = true; // Turn on the lighting subsystem.
effect.DirectionalLight0.DiffuseColor = new Vector3(0.2f, 0.2f, 0.2f);
effect.DirectionalLight0.Direction = new Vector3(0, 5, -10);
//effect.DirectionalLight0.SpecularColor = new Vector3(0, 1, 0); // with green highlights
//effect.AmbientLightColor = new Vector3(0.2f, 0.2f, 0.2f); // Add some overall ambient light.
//effect.EmissiveColor = new Vector3(1, 0, 0); // Sets some strange emmissive lighting. This just looks weird.
effect.World = world;
effect.View = view;
effect.Projection = projection;
}
mesh.Draw();
}
}
private void DrawDisplay()
{
spriteBatch.Begin();
spriteBatch.DrawString(font, "Position: " + aircraftPosition.ToString(), new Vector2(10, 10), Color.Black);
spriteBatch.DrawString(font, "Ground Height: " + nHeightData.ToString(), new Vector2(10, 25), Color.Black);
spriteBatch.DrawString(font, "Bullet Position: " + nBullets.ToString(), new Vector2(10, 40), Color.Black);
spriteBatch.DrawString(font, "Torpedo Position: " + nTorpedoes.ToString(), new Vector2(10, 55), Color.Black);
spriteBatch.End();
}
private void DrawExplosion()
{
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive);
for (int i = 0; i < particleList.Count; i++)
{
ParticleData particle = particleList[i];
spriteBatch.Draw(explosionTexture, particle.Position, null, particle.ModColor, i, new Vector2(256, 256), particle.Scaling, SpriteEffects.None, 1);
}
spriteBatch.End();
}
}
}
Instead of using a BasicEffect, use a DualTextureEffect. I've never used it before because I don't develop for hone but this is supposed to be a very good tutorial. http://blogs.msdn.com/b/shawnhar/archive/2010/08/04/dualtextureeffect.aspx>
I have an isometric tile engine written in XNA (Monogame). It can only draw tile map surface. But when I have bigger map (for example 50x50 tiles) then is very slow (about 15 FPS). When I have small map (for example 10x10 tiles) than framrate is perfect (60 FPS).
I'm trying to find way how to optimise my code but I have no idea how to do it.
This is my code:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using System;
namespace IsoEngine
{
public class Game1 : Game
{
GraphicsDeviceManager _graphics;
SpriteBatch _spriteBatch;
Texture2D Tile1;
Texture2D Tile2;
MouseState mouseState;
bool isMousePressed = false;
int[,] map = { {1, 1, 1, 1},
{1, 0, 0, 1},
{1, 0, 0, 1},
{1, 1, 1, 1} };
int tileWidth = 64;
int tileHeight = 32;
Vector2 scrollSpan = new Vector2(0, 0);
Vector2 mouseDragPos = new Vector2(0, 0);
public Game1()
{
_graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
base.IsMouseVisible = true;
base.Initialize();
}
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
Tile1 = Content.Load<Texture2D>("1");
Tile2 = Content.Load<Texture2D>("2");
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
mouseState = Mouse.GetState();
if (mouseState.LeftButton == ButtonState.Pressed && !isMousePressed)
{
isMousePressed = true;
mouseDragPos.X = mouseState.X;
mouseDragPos.Y = mouseState.Y;
}
if (mouseState.LeftButton == ButtonState.Pressed && isMousePressed)
{
if (mouseDragPos.X < mouseState.X)
{
scrollSpan.X += mouseState.X - mouseDragPos.X;
mouseDragPos.X = mouseState.X;
}
if (mouseDragPos.X > mouseState.X)
{
scrollSpan.X -= mouseDragPos.X - mouseState.X;
mouseDragPos.X = mouseState.X;
}
if (mouseDragPos.Y < mouseState.Y)
{
scrollSpan.Y += (mouseState.Y - mouseDragPos.Y) * 2;
mouseDragPos.Y = mouseState.Y;
}
if (mouseDragPos.Y > mouseState.Y)
{
scrollSpan.Y -= (mouseDragPos.Y - mouseState.Y) * 2;
mouseDragPos.Y = mouseState.Y;
}
}
if (mouseState.LeftButton == ButtonState.Released && isMousePressed)
isMousePressed = false;
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
_spriteBatch.Begin();
DrawMap();
_spriteBatch.End();
base.Draw(gameTime);
}
private void DrawMap()
{
for (int osaY = 0; osaY < map.GetLength(0); osaY++)
{
for (int osaX = 0; osaX < map.GetLength(1); osaX++)
{
int x = osaX * 32;
int y = osaY * 32;
Texture2D thisTile = Tile1;
if (map[osaY, osaX] == 0)
thisTile = Tile1;
if (map[osaY, osaX] == 1)
thisTile = Tile2;
PlaceTile(thisTile, CartToIso(new Vector2(x, y)), new Vector2(osaX, osaY));
}
}
}
public void PlaceTile(Texture2D tileImage, Vector2 tilePos, Vector2 tileCoords)
{
_spriteBatch.Draw(tileImage, new Vector2(tilePos.X - (tileWidth / 2), tilePos.Y - tileHeight), Color.White);
}
public Vector2 CartToIso(Vector2 cartCoords)
{
Vector2 isoCoords = new Vector2(0, 0);
isoCoords.X = (cartCoords.X + scrollSpan.X) - cartCoords.Y;
isoCoords.Y = (cartCoords.X + scrollSpan.Y + cartCoords.Y) / 2;
return isoCoords;
}
public Vector2 IsoToCart(Vector2 isoCoords)
{
Vector2 cartCoords = new Vector2(0, 0);
cartCoords.X = (2 * isoCoords.Y + isoCoords.X - scrollSpan.X - scrollSpan.Y) / 2;
cartCoords.Y = (2 * isoCoords.Y - isoCoords.X + scrollSpan.X - scrollSpan.Y) / 2;
return cartCoords;
}
}
}
I'd suggest you to take a look at an answer I wrote a while ago, it does draw only the only the visible part of a level, no matter how big the level is :
I'm not copying and pasting the answer here as I wrote it already, so go and have a look at it here :
https://gamedev.stackexchange.com/a/29930/16262
Generally, to increase performace avoid creating unessesary objects and dont do anything you dont have to. For example you create one useless local texture in DrawMap(), also for single call of method PlaceTile you create 3 new vectors, while you need one.etc. also note, these are only minor improvements.
Another ways of speeding up might be using buffers(not sure what is default for XNA)
But most importantly, parallelize wherever you can.
Before doing anything else, profile your code and see where the most time is being spent. Only then can you begin to optimize
When you click on the top most button it is suppose to draw a string to the screen, but it's no showing up. I moved mainMenu.UpdateButtons(); to the Draw method in Main.cs but the string is drawn then the background image is drawn again. Making it appear as the string appears for a split second and disappear. Why is it doing this?
Main.cs
using System;
using System.Collections.Generic;
using System.Linq;
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.Media;
using TestGame.Controls;
using TestGame.GameStates;
namespace TestGame
{
public class Main : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
InputHandler inputHandler;
public SpriteBatch spriteBatch;
public SpriteFont spriteFont;
MainMenu mainMenu;
Vector2 position;
public Main()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
inputHandler = new InputHandler();
mainMenu = new MainMenu(this);
graphics.PreferredBackBufferWidth = 1280;
graphics.PreferredBackBufferHeight = 720;
}
protected override void Initialize()
{
this.IsMouseVisible = true;
base.Initialize();
mainMenu.MenuInitialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
spriteFont = Content.Load<SpriteFont>(#"Fonts\MainFont");
mainMenu.MenuLoadContent();
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
inputHandler.Update();
if (inputHandler.currentKeyState.IsKeyDown(Keys.Escape))
this.Exit();
mainMenu.frameTime = gameTime.ElapsedGameTime.Milliseconds / 1000;
MouseState mouseState = Mouse.GetState();
mainMenu.mouseX = mouseState.X;
mainMenu.mouseY = mouseState.Y;
mainMenu.previouslyPressed = mainMenu.mousePressed;
mainMenu.mousePressed = mouseState.LeftButton == ButtonState.Pressed;
mainMenu.UpdateButtons();
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin();
mainMenu.MenuDraw();
spriteBatch.End();
base.Draw(gameTime);
}
}
}
MainMenu.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace TestGame.GameStates
{
public class MainMenu
{
enum buttonState { hover, up, released, down }
const int numberOfButtons = 4, newGameButtonIndex = 0, loadGameButtonIndex = 1, optionsButtonIndex = 2, quitButtonIndex = 3, buttonHeight = 48, buttonWidth = 80;
Color[] buttonColor = new Color[numberOfButtons];
Rectangle[] buttonRect = new Rectangle[numberOfButtons];
buttonState[] buttonSt = new buttonState[numberOfButtons];
Texture2D[] buttonTexture = new Texture2D[numberOfButtons];
double[] buttonTimer = new double[numberOfButtons];
public bool mousePressed, previouslyPressed = false;
public int mouseX, mouseY;
public double frameTime;
int buttonPadding;
Main main;
Texture2D backgroundImage;
Texture2D backgroundImageFade;
public MainMenu(Game game)
{
main = (Main)game;
}
public void MenuInitialize()
{
for (int i = 0; i < numberOfButtons; i++)
{
buttonSt[i] = buttonState.up;
buttonColor[i] = Color.White;
buttonTimer[i] = 0.0;
buttonRect[i] = new Rectangle(0, buttonPadding, buttonWidth, buttonHeight);
buttonPadding += buttonHeight;
}
}
public void MenuLoadContent()
{
backgroundImage = main.Content.Load<Texture2D>(#"Backgrounds\titlescreen");
backgroundImageFade = main.Content.Load<Texture2D>(#"Backgrounds\titlescreenfade");
buttonTexture[newGameButtonIndex] = main.Content.Load<Texture2D>(#"Sprites\desktop");
buttonTexture[loadGameButtonIndex] = main.Content.Load<Texture2D>(#"Sprites\desktop");
buttonTexture[optionsButtonIndex] = main.Content.Load<Texture2D>(#"Sprites\desktop");
buttonTexture[quitButtonIndex] = main.Content.Load<Texture2D>(#"Sprites\desktop");
}
public void MenuDraw()
{
main.spriteBatch.Draw(backgroundImage, new Vector2(0, 0), Color.White);
for (int i = 0; i < numberOfButtons; i++)
{
main.spriteBatch.Draw(buttonTexture[i], buttonRect[i], buttonColor[i]);
}
}
Boolean targetImageAlpha(Rectangle rect, Texture2D texture, int x, int y)
{
return targetImageAlpha(0, 0, texture, texture.Width * (x - rect.X) / rect.Width, texture.Height * (y - rect.Y) / rect.Height);
}
Boolean targetImageAlpha(float tx, float ty, Texture2D texture, int x, int y)
{
if (targetImage(tx, ty, texture, x, y))
{
uint[] data = new uint[texture.Width * texture.Height];
texture.GetData<uint>(data);
if ((x - (int)tx) + (y - (int)ty) * texture.Width < texture.Width * texture.Height)
{
return ((data[(x - (int)tx) + (y - (int)ty) * texture.Width] & 0xFF000000) >> 24) > 20;
}
}
return false;
}
Boolean targetImage(float tx, float ty, Texture2D texture, int x, int y)
{
return (x >= tx && x <= tx + texture.Width && y >= ty && y <= ty + texture.Height);
}
public void UpdateButtons()
{
for (int i = 0; i < numberOfButtons; i++)
{
if (targetImageAlpha(buttonRect[i], buttonTexture[i], mouseX, mouseY))
{
buttonTimer[i] = 0.0;
if (mousePressed)
{
buttonSt[i] = buttonState.down;
buttonColor[i] = Color.Blue;
}
else if (!mousePressed && previouslyPressed)
{
if (buttonSt[i] == buttonState.down)
{
buttonSt[i] = buttonState.released;
}
}
else
{
buttonSt[i] = buttonState.hover;
buttonColor[i] = Color.LightBlue;
}
}
else
{
buttonSt[i] = buttonState.up;
if (buttonTimer[i] > 0)
{
buttonTimer[i] = buttonTimer[i] - frameTime;
}
else
{
buttonColor[i] = Color.White;
}
}
if (buttonSt[i] == buttonState.released)
{
onButtonClick(i);
}
}
}
void onButtonClick(int i)
{
switch (i)
{
case newGameButtonIndex:
main.spriteBatch.Begin();
//main.spriteBatch.DrawString(main.spriteFont, "Creating new game", new Vector2(100, 200), Color.White);
main.spriteBatch.Draw(backgroundImageFade, new Vector2(0, 0), Color.White);
main.spriteBatch.End();
break;
default:
break;
}
}
}
}
It is being drawn, but then you proceed to erase it in your Draw method. That's the issue you'll get when you start to mix your drawing code in with your updating code.
So here's an example of what's happening in your game right now.
Update Main Game
Update Buttons
Draw Main Game
Draw Buttons
Then a click occurs and here's what happens.
Update Main Game
Update Buttons
onButtonClick -> this is where you draw your text
Draw Main Game -> the screen now clears and your draw your buttons
Draw Buttons
So it's all "working" just not how you really intended it. You're going to want to separate your drawing code so that you're drawing from Draw method calls. Basically check to see if the buttonState has become "released" in your Draw method and THEN draw the text you want.