C# XML Error: System.InvalidOperationException - c#

I'm getting weird error when serializing this XML:
<?xml version="1.0" encoding="utf-8" ?>
<SplashScreen>
<Image>
<Path>Content/splash</Path>
</Image>
</SplashScreen>
Error:
"A first chance exception of type 'System.InvalidOperationException'
occurred in System.Xml.dll Additional information: Reflecting on the
type of error occurred EasyRPG.SplashScreen. If there is a handler for
this exception, the program may be safely continued."
XMLManager class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
namespace EasyRPG.Managers {
public class XmlManager<T> {
public Type Type;
public T Load (String path) {
T instance;
using (TextReader reader = new StreamReader(path)){
XmlSerializer xml = new XmlSerializer(Type);
instance = (T)xml.Deserialize(reader);
}
return instance;
}
public void Save (string path, object obj) {
using (TextWriter writer = new StreamWriter(path)) {
XmlSerializer xml = new XmlSerializer(Type);
xml.Serialize(writer, obj);
}
}
}
}
I am lost, I tried everything I know(that's not much though) and still nothing.
Image class if needed:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using EasyRPG;
namespace TEAM_TheCity.Source {
public class Image {
public float Alpha;
public string Path;
public string Text, FontName;
public Vector2 Position;
public Vector2 Scale;
public Rectangle SourceRect;
public SpriteFont font;
public GraphicsDevice GraphcsDevice;
public Texture2D Texture;
Vector2 origin;
ContentManager content;
RenderTarget2D renderTarget;
public SpriteBatch SpriteBatch;
public Image () {
Path = Text = String.Empty;
FontName = "Orbitron";
Position = Vector2.Zero;
Scale = Vector2.One;
Alpha = 1.0F;
SourceRect = Rectangle.Empty;
}
public void LoadContent(){
content = new ContentManager(ScreenManager.Manager.Content.ServiceProvider, "Content");
if(Path != String.Empty) Texture = content.Load<Texture2D>(Path);
font = content.Load<SpriteFont>(FontName);
Vector2 dimensions = Vector2.Zero;
if(Texture != null)
dimensions.X += Texture.Width;
dimensions.X += font.MeasureString(Text).X;
if(Texture != null)
dimensions.Y = Math.Max(Texture.Height, font.MeasureString(Text).Y);
else
dimensions.Y = font.MeasureString(Text).Y;
if(SourceRect == Rectangle.Empty)
SourceRect = new Rectangle(0,0, (int)dimensions.X, (int)dimensions.Y);
renderTarget = new RenderTarget2D(ScreenManager.Manager.GraphicsDevice,(int) dimensions.X, (int)dimensions.Y);
ScreenManager.Manager.GraphicsDevice.SetRenderTarget(renderTarget);
ScreenManager.Manager.GraphicsDevice.Clear(Color.Transparent);
ScreenManager.Manager.SpriteBatch.Begin();
if (Texture != null)
ScreenManager.Manager.SpriteBatch.Draw(Texture, Vector2.Zero, Color.White);
ScreenManager.Manager.SpriteBatch.DrawString(font, Text, Vector2.Zero, Color.White);
ScreenManager.Manager.SpriteBatch.End();
Texture = renderTarget;
ScreenManager.Manager.GraphicsDevice.SetRenderTarget(null);
}
public void UnloadContent(){
}
public void Update(GameTime gameTime){
}
public void Draw(SpriteBatch SpriteBatch) {
origin = new Vector2(SourceRect.Width / 2, SourceRect.Height / 2);
SpriteBatch.Draw(Texture, Position + origin, SourceRect, Color.White, 0.0f, origin, Scale, SpriteEffects.None, 0.0f);
}
}
}
And SplashScreen class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using TEAM_TheCity.Source;
namespace EasyRPG {
public class SplashScreen : GameScreen{
public Image Image;
public SplashScreen () {
}
public override void LoadContent () {
base.LoadContent();
Image.LoadContent();
}
public override void UnloadContent () {
base.LoadContent();
Image.UnloadContent();
}
public override void Update (GameTime gameTime) {
base.Update(gameTime);
Image.Update(gameTime);
}
public override void Draw (SpriteBatch spriteBatch) {
base.Draw(spriteBatch);
Image.Draw(spriteBatch);
}
}
}
GameScreen class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
namespace EasyRPG {
public class GameScreen {
protected ContentManager content;
[XmlIgnore]
public Type Type;
public GameScreen () {
Type = this.GetType();
}
public virtual void LoadContent () {
content = new ContentManager(ScreenManager.Manager.Content.ServiceProvider, "Content");
}
public virtual void UnloadContent () {
content.Unload();
}
public virtual void Update (GameTime gameTime) {}
public virtual void Draw (SpriteBatch spriteBatch) {}
}
}
P.S.: sorry for that much code but I am new in XML and I have no idea what is important and what is not

This code will work.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
SplashScreen splashScreen = new SplashScreen()
{
image = new Image()
{
Path = "Content/splash"
}
};
XmlSerializer serializer = new XmlSerializer(typeof(SplashScreen));
StreamWriter writer = new StreamWriter(FILENAME);
serializer.Serialize(writer, splashScreen);
writer.Flush();
writer.Close();
writer.Dispose();
XmlSerializer xs = new XmlSerializer(typeof(SplashScreen));
XmlTextReader reader = new XmlTextReader(FILENAME);
SplashScreen newSplashScreen = (SplashScreen)xs.Deserialize(reader);
}
}
[XmlRoot("SplashScreen")]
public class SplashScreen
{
[XmlElement("Image")]
public Image image {get; set; }
}
[XmlRoot("Image")]
public class Image
{
[XmlElement("Path")]
public string Path {get; set;}
}
}
​

