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

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);
}
}
}
}

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 ?

C# XML Error: System.InvalidOperationException

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.

Unity Camera Change C#

I have three characters and each of them has a camera attached to them.By default they are disabled but one.I made a character selector which is supposed to change them.I have a problem where I can move the selected one but the camera stays at the last one.
Here is the script:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityStandardAssets.Utility;
public class GameManageer : MonoBehaviour {
public Camera[] cams = new Camera[3];
public Character CurrentCharacter;
public List<Character> Characters = new List<Character>();
public List<Item> AllItems;
bool ShowCharWheel;
public int SelectedCharacter;
public int lastCharacter;
public static GameManageer Instance;
void Awake(){
Instance = this;
foreach (Character c in Characters){
c.Instance = Instantiate(c.PlayerPrefab, c.HomeSpawn.position, c.HomeSpawn.rotation) as GameObject;
c.Instance.GetComponent<PlayerController>().LocalCharacter = c;
}
ChangeCharacter(Characters[PlayerPrefs.GetInt("SelectedChar")]);
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetKey (KeyCode.C)) {
ShowCharWheel = true;
} else {
ShowCharWheel = false;
}
}
void ChangeCharacter(Character c){
lastCharacter = SelectedCharacter;
SelectedCharacter = Characters.IndexOf (c);
cams [SelectedCharacter].gameObject.SetActive (true);
cams [lastCharacter].gameObject.SetActive (false);
CurrentCharacter = c;
Characters [lastCharacter].Instance.GetComponent<PlayerController> ().CanPlay = false;
Characters [SelectedCharacter].Instance.GetComponent<PlayerController> ().CanPlay = true;
PlayerPrefs.SetInt ("SelectedChar", SelectedCharacter);
}
void OnGUI(){
if (ShowCharWheel) {
GUILayout.BeginArea(new Rect(Screen.width - 64, Screen.height - 192,64,192));
foreach (Character c in Characters){
if (GUILayout.Button(c.Icon,GUILayout.Width(64),GUILayout.Height(64))){
ChangeCharacter(c);
}
}
GUILayout.EndArea();
}
}
}
[System.Serializable]
public class Character {
public string Name;
public Texture2D Icon;
public GameObject PlayerPrefab;
public GameObject Instance;
public Transform HomeSpawn;
}
[System.Serializable]
public class Item{
public string Name;
public Texture2D Icon;
public ItemInstance InstancePrefab;
}
This should do the job:
cams[SelectedCharacter].enabled = true;
cams[lastCharacter].enabled = false;
Use Depth:
foreach (Camera cam in cams)
{
cam.depth = cam == cams[SelectedCharacter] ? 10 : 0;
}
I think the real problem here though, is that you have more cameras in the scene which you have to manage as well, other then only the last and current selected character... in which case:
foreach (Camera cam in cams)
{
cam.SetActive(cam == cams[SelectedCharacter]);
}

Why won't my sprite draw? (XNA)

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

What is a good example of saving game data in XNA 4.0?

