Jump to content
  • Advertisement
Sign in to follow this  
zuhane

Classes and neatening code!

This topic is 2500 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello people! I was really hoping someone would be able to point me in the right direction with this. It's a problem that's kind of hard
to explain, but I'll go ahead with it. I've recently devoted a lot of time to reading XNA tutorials on the internet, seeking XNA advice and
buying XNA books. I'm starting to reach a point where I can add basic controls and movement, a little bit of physics and some sound effects,
etc. I'm studying computer programming and picking up certain points. However, and this is going to sound really weird, I don't actually get how you'd physically complete a game. My code is just all on one sheet, and it looks awful. I've heard something about "classes" which apparently allow you to reference more update and draw methods at the same time as the main class sheet or something.

I'm not too sure about how it works, but if someone could just point me in the direction of some good, extensive tutorials, or possibly try to explain to me how i'd go about this, I'd be so grateful! I understand methods and the concept of classes, but i literally can't find anything anywhere on how you'd take components of different XNA tutorials and add them all together into a full project.

Thanks for your time if you respond! ph34r.png

Share this post


Link to post
Share on other sites
Advertisement
Go with just C# for a while to learn the basics of object oriented programming (classe, inheritance, etc.). Plenty of tutorials that show you the basics of this. It's the same mistake i made when i went with XNA without enough knowledge of programming and C# in general.

However, if you create a class, for something that needs to load content.

You create that class called "ball" and add things like you do in that first game1.cs page. You add a constrctor for it to the class like this:

public int XPosition;
public int Ypos;
public Ball(int XPosition, int YPosition) //between () you can pass data to this class when you instantiate it in game1.cs
{
this.XPosition = Xposition;
Ypos = YPosition;
}
//now this class knows it's starting position once it's instantiated into an object.
//instantiate a object from this class in game1.cs like this:
Ball ball = new Ball(200, 400); //See how i "feed" the position to it.
//It also needs an image. So let's make a method for that.
Texture2D image;
public void LoadContent(ContentManager content) // again we need to pass this content manager to this method if we want to use it.
{
image = content.load<Texture2D>("imagename");
}
//now you want to call this method in the loadcontent method of game1.cs like this.
ball.LoadContent(Content); //Here i pass the games contentmanager to the method we created to this new object.


If you have trouble understanding this you really should go back and do some basic C# tutorials.

Share this post


Link to post
Share on other sites
Okay I can try to explain, Normally you use a different class whenever your programming a different object. That's why it's called object oriented programming. So what you would do is use a different class to describe the actions of every different object. For example in a pong game, you would make a class that describes the paddle, one that describes the ball. And you might add some classes for things like Gamestate, inputHandler, Network, Menu. e.t.c