Here is an answer that won't change your code too much because I recognize it from a youtube tutorial and changing it too much might make it hard to follow the tutorial. You need to use [XmlIgnore] if you do not include the public variables in the Xml file. So you can either change your XMl file or add [XmlIgnore] to the image.cs Because this is from a tutorial I recommend the later, just remember to remove the added [XmlIgnore] if/when you want to add the variables to the xml file.
Best Option: Edit the Image.cs
[XmlIgnore] public float Alpha;
public string Path;
[XmlIgnore] public string Text, FontName;
[XmlIgnore] public Vector2 Position;
[XmlIgnore] public Vector2 Scale;
[XmlIgnore] public Rectangle SourceRect;
[XmlIgnore] public SpriteFont font;
[XmlIgnore] public GraphicsDevice GraphcsDevice;
[XmlIgnore] public Texture2D Texture;
Vector2 origin;
ContentManager content;
RenderTarget2D renderTarget;
[XmlIgnore] public SpriteBatch SpriteBatch;
Other Option: Edit the XML
Basically initialize all public values in XML file. (Note I left some vars out, you get the idea though)
<?xml version="1.0" encoding="utf-8" ?>
<SplashScreen>
<Image>
<Alpha>0.5</Alpha>
<Path>Content/splash</Path>
<Text>Put Text Here</Text>
<FontName>Fonts/Orbitron</FontName>
<Scale>
<X>1.0</X>
<Y>1.0</Y>
</Scale>
<Position>
<X>0</X>
<Y>0</Y>
</Position>
<SourceRect>Rectangle.Empty</SourceRect>
</Image>
</SplashScreen>
Side Note
I believe that you do not need "public GraphicsDevice GraphicsDevice;" and "public SpriteBatch SpriteBatch;" in Image.cs, instead they should be in ScreenManager.cs
Also I think that "public SpriteFont font;" should not be public.

Related

How can I add the locksystem state to my SaveState class?