I am trying to work my way through the XNA MSDN documentation on saving and reading game data, and I am not having much luck.
In essence I have a manager class which keeps track multiple instance of base classes.
I want to be able to save the state of the entire list of objects that the manager is keeping track of.
Then load them in the next time the game loads. Basically saving the state of the world.
If you use the XmlSerializer as shown in the XNA 4.0 help, base classes need to have the [XmlInclude(Type)] attribute specified for each concrete type they can be serialized into.
Below is an example of how to save game data in XNA 4.0. Press F1 to save once the game is running. The data will be saved to a location similar to C:\Users\{username}\Documents\SavedGames\WindowsGame\Game1StorageContainer\Player1.
Loading the data again is a very similar process.
To get this working on XBox add references to Microsoft.Xna.Framework.GamerServices & System.Xml.Serialization.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Xml.Serialization;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.GamerServices;
namespace WindowsGame
{
[XmlInclude(typeof(Soldier)), XmlInclude(typeof(Grenade))]
public class BaseGameObject
{
public Vector3 Position { get; set; }
}
public class Soldier : BaseGameObject
{
public float Health { get; set; }
}
public class Grenade : BaseGameObject
{
public float TimeToDetonate { get; set; }
}
public struct SaveGameData
{
public string PlayerName;
public Vector2 AvatarPosition;
public int Level;
public int Score;
public List<BaseGameObject> GameObjects;
}
public class Game1 : Microsoft.Xna.Framework.Game
{
enum SavingState
{
NotSaving,
ReadyToSelectStorageDevice,
SelectingStorageDevice,
ReadyToOpenStorageContainer, // once we have a storage device start here
OpeningStorageContainer,
ReadyToSave
}
GraphicsDeviceManager graphics;
KeyboardState oldKeyboardState;
KeyboardState currentKeyboardState;
StorageDevice storageDevice;
SavingState savingState = SavingState.NotSaving;
IAsyncResult asyncResult;
PlayerIndex playerIndex = PlayerIndex.One;
StorageContainer storageContainer;
string filename = "savegame.sav";
SaveGameData saveGameData = new SaveGameData()
{
PlayerName = "Grunt",
AvatarPosition = new Vector2(10, 15),
Level = 3,
Score = 99424,
GameObjects = new List<BaseGameObject>()
{
new Soldier { Health = 10.0f, Position = new Vector3(0.0f, 10.0f, 0.0f) },
new Grenade { TimeToDetonate = 3.0f, Position = new Vector3(4.0f, 3.0f, 0.0f) }
}
};
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
#if XBOX
Components.Add(new GamerServicesComponent(this));
#endif
currentKeyboardState = Keyboard.GetState();
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
oldKeyboardState = currentKeyboardState;
currentKeyboardState = Keyboard.GetState();
UpdateSaveKey(Keys.F1);
UpdateSaving();
base.Update(gameTime);
}
private void UpdateSaveKey(Keys saveKey)
{
if (!oldKeyboardState.IsKeyDown(saveKey) && currentKeyboardState.IsKeyDown(saveKey))
{
if (savingState == SavingState.NotSaving)
{
savingState = SavingState.ReadyToOpenStorageContainer;
}
}
}
private void UpdateSaving()
{
switch (savingState)
{
case SavingState.ReadyToSelectStorageDevice:
#if XBOX
if (!Guide.IsVisible)
#endif
{
asyncResult = StorageDevice.BeginShowSelector(playerIndex, null, null);
savingState = SavingState.SelectingStorageDevice;
}
break;
case SavingState.SelectingStorageDevice:
if (asyncResult.IsCompleted)
{
storageDevice = StorageDevice.EndShowSelector(asyncResult);
savingState = SavingState.ReadyToOpenStorageContainer;
}
break;
case SavingState.ReadyToOpenStorageContainer:
if (storageDevice == null || !storageDevice.IsConnected)
{
savingState = SavingState.ReadyToSelectStorageDevice;
}
else
{
asyncResult = storageDevice.BeginOpenContainer("Game1StorageContainer", null, null);
savingState = SavingState.OpeningStorageContainer;
}
break;
case SavingState.OpeningStorageContainer:
if (asyncResult.IsCompleted)
{
storageContainer = storageDevice.EndOpenContainer(asyncResult);
savingState = SavingState.ReadyToSave;
}
break;
case SavingState.ReadyToSave:
if (storageContainer == null)
{
savingState = SavingState.ReadyToOpenStorageContainer;
}
else
{
try
{
DeleteExisting();
Save();
}
catch (IOException e)
{
// Replace with in game dialog notifying user of error
Debug.WriteLine(e.Message);
}
finally
{
storageContainer.Dispose();
storageContainer = null;
savingState = SavingState.NotSaving;
}
}
break;
}
}
private void DeleteExisting()
{
if (storageContainer.FileExists(filename))
{
storageContainer.DeleteFile(filename);
}
}
private void Save()
{
using (Stream stream = storageContainer.CreateFile(filename))
{
XmlSerializer serializer = new XmlSerializer(typeof(SaveGameData));
serializer.Serialize(stream, saveGameData);
}
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
base.Draw(gameTime);
}
}
}

Categories

Resources