Example down here i cut down a lot of the code cause that would make the post way to long (still long though), for the example i took the code from a pong game i made sometime ago. Advantage is that you describe an object with 1 class then make multiple object of it. So we make 2 paddles for 2 players with different keys. (also input i handled by a class called InputHelper) this makes code easier to read. Hope you will get how it works, if not you can send me a pm.

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Audio;
using System;
using System.Collections.Generic;
class GameWorld
{
public Vector2 Screensize;
Random random;
Texture2D background, scoreBar;
public Paddle paddle1, paddle2;
public List<Ball> balls;
public List<Particle> particles;
public Vector2 fieldSize = new Vector2(720, 450);
SpriteFont agency;
Pong_Fu mainClass;
public int score1, score2;
public Vector2 worldOffset = new Vector2(0, 0);

public GameWorld(ContentManager Content, Pong_Fu mainClass)
{
this.mainClass = mainClass;
Screensize = mainClass.Screensize;

balls = new List<Ball>();
particles = new List<Particle>();
random = new Random();
background = Content.Load<Texture2D>("Veld2");
Texture2D paddleSprite = Content.Load<Texture2D>("PongBar");
Texture2D ballSprite = Content.Load<Texture2D>("Bal");
scoreBar = Content.Load<Texture2D>("ScoreBar");
agency = Content.Load<SpriteFont>("agencyFB");
paddle1 = new Paddle(paddleSprite, new Vector2(Screensize.X/2-fieldSize.X/2, (Screensize.Y / 2)-(paddleSprite.Height/2)), Microsoft.Xna.Framework.Input.Keys.W, Microsoft.Xna.Framework.Input.Keys.S,Microsoft.Xna.Framework.Input.Keys.C,Microsoft.Xna.Framework.Input.Keys.V,Microsoft.Xna.Framework.Input.Keys.D,Microsoft.Xna.Framework.Input.Keys.A, 5, 255, this);
paddle2 = new Paddle(paddleSprite, new Vector2(Screensize.X/2 + fieldSize.X/2 - paddleSprite.Width, Screensize.Y / 2 - (paddleSprite.Height / 2)), Microsoft.Xna.Framework.Input.Keys.Up, Microsoft.Xna.Framework.Input.Keys.Down, Microsoft.Xna.Framework.Input.Keys.N,Microsoft.Xna.Framework.Input.Keys.M, Microsoft.Xna.Framework.Input.Keys.Left,Microsoft.Xna.Framework.Input.Keys.Right, 5, 255, this);
balls.Add(new Ball(ballSprite, new Vector2((Screensize.X / 2) - (ballSprite.Width / 2), (Screensize.Y / 2) - (ballSprite.Height / 2)), 0, 8, 255, false, this));
score1 = 0;
score2 = 0;
}

public void HandleInput(InputHelper inputHelper)
{
paddle1.HandleInput(inputHelper);
paddle2.HandleInput(inputHelper);
if (inputHelper.KeyPress(Microsoft.Xna.Framework.Input.Keys.Escape))
mainClass.gameState = 0;
if (inputHelper.KeyPress(Microsoft.Xna.Framework.Input.Keys.Pause))
mainClass.gameState = 0;
}


And here is the Paddle class

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
class Paddle : GameObject
{
Microsoft.Xna.Framework.Input.Keys Omhoog = new Microsoft.Xna.Framework.Input.Keys();
Microsoft.Xna.Framework.Input.Keys Omlaag = new Microsoft.Xna.Framework.Input.Keys();
Microsoft.Xna.Framework.Input.Keys Run = new Microsoft.Xna.Framework.Input.Keys();
Microsoft.Xna.Framework.Input.Keys Charge = new Microsoft.Xna.Framework.Input.Keys();
Microsoft.Xna.Framework.Input.Keys Sneaky = new Microsoft.Xna.Framework.Input.Keys();
Microsoft.Xna.Framework.Input.Keys SneakyCounter = new Microsoft.Xna.Framework.Input.Keys();
float curSpeed;
public bool running, runUp, runDown, makeSneaky, counterSneaky;
public int chargeValue;
Random random;

public Paddle(Texture2D spr, Vector2 pos, Keys omhoog, Keys omlaag, Keys run, Keys charge, Keys sneaky, Keys sneakyCounter, float spd, float alp, GameWorld gameworld)
: base(spr, pos, spd, alp, gameworld)
{
random = new Random();
Omhoog = omhoog;
Omlaag = omlaag;
Run = run;
Charge = charge;
Sneaky = sneaky;
SneakyCounter = sneakyCounter;
}
public override void HandleInput(InputHelper inputHelper)
{
if (inputHelper.KeyPressed(Run))
{
curSpeed = speed * 2;
running = true;
}
else
{
curSpeed = speed;
running = false;
}
if (inputHelper.KeyPressed(Charge))
{
chargeValue++;
curSpeed = speed/2;
running = false;
}
else
{
chargeValue = 0;
}
if (inputHelper.KeyPressed(Sneaky))
{
makeSneaky = true;
}
else
{
makeSneaky = false;
}
if (inputHelper.KeyPressed(SneakyCounter))
{
makeSneaky = false;
counterSneaky = true;
}
else
{
counterSneaky = false;
}
if (inputHelper.KeyPressed(Omhoog) && !inputHelper.KeyPressed(Omlaag))
{
position.Y -= curSpeed;
if (running)
runUp = true;
}
else
runUp = false;
if (inputHelper.KeyPressed(Omlaag) && !inputHelper.KeyPressed(Omhoog))
{
position.Y += curSpeed;
if (running)
runDown = true;
}
else
runDown = false;
if (position.Y > world.Screensize.Y / 2 + world.fieldSize.Y / 2 - sprite.Height) {
position.Y = world.Screensize.Y / 2 + world.fieldSize.Y / 2 - sprite.Height;
runDown = false;
}
if (position.Y < world.Screensize.Y / 2 - world.fieldSize.Y / 2) {
position.Y = world.Screensize.Y / 2 - world.fieldSize.Y / 2;
runUp = false;
}
}

public override void Update()
{
world.particles.Add(new Particle(sprite, position, 0.5f, 70, world.Random.Next(360), 1, world));
if (chargeValue > 0)
{
world.particles.Add(new Particle(sprite, position, chargeValue / 10, 70 + chargeValue, world.Random.Next(360), 1, world));
}
}
}


I hope this helped!

Share this post


Link to post
Share on other sites
Thanks for the speedy replies! I am actually studying C# alongside XNA, which is nice since they kind of slot together well. I'll read up on classes more in
C#. The weird thing is that the code I've been shown by you too makes sense to an extent, but it's just that I don't really get how you link components of different
classes together and how you make sure that the main Game.cs page doesn't get cluttered.

I think I'd be able to pick up the concept if I could find something extensive enough, but most internet tutorials seems to be a bit lacking in that area.

Share this post


Link to post
Share on other sites
Well check this out:

This is a class that is basically Game1.cs and gets all the information.
namespace Test
{
class Game1Replica
{
ContentManager content; //<-- this field is for storing the content manager if you might need it in the update method of this class. It's just an empty field still.
GraphicsDevice device; //<-- This one is for storing the graphics device object Game1.cs creates. It is handy since it has the viewport conditions in it for instance.
DrawSomething drawSome // <-- this represents another class i created , here i make a field for it.

public Game1Replica()
{
//This is the constructor just like in Game1.cs it does not need to return anything hence there is no need for "void".
drawSome = new DrawSomething(); //<-- Here i put a new object into the field.
}
public void Initialize(GraphicsDevice device) //<-- look it needs a graphics device whenever i call this method.
{
this.device = device; //This is basically the same as in the Game1.cs initialize method. See her i put the graphics device Game1.cs uses into the field i created above so i can use it throughout this class.
}
public void LoadContent(ContentManager content) //<-- And here it needs a contentmanager if i call this method from Game1.cs
{
this.content = content; // <-- like i did with the graphics device i put the content manager into it's own field within this class for further use.
drawSome.LoadContent(content); <-- Thats that draw class to draw something, since it probably needs to load some content i made that method like this one. Also content refers to the one that gets passed to this method. This.content refers to the content field in this class itself.
}
public void Update(GameTime gameTime)
{

}
public void Draw(SpriteBatch spriteBatch)
{
drawSome.draw(spriteBatch); // In that class that draws something i also created a Draw method, and it needs a spriteBatch to be fed.
}
}
}


Now whatch closely how i use all these methods in my game1.cs.
Game1.cs:
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Game1Replica Game2; //<---------------------------------------------------------------------------------------------------------------------------------------------------------
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
Game2 = new Game1Replica(); // <----------------------------------------------------------------------------------------------------------------------
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
Game2.Initialize(graphics.GraphicsDevice); //<----------------------------------------------------------------------------------------
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);
Game2.LoadContent(Content); //<------------------------------------------------------------------------------------------------------
// TODO: use this.Content to load your game content here
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// 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();
Game2.Update(gameTime); //<-----------------------------------------------------------------------------------------------------------------
// TODO: Add your update logic here
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);