The Lock System script :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LockSystem : MonoBehaviour
{
public bool mouseCursorLockState = true;
public PlayerCameraController playerCameraController;
public PlayerController playerController;
// Start is called before the first frame update
void Start()
{
MouseCursorLockState(mouseCursorLockState);
}
public void MouseCursorLockState(bool lockState)
{
if (lockState == false)
{
Cursor.visible = true;
Cursor.lockState = CursorLockMode.None;
}
else
{
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
}
}
public void PlayerLockState(bool LockPlayer, bool LockPlayerCamera)
{
if (LockPlayer == true)
{
playerController.enabled = false;
}
else
{
playerController.enabled = true;
}
if (LockPlayerCamera == true)
{
playerCameraController.enabled = false;
}
else
{
playerCameraController.enabled = true;
}
}
}
I'm using it in some places in my game for example :
public LockSystem playerLockMode;
playerLockMode.PlayerLockState(true, false);
The playerLockMode is at the top and the using it in some function it's just exmaple of how I'm using it.
The Save State class. So far I can save any object position rotation scaling. Now I want to save also the locking system state :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
[Serializable]
public class SaveState
{
[Serializable]
public struct SerializableVector3
{
public float X;
public float Y;
public float Z;
public SerializableVector3(Vector3 v)
{
X = v.x;
Y = v.y;
Z = v.z;
}
// And now some magic
public static implicit operator SerializableVector3(Vector3 v)
{
return new SerializableVector3(v);
}
public static implicit operator Vector3(SerializableVector3 sv)
{
return new Vector3(sv.X, sv.Y, sv.Z);
}
}
[Serializable]
public struct SerializableQuaternion
{
public float X;
public float Y;
public float Z;
public float W;
public SerializableQuaternion(Quaternion q)
{
X = q.x;
Y = q.y;
Z = q.z;
W = q.w;
}
public static implicit operator SerializableQuaternion(Quaternion q)
{
return new SerializableQuaternion(q);
}
public static implicit operator Quaternion(SerializableQuaternion sq)
{
return new Quaternion(sq.X, sq.Y, sq.Z, sq.W);
}
}
public SerializableVector3 position;
public SerializableQuaternion rotation;
public SerializableVector3 scale;
public SaveState(Vector3 pos, Quaternion rot, Vector3 sca)
{
position = pos;
rotation = rot;
scale = sca;
}
public void ApplyToPlayer(Transform player)
{
player.localPosition = position;
player.localRotation = rotation;
player.localScale = scale;
}
public bool LockState(bool lockState)
{
return lockState;
}
}
I tried to add in the bottom the new function LockState but that's not the right way to handle it.
The save manager script :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.Serialization.Formatters.Binary;
using System;
using System.IO;
public class SaveManager : MonoBehaviour
{
public static void Save(SaveState player)
{
BinaryFormatter formatter = new BinaryFormatter();
string path = Application.persistentDataPath + "/player.bin";
FileStream stream = new FileStream(path, FileMode.Create);
formatter.Serialize(stream, player);
stream.Close();
}
public static SaveState Load()
{
string path = Application.persistentDataPath + "/player.bin";
if (File.Exists(path))
{
BinaryFormatter formatter = new BinaryFormatter();
FileStream stream = new FileStream(path, FileMode.Open);
SaveState data = formatter.Deserialize(stream) as SaveState;
stream.Close();
return data;
}
else
{
Debug.LogError("Save file not found in " + path);
return null;
}
}
}
The Player State script for saving the player state but I can also save here the lock system state just not sure yet how :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerState : MonoBehaviour
{
private void Awake()
{
Save();
}
public void Save()
{
SaveState saveState = new SaveState(transform.localPosition,
transform.localRotation, transform.localScale);
SaveManager.Save(saveState);
}
public void Load()
{
var playerInfo = SaveManager.Load();
playerInfo.ApplyToPlayer(transform);
}
}
Once the game start I'm saving in the Awake once.
Then calling the Load function to my Main Menu ui button :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class MainMenu : MonoBehaviour
{
public void StartNewGame()
{
ScenesManager.StartNewGame();
}
public void LoadGame()
{
var playerstate = GameObject.Find("Player").GetComponent<PlayerState>();
playerstate.Load();
}
public void ResumeGame()
{
ScenesManager.ResumeGame();
}
public void QuitGame()
{
Application.Quit();
}
}
My idea is to save one the game start and then using a timer and save each 5 minutes for example.
So I'm calling only the Load function in the Main Menu. The save will be automatic during the game.
In the SaveState class I want to add more and more stuff to save it's state like the locking system and also a coroutine state. The game start with a running coroutine that make some effect. I want also to save the coroutine state if the game save at the start or a bit later while the coroutine is running so save the current coroutine state too.
This is when the game start :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.PostProcessing;
public class DepthOfField : MonoBehaviour
{
public UnityEngine.GameObject player;
public PostProcessingProfile postProcessingProfile;
public bool dephOfFieldFinished = false;
public LockSystem playerLockMode;
private Animator playerAnimator;
private float clipLength;
private Coroutine depthOfFieldRoutineRef;
// Start is called before the first frame update
void Start()
{
if (depthOfFieldRoutineRef != null)
{
StopCoroutine(depthOfFieldRoutineRef);
}
playerAnimator = player.GetComponent<Animator>();
AnimationClip[] clips = playerAnimator.runtimeAnimatorController.animationClips;
foreach (AnimationClip clip in clips)
{
clipLength = clip.length;
}
DepthOfFieldInit(clipLength);
// Don't forget to set depthOfFieldRoutineRef to null again at the end of routine!
}
public void DepthOfFieldInit(float duration)
{
var depthOfField = postProcessingProfile.depthOfField.settings;
depthOfField.focalLength = 300;
StartCoroutine(changeValueOverTime(depthOfField.focalLength, 1, duration));
postProcessingProfile.depthOfField.settings = depthOfField;
}
public IEnumerator changeValueOverTime(float fromVal, float toVal, float duration)
{
playerLockMode.PlayerLockState(true, true);
float counter = 0f;
while (counter < duration)
{
var dof = postProcessingProfile.depthOfField.settings;
counter += Time.deltaTime;
float val = Mathf.Lerp(fromVal, toVal, counter / duration);
dof.focalLength = val;
postProcessingProfile.depthOfField.settings = dof;
yield return null;
}
playerAnimator.enabled = false;
dephOfFieldFinished = true;
depthOfFieldRoutineRef = null;
}
}
This is a screenshot of the game start and the effect while the coroutine is running :
This blur effect is made by the PostProcessing and the coroutine.
I want also to save the state if that.
Saving objects info is easy like position rotation and scaling but how can I save the state of other stuff like the locking system and the DepthOfField ? How should I extend the SaveState class and then how to use it to save it in the PlayerState script ?

