I'm trying to encapsulate my game objects by having them extend Mircosoft.Xna.Framework.GameCompenent, then merely constructing them and managing them in the Update() method of Game1. I have my Game1 class, a Player class, and an Animation class. Animations are supposed manage the Texture2D changes of an object, in this instance Player.
My problem is that even though I have successfully extended everything, have no syntax errors, no exceptions thrown, and have checked and re-checked what little code I have written, the override functions are not called and I end up with a black screen.
Game1.cs: (note that the only two lines changed are for the Player declaration)
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Player player;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
player = new Player(this);
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// TODO: Add your update logic here
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
base.Draw(gameTime);
}
}
Player.cs:
class Player : Microsoft.Xna.Framework.DrawableGameComponent
{
Rectangle bounds;
Texture2D t;
Animation[] animations = new Animation[4];
String path = #"..\..\..\Content\player.png";
#region Animation Constants
private const int WALK_RIGHT = 0;
#endregion
SpriteBatch spriteBatch;
public Player(Game game) : base(game)
{
//should only ever be one player, all value defaults set in Initialize()
}
public Texture2D T
{
get { return t; }
}
public Rectangle Bounds
{
get { return bounds; }
}
public override void Initialize()
{
base.Initialize();
bounds = new Rectangle(0, 0,
System.Drawing.Image.FromFile(path).Width,
System.Drawing.Image.FromFile(path).Height
);
t = Game.Content.Load<Texture2D>("player");
animations[0] = new Animation(this.Game, "player", "walking", 3);
}
protected override void LoadContent()
{
base.LoadContent();
spriteBatch = new SpriteBatch(this.Game.GraphicsDevice);
}
public override void Update(GameTime gameTime)
{
base.Update(gameTime);
KeyboardState k = Keyboard.GetState();
if (k.IsKeyDown(Keys.Right)) //walk right
{
bounds.X += 3;
if (animations[WALK_RIGHT].Playing)
{
t = animations[WALK_RIGHT].getTexture();
}
else
{
animations[WALK_RIGHT].Play();
}
}
else if (animations[WALK_RIGHT].Playing)
animations[WALK_RIGHT].Stop();
}
public override void Draw(GameTime gameTime)
{
base.Draw(gameTime);
spriteBatch.Begin();
spriteBatch.Draw(t, bounds, Color.White);
spriteBatch.End();
}
}
Animation.cs:
class Animation : Microsoft.Xna.Framework.GameComponent
{
Game game;
String name; //name of default sprite; standing, unmoving, neutral, etc. The rest of the animation sprite names should derive from this
String keyword;
int frameCount;
int delay; //frames between texture change
String[] paths; //texture pathnames generated by the MakePaths() function
int currentFrame = 0;
int delayCount = 0;
bool playing = false;
public Animation(Game associatedGame, String nameVal, String keywordVal, int frameCountVal)
: base(associatedGame)
{
name = nameVal;
keyword = keywordVal;
frameCount = frameCountVal;
paths = MakePaths();
delay = 10;
}
public Animation(Game associatedGame, String nameVal, String keywordVal, int frameCountVal, int delayVal)
: base(associatedGame)
{
name = nameVal;
keyword = keywordVal;
frameCount = frameCountVal;
paths = MakePaths();
delay = delayVal;
}
private String[] MakePaths()
{
//format: name_keyword_anim[i]
//format example: player_walking_anim1
String[] temp = new String[frameCount];
for (int i = 0; i < frameCount; i++)
{
temp[i] = name + "_" + keyword + "_" + "anim" + i.ToString();
}
return temp;
}
public Texture2D getTexture()
{
return Game.Content.Load<Texture2D>(paths[currentFrame]);
}
public void Play()
{
playing = true;
}
public void Stop()
{
currentFrame = 0;
delayCount = 0;
playing = false;
}
public bool Playing
{
get { return playing; }
}
public override void Update(GameTime gameTime)
{
if (playing)
{
if (delayCount == delay)
{
delayCount = 0;
if ((currentFrame + 1) == frameCount) currentFrame = 0;
else currentFrame++;
}
else delayCount++;
}
base.Update(gameTime);
}
public override string ToString()
{
return "params: " + name + "," + keyword + "," + frameCount.ToString() + "\nUsing paths: " + paths;
}
}
The only LoadContent, Initialize, Update, and Draw methods that are called are the ones in Game1. What really baffles me is that I was able to use this technique before without issue. These functions would be called naturally by the Xna update process.
So... why is this?
You need to add game Components to the Components collection to have them called automatically
protected override void Initialize()
{
player = new Player(this);
Components.Add(player);
base.Initialize();
}
See http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.game.components.aspx
Related
I'm figuring out how XNA works and stuff, I was experimenting with a tile-based game. Now, when I register the tiles, I store them in a list, but when the class loader calls the list, it's empty.
The Tile Handler
public class Tile
{
public class TileType
{
public int ID;
public Texture2D Texture;
public Rectangle Rectangle;
}
private List<Handler.Tile.TileType> tiles = new List<Handler.Tile.TileType>();
public List<Handler.Tile.TileType> Tiles
{
get { return tiles; }
}
int TileNumber = 0;
Game1 game = new Game1();
public void LoadTile(int ID, SpriteBatch spriteBatch)
{
spriteBatch.Draw(tiles[ID].Texture, tiles[ID].Rectangle, Color.White);
}
public void AddTile(Texture2D texture, Rectangle rectangle, SpriteBatch spriteBatch)
{
tiles.Add(new TileType { ID = TileNumber, Texture = texture, Rectangle = rectangle });
TileNumber++;
Console.WriteLine("[Tile.cs] - Number of tiles in tiles: " + tiles.Count);
Console.WriteLine("[Tile.cs] - Added a tile, with ID of " + tiles[TileNumber-1].ID);
}
public void LoadMap(SpriteBatch spriteBatch)
{
foreach (TileType tile in tiles)
{
LoadTile(tile.ID, spriteBatch);
Console.WriteLine("Loaded Tile: " + tile.ID + "With Texture: " + tile.Texture);
}
}
}
This adds the Tiles:
class CreateMap
{
public void createMap(int size, SpriteBatch spriteBatch, List<Texture2D> texture)
{
Tile tile = new Tile();
Random rnd = new Random();
int air = 1;
switch(size)
{
case 1:
size = -64;
break;
case 2:
size = -128;
break;
case 3:
size = -256;
break;
default:
size = -64;
break;
}
for (int x = size; x <= (size * -1); x++)
for (int y = 0; y < 65; y++)
{
if (air <= 3)
{
tile.AddTile(texture[1], new Rectangle(x * 64, y * 64, 64, 64), spriteBatch);
air++;
}
else
{
switch (rnd.Next(0, 3))
{
case 1:
tile.AddTile(texture[1], new Rectangle(x * 64, y * 64, 64, 64), spriteBatch);
Console.WriteLine("Added Tile with texture of Dirt");
break;
case 2:
tile.AddTile(texture[0], new Rectangle(x * 64, y * 64, 64, 64), spriteBatch);
Console.WriteLine("Added Tile with texture of Sky");
break;
}
}
Console.WriteLine("[ CreateMap.cs ] - Tile Number: " + tile.Tiles.Count);
}
}
}
And the Game1.cs
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Handler.Tile tile;
Handler.CreateMap mapHandler;
Handler.TextureHandler textureHandler;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
tile = new Handler.Tile();
mapHandler = new Handler.CreateMap();
textureHandler = new Handler.TextureHandler();
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
textureHandler.LoadTextures(Content);
mapHandler.createMap(1, spriteBatch, textureHandler.Textures);
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
Console.WriteLine("[Game1.cs / Update ] - Tiles in Update: " + tile.Tiles.Count);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
tile.LoadMap(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
}
(Better) Explanation: When LoadMap() is called, the Console.WriteLine() returns 0, while the CreateMap return the correct number.
You need to return the Tile object you create in
class CreateMap
{
public Tile createMap(int size, SpriteBatch spriteBatch, List<Texture2D> texture)
{
Tile tile = new Tile();
// do the work
return tile;
}
}
This needs to be returned to Game1
public class Game1 : Microsoft.Xna.Framework.Game
{
// ...
protected override void Initialize()
{
mapHandler = new Handler.CreateMap();
tile = mapHandler.createMap();
textureHandler = new Handler.TextureHandler();
base.Initialize();
}
}
when i start to debug my code it loads fine but only the fade in happens when i press Z the Enter key does not cause the fade or the next menu with text "Title Screen"to appear i wonder if anyone could tell me where i went wrong ill upload the full code below.
p.s. there is no error message.
what should happen when the game starts "Splash screen"
should appear on the screen pressing enter fades out the screen to the Title screen saying "Title Screen", the splash screen loads and when Z is pressed the fade animation happens but the Enter key has 0 effect on the game.
namespace Platformer
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
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()
{
Screen_Manager.Instance.Initiaize();
Screen_Manager.Instance.Dimensions = new Vector2(800, 600);
graphics.PreferredBackBufferWidth = (int)Screen_Manager.Instance.Dimensions.X;
graphics.PreferredBackBufferHeight = (int)Screen_Manager.Instance.Dimensions.Y;
graphics.ApplyChanges();
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);
Screen_Manager.Instance.LoadContent(Content);
}
/// <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>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
Screen_Manager.Instance.Update(gameTime);
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)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
Screen_Manager.Instance.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
{
public class Game_Screen
{
protected ContentManager content;
public virtual void LoadContent(ContentManager Content)
{
content = new ContentManager(Content.ServiceProvider, "content");
}
public virtual void UnloadContent()
{
content.Unload();
}
public virtual void Update(GameTime gameTime)
{
}
public virtual void Draw(SpriteBatch spriteBatch)
{
}
}
}
{
public class Screen_Manager
{
#region variables
ContentManager content; // creating custom ContentManger
Game_Screen currentScreen; // screen being currently displayed
Game_Screen newScreen; // new screen taking effect
private static Screen_Manager instance; // Screen Manger instance
// Dictionary<string, Game_Screen> screens = new Dictionary<string, Game_Screen>(); // Game Screen storage
Stack<Game_Screen> screenStack = new Stack<Game_Screen>(); // screens Stack
Vector2 dimensions; // width&Height of Screens
bool transition;
Fade_Animation fade;
Texture2D fadeTexture;
#endregion
#region Properties
public static Screen_Manager Instance
{
get
{
if (instance == null)
instance = new Screen_Manager();
return instance;
}
}
public Vector2 Dimensions
{
get { return dimensions; }
set { dimensions = value; }
}
#endregion
#region Main Methods
public void AddScreen(Game_Screen screen)
{
transition = true;
newScreen = screen;
fade.IsActive = true;
fade.Alpha = 1.0f;
fade.ActivateValue = 1.0f;
}
public void Initiaize()
{
currentScreen = new Splash_Screen();
fade = new Fade_Animation();
}
public void LoadContent(ContentManager Content)
{
content = new ContentManager(Content.ServiceProvider, "Content");
currentScreen.LoadContent(Content);
fadeTexture = content.Load<Texture2D>("fade");
fade.LoadContent(content, fadeTexture, "", Vector2.Zero);
fade.Scale = dimensions.X;
}
public virtual void Update(GameTime gameTime)
{
if (!transition)
currentScreen.Update(gameTime);
else
Transition(gameTime);
}
public virtual void Draw(SpriteBatch spriteBatch)
{
currentScreen.Draw(spriteBatch);
if (transition)
fade.Draw(spriteBatch);
}
#endregion
#region Provate Methods
private void Transition(GameTime gameTime)
{
fade.Update(gameTime);
if(fade.Alpha == 1.0f && fade.Timer.TotalSeconds == 1.0f)
{
screenStack.Push(newScreen);
currentScreen.UnloadContent();
currentScreen = newScreen;
currentScreen.LoadContent(content);
}
else if (fade.Alpha == 0.0f)
{
transition =false;
fade.IsActive = false;
}
}
#endregion
}
}
{
public class Splash_Screen : Game_Screen
{
KeyboardState keystate;
SpriteFont font;
public override void LoadContent(ContentManager Content)
{
base.LoadContent(Content);
if (font == null)
font = content.Load<SpriteFont>("Font1");
}
public override void UnloadContent()
{
base.UnloadContent();
}
public override void Update(GameTime gameTime)
{
keystate = Keyboard.GetState();
if (keystate.IsKeyDown(Keys.Z))
Screen_Manager.Instance.AddScreen(new Title_Screen());
}
public override void Draw(SpriteBatch spriteBatch)
{
spriteBatch.DrawString(font, "SplashScreen",
new Vector2(100, 100), Color.Black);
}
}
}
{
public class Title_Screen : Game_Screen
{
KeyboardState keystate;
SpriteFont font;
public override void LoadContent(ContentManager Content)
{
base.LoadContent(Content);
if (font == null)
font = content.Load<SpriteFont>("Font1");
}
public override void UnloadContent()
{
base.UnloadContent();
}
public override void Update(GameTime gameTime)
{
keystate = Keyboard.GetState();
if (keystate.IsKeyDown(Keys.Enter))
Screen_Manager.Instance.AddScreen(new Splash_Screen());
}
public override void Draw(SpriteBatch spriteBatch)
{
spriteBatch.DrawString(font, "Title Screen",
new Vector2(100, 100), Color.Black);
}
}
}
{
public class Animation
{
protected Texture2D image;
protected string text;
protected SpriteFont font;
protected Color color;
protected Rectangle sourceRect;
protected float rotation, scale, axis, alpha;
protected Vector2 origin, position;
protected ContentManager content;
protected bool isActive;
public virtual float Alpha
{
get { return alpha; }
set { alpha = value; }
}
public bool IsActive
{
set { isActive = value; }
get { return isActive; }
}
public float Scale
{
set { scale = value; }
// get { return scale; }
}
public virtual void LoadContent(ContentManager Content, Texture2D image,
string text, Vector2 position)
{
content = new ContentManager(Content.ServiceProvider, "Content");
this.image = image;
this.text = text;
this.position = position;
if (text != string.Empty)
{
font = Content.Load<SpriteFont>("Font1");
color = new Color(114, 77, 225);
}
if (image != null)
sourceRect = new Rectangle(0, 0, image.Width, image.Height);
rotation = 0.0f;
axis = 0.0f;
scale = 1.0f;
alpha = 1.0f;
isActive = false;
}
public virtual void UnloadContent()
{
content.Unload();
text = string.Empty;
position = Vector2.Zero;
sourceRect = Rectangle.Empty;
image = null;
}
public virtual void Update(GameTime gameTime)
{
}
public virtual void Draw(SpriteBatch spriteBatch)
{
if (image != null)
{
origin = new Vector2(sourceRect.Width / 2,
sourceRect.Height / 2);
spriteBatch.Draw(image, position + origin, sourceRect,
Color.White * alpha, rotation, origin, scale,
SpriteEffects.None, 0.0f);
}
if (text != String.Empty)
{
origin = new Vector2(font.MeasureString(text).X / 2,
font.MeasureString(text).Y / 2);
spriteBatch.DrawString(font, text, position + origin,
color * alpha, rotation, origin, scale, SpriteEffects.None,
0.0f);
}
}
}
}
{
class Fade_Animation : Animation
{
bool increase;
float fadespeed;
TimeSpan defaultTime, timer;
bool startTimer;
float activatevalue;
bool stopUpdateing;
float defaultAlpha;
public TimeSpan Timer
{
get { return timer; }
set { defaultTime = value; timer = defaultTime; }
}
public float FadeSpeed
{
get { return fadespeed; }
set { fadespeed = value; }
}
public override float Alpha
{
get
{
return alpha;
}
set
{
alpha = value;
if (alpha == 1.0f)
increase = false;
else if (alpha == 0.0f)
increase = true;
}
}
public float ActivateValue
{
get { return activatevalue; }
set { activatevalue = value; }
}
public override void LoadContent(ContentManager Content,
Texture2D image, string text, Vector2 position)
{
base.LoadContent(Content, image, text, position);
increase = false;
fadespeed = 1.0f;
defaultTime = new TimeSpan(0, 0, 1);
timer = defaultTime;
activatevalue = 0.0f;
stopUpdateing = false;
defaultAlpha = alpha;
}
public override void Update(GameTime gameTime)
{
if (isActive)
{
if (!stopUpdateing)
{
if (!increase)
alpha -= fadespeed * (float)gameTime.ElapsedGameTime.TotalSeconds;
else
alpha += fadespeed * (float)gameTime.ElapsedGameTime.TotalSeconds;
if (alpha <= 0.0f)
alpha = 0.0f;
else if (alpha >= 1.0f)
alpha = 1.0f;
}
if (alpha == activatevalue)
{
stopUpdateing = true;
timer -= gameTime.ElapsedGameTime;
if (timer.TotalSeconds <= 0)
{
increase = !increase;
timer = defaultTime;
stopUpdateing = false;
}
}
}
else
{
alpha = defaultAlpha;
}
}
}
}
This is the first time I program a game, I want to creat a sound effect on each time I shot a missile, not playing the sound when the missile is on the screen, just right after the character shooted it. Here is the code. Please help me, I tried to do it the whole night :
class Player
{
Texture2D hero;
Vector2 hero_location;
KeyboardState hero_movement;
int missileREA;
public List<adw> missiles = new List<adw>();
ContentManager takeContent;
public void LoadContent(ContentManager Content)
{
hero = Content.Load<Texture2D>("F5S4");
hero_location = Vector2.Zero;
takeContent = Content;
}
public void ShootMissiles(GameTime gameTime)
{
adw missile = new adw();
missile.LoadContent(takeContent);
missile.missile_location = hero_location + new Vector2(hero.Width /2,-50);
missiles.Add(missile);
shot = missiles;
}
public void Update(GameTime gameTime)
{
hero_movement = Keyboard.GetState();
if (hero_movement.IsKeyDown(Keys.W))
{
hero_location.Y -= 5;
}
if (hero_movement.IsKeyDown(Keys.D))
{
hero_location.X += 5;
}
if (hero_movement.IsKeyDown(Keys.S))
{
hero_location.Y += 3;
}
if (hero_movement.IsKeyDown(Keys.A))
{
hero_location.X -= 5;
}
if (hero_movement.IsKeyDown(Keys.NumPad1))
{
missileREA += gameTime.ElapsedGameTime.Milliseconds;
if (missileREA > 200)
{
missileREA = 0;
ShootMissiles(gameTime);
}
}
foreach (adw missile in missiles)
{
missile.Update(gameTime);
}
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(hero, hero_location, Color.White);
foreach (adw missile in missiles)
{
missile.Draw(spriteBatch);
}
}
public IEnumerable<adw> ShootMissile { get; set; }
public List<adw> shot { get; set; }
}
This is my Game1.cs, where all of my contents are loaded and drawn to the screen under my control.
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Player player;
SoundEffect missile1;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
player = new Player();
graphics.PreferredBackBufferWidth = 1024;
graphics.PreferredBackBufferHeight = 680;
graphics.ApplyChanges();
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
missile1 = Content.Load<SoundEffect>("missile1");
player.LoadContent(Content);
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
foreach (adw missile in player.missiles)
{
missile1.Play();
}
player.Update(gameTime);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
player.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
And if this is not the place to ask things like this, just tell me. I will do as you advice.
protected override void Update(GameTime gameTime)
{
....
foreach (adw missile in player.missiles)
{
missile1.Play();
}
....
}
Every single frame / tick of your game (I assume this is 60 times a second) you are trying to play your sound for every bullet you currently store a reference to. Basically, you're playing a sound 60+ times a second.
Load your sound within your Player class, exactly in the same way you load your texture. Call Play() on it every time you create a new bullet with ShootMissiles(gameTime);
I have 3 classes:
- Game1 (main class)
- Entity (base entity class)
- Player (player class, extends Entity class)
I draw the player class, but after that I can't seem to change the position of the player object.
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
//Create a list with all the entities
List<Entity> entityList = new List<Entity>();
//Player
Player player;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
//Create player
Texture2D playertexture = Content.Load<Texture2D>("player/player");
Rectangle playerrectangle = new Rectangle(10, 10, playertexture.Width, playertexture.Height);
player = new Player(playertexture, playerrectangle);
entityList.Add(player);
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (Keyboard.GetState().IsKeyDown(Keys.Escape))
this.Exit();
//Update players and entities
player.Update(graphics.GraphicsDevice);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
//Draw player
player.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
}
class Entity
{
//Standard variables
int health;
int armor;
float speed;
float friction;
//Get graphic and bounding box
Texture2D texture;
Rectangle rectangle;
public Entity(Texture2D newTexture, Rectangle newRectangle){
texture = newTexture;
rectangle = newRectangle;
}
public void Update(GraphicsDevice graphics) {
}
public void Draw(SpriteBatch spriteBatch) {
}
/*
* Modifiers for the variables
*/
public void modifyHealth(int amount) { health = health + amount; }
public void modifyArmor(int amount){ armor = armor + amount; }
public void modifySpeed(float amount) { speed = speed + amount; }
/*
* Getters for variables
*/
public int getHealth() { return health; }
public int getArmor() { return armor; }
public float getSpeed() { return speed; }
public float getFriction() { return friction; }
/*
* Setters for variables
*/
public void setHealth(int amount) { health = amount; }
public void setArmor(int amount) { armor = amount; }
public void setSpeed(float amount) { speed = amount; }
public void setFriction(float amount) { friction = amount; }
/*
* Functions
*/
public void damage(int damage) {
/*
* Calculate health
*
* Armor takes half the damage, if possible
*/
if (damage / 2 >= armor) {
damage = damage / 2;
armor -= damage;
} else if (armor > 0) {
damage -= armor;
armor = 0;
}
health -= damage;
if(health <= 0){
health = 0;
//TODO Death
}
}
}
class Player : Entity
{
//Create player
Entity player;
//Position and velocity
Vector2 position;
Vector2 velocity;
//Texture and rectangle
Texture2D texture;
Rectangle rectangle;
public Player(Texture2D newtexture, Rectangle newrectangle) : base(newtexture, newrectangle) {
texture = newtexture;
rectangle = newrectangle;
//Set basic variables
this.setHealth(100);
this.setArmor(0);
this.setSpeed(10);
this.setFriction(1);
}
public void Update() {
//Movement
if(Keyboard.GetState().IsKeyDown(Keys.Right)){
rectangle.X += 1;
}
rectangle.Y += 4;
}
public void Draw(SpriteBatch spriteBatch) {
spriteBatch.Draw(texture, rectangle, Color.White);
}
}
If there are also general mistakes I make, do point them out, I want to make everything as good as I can now that I'm still learning. Thanks in advance!
Your calling public void Update(GraphicsDevice graphics)
but the movement code is in public void Update()
What I suggest you do is this, use the virtual and override keywords.
In your entity class it should look like this:
public virtual void Update(GraphicsDevice graphics) {
}
And in your player class
public override void Update(GraphicsDevice graphics) {
//ADD MOVEMENT CODE HERE
}
I was just messing around with XNA and trying to get a simple player class that could move around through keyboard controls. I can't seem to get it to draw the way I have it set up now though. I'm not seeing what error I'm making.
Here's the Actor base class:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace RunnerTEst
{
class Actor
{
public static List<Actor> actors;
public Texture2D texture;
protected Vector2 position;
protected float rotation;
protected float scale;
protected Color color;
#region Constructors
static Actor()
{
actors = new List<Actor>();
}
public Actor(Texture2D texture)
{
actors.Add(this);
this.texture = texture;
this.position = Vector2.Zero;
this.rotation = 0f;
this.scale = 1f;
}
#endregion
#region Properties
public Vector2 Position
{
get { return this.position; }
set { this.position = value; }
}
public Vector2 Origin
{
get { return new Vector2(this.position.X + this.texture.Width / 2,
this.position.Y + this.texture.Height / 2); }
}
public float Rotation
{
get { return this.rotation; }
set { this.rotation = value; }
}
public float Scale
{
get { return this.scale; }
set { this.scale = value; }
}
public Color Color
{
get { return this.color; }
set { this.color = value; }
}
public float Width
{
get { return this.texture.Width; }
}
public float Height
{
get { return this.texture.Height; }
}
#endregion
#region Methods
public virtual void Update(GameTime gameTime)
{
}
public virtual void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(this.texture, this.position, this.color);
}
#endregion
}
}
Player class:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace RunnerTEst
{
class Player : Actor
{
private const float speed = 5f;
protected Vector2 velocity;
private static KeyboardState currState, prevState;
static Player()
{
currState = prevState = Keyboard.GetState();
}
public Player(Texture2D texture, Vector2 position)
: base(texture)
{
this.position = position;
this.velocity = Vector2.Zero;
}
public override void Update(GameTime gameTime)
{
this.HandleInput();
this.position += this.velocity;
foreach (Actor actor in Actor.actors)
{
if (this == actor)
continue;
this.CheckCollision(actor);
}
base.Update(gameTime);
}
public override void Draw(SpriteBatch spriteBatch)
{
base.Draw(spriteBatch);
}
public void CheckCollision(Actor actor)
{
//--left/right sides
if (this.position.X + this.Width > actor.Position.X) //right of this hitting left actor
{
this.position.X = actor.Position.X - this.Width;
}
else if (this.position.X < (actor.Position.X + actor.Width))//left this hit right actor
{
this.position.X = actor.Position.X + actor.Width;
}
//--top/bottom
if (this.position.Y + this.Height > actor.Position.Y) //this bottom hit actor top
{
this.position.Y = actor.Position.Y - this.Width;
}
else if (this.position.Y < (actor.Position.Y + actor.Height))//this top hit actor bottom
{
this.position.Y = actor.Position.Y + actor.Height;
}
//TODO: check screen bounds
}
public void HandleInput()
{
currState = Keyboard.GetState();
if (currState.IsKeyDown(Keys.W))
{
this.velocity.Y = -speed;
}
else if (currState.IsKeyDown(Keys.S))
{
this.velocity.Y = speed;
}
else
{
this.velocity.Y = 0f;
}
if (currState.IsKeyDown(Keys.A))
{
this.velocity.X = -speed;
}
else if (currState.IsKeyDown(Keys.D))
{
this.velocity.X = speed;
}
else
{
this.velocity.X = 0f;
}
prevState = currState;
}
}
}
and lastly, the game:
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;
namespace RunnerTEst
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D playerTexture;
Player me;
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);
playerTexture = Content.Load<Texture2D>(#"Textures\player");
me = new Player(playerTexture, new Vector2(200, 200));
}
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();
me.Update(gameTime);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
me.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
Thanks in advance for your time!
I looked through it, and it looks like you never define the Actor's color property. This means that the color variable defaults to black, which means that the tint given to the Draw line (spriteBatch.Draw(this.texture, this.position, this.color);) is Black, which hides the sprite.
Just set the color of the Actor to white somewhere (I just set it underneath me = new Player(playerTexture, new Vector2(200, 200));).
So the new LoadContent would look like:
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
playerTexture = Content.Load<Texture2D>(#"Textures\player");
me = new Player(playerTexture, new Vector2(200, 200));
me.Color = Color.White;
}
Hope that helps,
max