// TODO: Add your drawing code here
Game2.Draw(spriteBatch); // <-----------------------------------------------------------------------------------------------------------------------------
base.Draw(gameTime);
}
}


To extend on this.

Say i have a camera class that has something like a position.

public Vector2 CamPosition { get; private set;}
And a input class that gets me my mouse position on the screen.
static public Vector2 MouseScreenPosition()
{
return new Vector2((int)newMouseState.X, (int)newMouseState.Y);
}


I instantiate both classe (creating a object with a "new" statement.

and i need that info in another class let's say my character to know where he clicked i can do this:

Character.cs Update method
public void Update(Vector2 CamPosition, Vector2 MousePosition, GameTime time)
{
//Do stuff with it.
}


And if i want to use this method, i first have to create an object from this class like, Character newChar = new Character. Then if i want to call this newChar.update method in the Game1 Update method i do this.
newChar.Update(cameraObject.CamPosition, input.MouseScreenPosition(), Gametime);
Obvious that camera class has to have an object here or further down the line and has it's position passed to it like this. In this case i instantiated the camera class as cameraObject. Input is static so can be called directly from the class.



Really if this is still not clear, drop XNA for now and learn about classes. You should also learn about inheritance if you want to get anywhere.

Share this post


Link to post
Share on other sites
A Class is really a classification for an object.

You could have a Base Animal Class, with derived Mammal/Human/Rat/Cat Classes.

In the class you have everything you need to use your class object.

As in a Human class would describe more functions than the Rat Class.

To get the objects to interact with each other you would pass a class object as a method parameter, or loop thru a list of say rats to check if the human can see them.

http://msdn.microsoft.com/en-us/library/ms173109.aspx

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!