My LoadContent Function does not load my sprites(Building a Pacman Game)

Alright so Im following a tutorial on youtube about creating a Pacman game using XNA here is the link https://www.youtube.com/watch?v=TN3NYT_glmg. I have watched up to 3 tutorials and have encountered a problem.
I follow exactly what the guy does but there is a problem, my sprites dont draw in my screen, I back traced the tutorial trying to figure out what I was missing but, I cant find anything that I missed.
Id be grateful for your help, I need to complete this game in order to understand how game programming actually works.
Here is the code
Object Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
namespace WindowsGame1
{
class Obj
{
public Texture2D Texture = null; //texture of object;
public string TextureName = string.Empty;//name of texture
public Vector2 center = Vector2.Zero;//Center of texture
public Vector2 position = Vector2.Zero;//Postion of object
public float Rotation = 0.0f; //Rotation of Object
public float scale = 1.0f; //Scale of the object
public float speed = 0.0f; //speed of the object
public bool isAlive = true;
public Obj(Vector2 pos)
{
position = pos;
}
public Obj()
{
}
public virtual void LoadContent(ContentManager Content)//Loads Content
{
Texture = Content.Load<Texture2D>("Sprites/"+this.TextureName);
center = new Vector2(Texture.Width / 2, Texture.Height / 2);
}
public virtual void Update(GameTime gameTime)//Updates the gametime
{
}
public virtual void Draw(SpriteBatch spriteBatch)//Draws object/sprites
{
if (isAlive)
return;
spriteBatch.Draw(Texture, position, null, Color.White, MathHelper.ToRadians(Rotation), center, scale,SpriteEffects.None, 0);
}
}
}
Items Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
namespace WindowsGame1
{
class Items
{
public static List<Obj> Objlist = new List<Obj>();//Create list of objects
public static Pacman Pacman;
public static void Initialize()
{
Objlist.Add(Pacman=new Pacman(new Vector2(250,250), "Pacman1"));
}
}
}
Pacman Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
namespace WindowsGame1
{
class Pacman:Obj
{
public Pacman(Vector2 pos, string textureName)
{
TextureName = textureName;
position = pos;
isAlive = true;
}
}
}
And Finally
Game Class
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 WindowsGame1
{
/// <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()
{
Items.Initialize();
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()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
foreach (Obj o in Items.Objlist)
{
o.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)
{
foreach (Obj o in Items.Objlist)
{
o.Update(gameTime);//updates all ojects
}
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)//Used to draw the game
{
GraphicsDevice.Clear(Color.SkyBlue);//This line here is used to change the color of the screen
spriteBatch.Begin();
foreach (Obj o in Items.Objlist)
{
o.Draw(spriteBatch);
}
spriteBatch.End();
base.Draw(gameTime);
}
}
}
Look at your Draw code:
public virtual void Draw(SpriteBatch spriteBatch)//Draws object/sprites
{
if (isAlive)
return;
spriteBatch.Draw(Texture, position, null, Color.White, MathHelper.ToRadians(Rotation), center, scale,SpriteEffects.None, 0);
}
If the object is alive you don't draw it....
It should be:
public virtual void Draw(SpriteBatch spriteBatch)//Draws object/sprites
{
if (!isAlive)
return;
spriteBatch.Draw(Texture, position, null, Color.White, MathHelper.ToRadians(Rotation), center, scale,SpriteEffects.None, 0);
}

C# XNA - randomly draw a texture on the top X axis

So I'm making a space invaders game. I want to have meteors spawning from different/random locations on the entire 0 coordinate of X. How should I ahieve this? I've seen people using Lists and Random()s but I need a code for my meteorGenerator class. Then I'll call it's methods in Game1
When the meteors are drawn they should fall down at the bottom of the screen and disappear.
I saw an answer here on SO and implemented it to my class:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Storage;
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 Microsoft.Xna.Framework.Net;
namespace SpaceInvaders
{
class meteorGenerator
{
public static Vector2 m_Pos;
public Vector2 m_Position
{
get { return m_Pos; }
set { m_Pos = value; }
}
Texture2D m_Texture { get; set; }
Texture2D m_MeteorsTex;
public meteorGenerator(Texture2D m_Tex, Vector2 m_Pos)
{
m_Position = m_Pos;
m_Texture = m_Tex;
}
List<meteorGenerator> m_MeteorsList = new List<meteorGenerator>();
static readonly Random rnd = new Random();
public void LoadContent(ContentManager Content)
{
m_MeteorsTex = Content.Load<Texture2D>(".\\gameGraphics\\gameSprites\\thePlan\\meteorSpawn");
}
public void Update(GameTime gameTime)
{
if (m_MeteorsList.Count() < 4)
{
m_MeteorsList.Add(new meteorGenerator(m_MeteorsTex, new Vector2(rnd.Next(30, 610), rnd.Next(30, 450))));
}
}
public void Draw(SpriteBatch spriteBatch)
{
foreach (meteorGenerator m_Meteor in m_MeteorsList)
{
spriteBatch.Draw(m_Meteor.m_Texture, m_Meteor.m_Position, Color.White);
}
}
}
}
But when I try to instance the constructor of the class in Game1 I get an error:
meteorGenerator m_MeteorGenerator;
protected override void Initialize()
{
// TODO: Add your initialization logic here.
m_MeteorGenerator = new meteorGenerator(meteorGenerator.m_Tex, meteorGenerator.m_Pos);
}
Error 1 'SpaceInvaders.meteorGenerator' does not contain a definition for 'm_Tex'
I think this will do the trick.
I renamed the parameters for the constructor to vTexture and vPos but I agree with the comments this is old style coding and very confusing. Now we would use
public Vector2 position
public Vector2 Position
{
get { return position }
set { position = value; }
}
public meteorGenerator(Texture2D texture, Vector2 position)
{
Position = texture;
Texture = position;
}
But that is splitting hairs for now.
What I did change is m_MeteorsList, LoadContent, Update and Draw are now static.
you can just call
meteorGenerator.Loadcontent(Content) // to load your content
meteorGenerator.Update(gameTime) // will generate the meteors
meteorGenerator.Draw(spriteBatch) // will draw them.
No need to have multiple instances of the meteorGenerator class.
I honestly don't think this good practice as I would have used a separate Meteor class or struct to store information about meteors.
namespace SpaceInvaders
{
class meteorGenerator
{
public Vector2 m_Pos;
public Vector2 m_Position
{
get { return m_Pos; }
set { m_Pos = value; }
}
Texture2D m_Texture { get; set; }
Texture2D m_MeteorsTex;
public meteorGenerator(Texture2D vTex, Vector2 vPos)
{
m_Position = vPos;
m_Texture = vTex;
}
static List<meteorGenerator> m_MeteorsList = new List<meteorGenerator>();
static readonly Random rnd = new Random();
public static void LoadContent(ContentManager Content)
{
m_MeteorsTex = Content.Load<Texture2D>(".\\gameGraphics\\gameSprites\\thePlan\\meteorSpawn");
}
public static void Update(GameTime gameTime)
{
if (m_MeteorsList.Count() < 4)
{
m_MeteorsList.Add(new meteorGenerator(m_MeteorsTex, new Vector2(rnd.Next(30, 610), rnd.Next(30, 450))));
}
}
public static void Draw(SpriteBatch spriteBatch)
{
foreach (meteorGenerator m_Meteor in m_MeteorsList)
{
spriteBatch.Draw(m_Meteor.m_Texture, m_Meteor.m_Position, Color.White);
}
}
}
}

Error creating a hitbox?

So I have a HealthPickup class and a Player class. Each class has this line of code:
public static Rectangle Hitbox = new Rectangle(Pos.X, Pos.Y, Tex.Width, Tex.Height);
My question is, why is there an error on the Player class and not the HealthPickup class? Edit: If i step over the Player hitbox, the HealthPickup causes the same error.Is it something to do with my Rectangle? The error is a TypeInitializationException which details follow as such:
System.TypeInitializationException was unhandled
HResult=-2146233036
Message=The type initializer for 'TestGame.Player' threw an exception.
Source=TestGame
TypeName=TestGame.Player
StackTrace:
at TestGame.RPG.LoadContent() in C:\Users\Pyroglyph\Documents\Visual Studio 2010\Projects\TestGame\TestGame\TestGame\RPG.cs:line 41
at Microsoft.Xna.Framework.Game.Initialize()
at TestGame.RPG.Initialize() in C:\Users\Pyroglyph\Documents\Visual Studio 2010\Projects\TestGame\TestGame\TestGame\RPG.cs:line 33
at Microsoft.Xna.Framework.Game.RunGame(Boolean useBlockingRun)
at Microsoft.Xna.Framework.Game.Run()
at TestGame.Program.Main(String[] args) in C:\Users\Pyroglyph\Documents\Visual Studio 2010\Projects\TestGame\TestGame\TestGame\Program.cs:line 15
InnerException: System.NullReferenceException
HResult=-2147467261
Message=Object reference not set to an instance of an object.
Source=TestGame
StackTrace:
at TestGame.Player..cctor() in C:\Users\Pyroglyph\Documents\Visual Studio 2010\Projects\TestGame\TestGame\TestGame\Player.cs:line 20
InnerException:
Edit: I stopped the error but I still need collision-detection, I'm using Console.Beep() to determine whether code runs or not. And, as per request, more code :)
public class HealthPickup : Microsoft.Xna.Framework.GameComponent
{
public static Texture2D Tex;
public static Point Pos = new Point(50, 50);
public static Rectangle Hitbox = new Rectangle(Pos.X, Pos.Y, 32, 32);
public HealthPickup(Game game) : base(game) { }
public override void Initialize() { base.Initialize(); }
public override void Update(GameTime gameTime)
{
//if (Tex.Bounds.Intersects(Player.Tex.Bounds)) //was testing other collision-detection methods
//{
// Console.Beep(); //the only way I can check if it's being run or not
//}
}
}
In Draw():
GraphicsDevice.Clear(Color.White);
spriteBatch.Begin();
// Create Useless Rectangles
Rectangle player = new Rectangle(Player.Pos.X, Player.Pos.Y, Player.Tex.Width, Player.Tex.Height);
Rectangle healthPickup = new Rectangle(HealthPickup.Pos.X, HealthPickup.Pos.Y, HealthPickup.Tex.Width, HealthPickup.Tex.Height);
// Draw Sprites
spriteBatch.Draw(Player.Tex, player, Color.White);
spriteBatch.Draw(HealthPickup.Tex, healthPickup, Color.White);
spriteBatch.End();
base.Draw(gameTime);
Player class:
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 TestGame
{
public class Player : Microsoft.Xna.Framework.GameComponent
{
public static Texture2D Tex;
public static string Dir = "D";
public static Point Pos = new Point(GraphicsDeviceManager.DefaultBackBufferWidth / 2, GraphicsDeviceManager.DefaultBackBufferHeight / 2);
public static int speed = 4;
public static Rectangle Hitbox = new Rectangle(Pos.X, Pos.Y, Tex.Width, Tex.Height);
public Player(Game game): base(game) { }
public override void Initialize() { base.Initialize(); }
public override void Update(GameTime gameTime) { }
}
}
This exception is thrown whenever a static constructor throws an exception, and in this case it seems like you have a NullReferenceException in the static constructor of the Player class.
EDIT:
The problem here is the Tex static field which isn't initialized before HitBox is created, and this explains the reason of the NullReferenceExcpetion that you get. So in order to solve the problem you have to initialize it, and you can do it in this way in the Player class:
public static Rectangle HitBox;
//other fields and methods
public override void LoadContent(){
ContentManager content = MyGame.ContentManager;
Tex = content.Load<Texture2D>("mytexture");
//...
base.LoadContent();
this.InitializeAfterLoadingContent();
}
private void InitializeAfterLoadingContent(){
Hitbox = new Rectangle(Pos.X, Pos.Y, Tex.Width, Tex.Height);
}
As you can see I created another method cause a problem comes when the graphics resources are needed to initialize. In XNA the Initialize method is called before the LoadContent, so what you need to overcome this problem is to create a method and call it after loading content. Also your Game class can be done as:
public class MyGame : Microsoft.Xna.Framework.Game {
public static ContentManager ContentManager;
//...
public MyGame( ) {
//...
ContentManager = Content;
}
protected override void Initialize(){
// TODO: Add your initialization logic here
base.Initialize();
}
protected override void LoadContent() {
spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
//...
this.InitializeAfterLoadingContent();
}
//you can call it however you want
private void InitializeAfterLoadingContent(){
//initialize your non-graphical resources by using the content info you need,
//like the width and height of a texture you loaded
}
//...
}

Xna Movement not working

Hey since 1 week I am coding C# Xna and I ran into a problem
I hope you can help me.
The problem is that I made a Main class where I draw everything and I have a class for Control's
But now the control's wont work.
Main Class:
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 Pong_0._0._0._1
{
public class Main : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
public Texture2D paddel1;
public Texture2D paddel2;
public Texture2D border1;
public Texture2D border2;
public Vector2 paddel1Pos;
public Vector2 paddel2Pos;
public Vector2 border1Pos;
public Vector2 border2Pos;
public static int ScreenWidth = 1024;
public static int ScreenHeight = 768;
Paddels pads;
public Main()
{
graphics = new GraphicsDeviceManager(this);
graphics.PreferredBackBufferWidth = ScreenWidth;
graphics.PreferredBackBufferHeight = ScreenHeight;
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
pads = new Paddels();
pads.Initialize();
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
paddel1 = Content.Load<Texture2D>("BOP");
paddel2 = Content.Load<Texture2D>("BOP");
border1 = Content.Load<Texture2D>("BOB");
border2 = Content.Load<Texture2D>("BOB");
paddel1Pos = new Vector2(ScreenWidth / 16, ScreenHeight / 2 - paddel1.Height / 2);
paddel2Pos = new Vector2((ScreenWidth - paddel2.Width) - ScreenWidth / 16 , ScreenHeight / 2 - paddel2.Height / 2);
border1Pos = new Vector2(ScreenWidth / 2 - (border1.Width / 2) , ScreenHeight / 12);
border2Pos = new Vector2(ScreenWidth / 2 - (border2.Width / 2), (ScreenHeight - border2.Height) - ScreenHeight / 12);
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
pads.Update(gameTime);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Tomato);
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);
spriteBatch.Draw(paddel1, paddel1Pos, Color.White);
spriteBatch.Draw(paddel2, paddel2Pos, Color.White);
spriteBatch.Draw(border1, border1Pos, Color.White);
spriteBatch.Draw(border2, border2Pos, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
Control Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace Pong_0._0._0._1
{
public class Paddels
{
public Main main;
public int SPEED = 2;
public Paddels()
{
}
public void Initialize()
{
main = new Main();
}
public void Update(GameTime gameTime)
{
KeyboardState KBS = Keyboard.GetState();
if (KBS.IsKeyDown(Keys.Up))
{
main.paddel1Pos.Y = main.paddel1Pos.Y + SPEED;
}
else if (KBS.IsKeyDown(Keys.Down))
{
}
if (KBS.IsKeyDown(Keys.W))
{
}
else if (KBS.IsKeyDown(Keys.S))
{
}
}
}
}
I could do it all in one class but I want to learn to use multiple classes and the never work.
Thanks and hope to hear from anyone soon.
You are creating a new "main" in your "Paddles" class. This new "Main" object has no knowledge of the actual one.
To solve this, just pass in the existing one when creating the paddles like this:
pads.Initialize(this);
With your initialize function changed to:
public void Initialize(Main parent)
{
main = parent;
}
In general though, you are breaking encapsulation by doing this. The "Paddles" class should hold all the textures, update logic, and draw logic for the paddle game objects. The main class shouldn't need any of that, since it is passing it off to the new class, and the "Paddles" class shouldn't need any knowledge of the "Main" class (at least in your example).
Please let me know if you would like any clarification or extra informatino.
You need to put your paddle position, and paddle texture inside of your paddle class.
Then you need to make the paddle draw itself using these values.

Categories

Resources