13 Replies - 702 Views - Last Post: 11 June 2012 - 06:10 PM

#1 DanielLeone  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 177
  • Joined: 04-February 12

Efficiency Question

Posted 08 June 2012 - 09:00 PM

Hello,

As you know, the predefined Game1 class in a Windows Game, already has separate Update and Draw methods. I know these are used when the Game is running, in the way that it will Update 60 times a second, and only draw if it has the time. Something like that (you know what I mean).

Now, as I would imagine many of you would do, I have a GameObject class, with an Update and Draw method, and then all my 'gameObjects' inherit GameObject. The obvious way to Update your Objects in my opinion is using a loop like so :

Update method...
foreach (GameObject o in gameObjects)
{
   o.Update(gameTime);
}

Draw method...
foreach (GameObject o in gameObjects)
{
   o.Draw(spriteBatch);
}



I tend not to like using the Game1 class, I think because I don't really know what it does. I'm one of those people who like to know exactly what something is doing (if you know what I mean). So what I do is create another class, something like Manager.

Then I create my own Initialize and Updater methods in that.

That way, I only have 2 lines of code in the Game1 class.

Manager.Intialize(parametres); In the Initialize method of Game1

Mangaer.Updater(parameters); In the Update method of Game1.

It's purely choice that I have it in 2 lines, and not 4, because I could be uisng Initialize, LoadContent, Update and Draw.

Now what this means, it that I only have 1 foreach loop for Updating and Drawing instead of 2. Like so.
public void Updater(GameTime gameTime, SpriteBatch spriteBatch)
{
   foreach (GameObject o in gameObjects)
   {
      o.Update(gameTime);
      o.Draw(spriteBatch);
   }
}



So that is the benefits. The Cons are I suppose that I will always be running through the Drawing stuff, whereas the framework is designed to have 2 seperate methods.

Is this a good Idea?
Or should I revert back to using 2 methods for Update and Draw?

Another benefit I thought of is that, I actually have all my objects draw and updated in a specific order. So an example is, anything under the pause screen is Update and Draw before the PauseScreen is actually Update itselft. If that made sense. Like this :

Object1.Update
Object1.Draw

Object2.Update
Object3.Update

Object2.Draw
Object3.Draw

And in some cases, it's important the order they're in.

Thanks in advance,
Daniel,

Wow. I just reread that, and could have just said, is using 2 foreach loops going to be less efficient that using 1? I must be getting that from BBeck;)

This post has been edited by DanielLeone: 09 June 2012 - 12:08 AM


Is This A Good Question/Topic? 0
  • +

Replies To: Efficiency Question

#2 bonyjoe  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 175
  • View blog
  • Posts: 548
  • Joined: 08-September 10

Re: Efficiency Question

Posted 09 June 2012 - 01:13 PM

I suggest you stick to using update to update and draw to draw, that way the entire frame should have updated before it is drawn, this will prevent dodgy collisions etc. Also the update method is meant to be used for updating, all the xna code is based around this being the case, if this becomes not the case then it's only ever likely to be perform worse, I doubt it will ever perform better.

edit: why do you want to draw your pause screen before updating everything else? Surely your pause screen should just prevent everything else from updating.

This post has been edited by bonyjoe: 09 June 2012 - 01:14 PM

Was This Post Helpful? 1
  • +
  • -

#3 DanielLeone  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 177
  • Joined: 04-February 12

Re: Efficiency Question

Posted 10 June 2012 - 04:09 AM

Yeah I suppose you're right bonyjoe. I've changed all my code to comply with this, and it's now all working properly.

I have an error I'm getting though, in one of my foreach loops. This is off topic, but I'll ask it here since this topic didn't really go far.

It's saying the collection was modified, and I do know what that means. But I refuse to belive how it's happened.

Basically I have 2 lists.
1. Screens.
2. tempScreens.

In a obscure part of my code I do have Screens = tempSceens, and tempScreens = Screens, but this shouldn't matter because they aren't run through where the error occurs.

So, I put a breakpoint, at the line of code that says tempScreen.Add(screen). Just before this line, Screens has 1 object inside. Just after this line runs, Screens now has 2! How can that be.

I think you'll have to take my word that it's the truth, Screens is changed, without it ever being called. It's like tempScreens is linked to Screens or something. But I can't see how, it's not like Screens returns tempScreens or anything through Properties.

Any Ideas?
Thanks,
Daniel,

This post has been edited by DanielLeone: 10 June 2012 - 04:17 AM

Was This Post Helpful? 0
  • +
  • -

#4 racidon  Icon User is offline

  • D.I.C Head

Reputation: 59
  • View blog
  • Posts: 172
  • Joined: 27-August 11

Re: Efficiency Question

Posted 10 June 2012 - 08:12 AM

Hi Daniel,

Your "obscure" bit is because when you say "List<T>" = "List<T>" or any kind of array or class type equals another you will get a "Reference" which is just an address to a space in memory. So if you edit one you will edit them all.

To avoid this if you actually want the data rather than the reference you use the "Clone" method:

Screens = (List<T>)tempScreens.Clone();

For classes of your own kind you will need to implement IClonable or you can create a constructor that takes the same type and sets all values based on passed class

Example:

public class exampleClass
{
string exampleString;

public exampleClass()
{
exampleString = string.Empty;
}

public exampleClass(string value)
{
exampleString = value;
}

public exampleClass(exampleClass example)
{
this.exampleString = example.exampleString;
}

}




exampleClass
   startobject,
   refobject,
   valueobject;

startObject = new exampleClass("This creates a new reference to memory");

refObject = startObject;

//Change start object string
startObject.exampleString = "This will be a value object";

valueObject = new exampleClass(startObject);

//Change back
startObject.exampleString = "Classes with this value are storing the reference of this class."




Final output of each object:
startObject = "Classes with this value are storing the reference of this class."
refObject = "Classes with this value are storing the reference of this class."
valueObject = "This will be a value object"



As for how your making objects, a handy class to be using is "DrawableGameComponent" and "GameComponent"

If you add this as base classes to your main classes you then add them to your "Components" of your Game class and when "base.Update()" and "base.Draw()" are called, the draw and update of each component that is enabled/visible are called.
Was This Post Helpful? 3
  • +
  • -

#5 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 578
  • View blog
  • Posts: 1,282
  • Joined: 24-April 12

Re: Efficiency Question

Posted 11 June 2012 - 05:13 AM

View PostDanielLeone, on 08 June 2012 - 09:00 PM, said:

Hello,

As you know, the predefined Game1 class in a Windows Game, already has separate Update and Draw methods. I know these are used when the Game is running, in the way that it will Update 60 times a second, and only draw if it has the time. Something like that (you know what I mean).

Now, as I would imagine many of you would do, I have a GameObject class, with an Update and Draw method, and then all my 'gameObjects' inherit GameObject. The obvious way to Update your Objects in my opinion is using a loop like so :

Update method...
foreach (GameObject o in gameObjects)
{
   o.Update(gameTime);
}

Draw method...
foreach (GameObject o in gameObjects)
{
   o.Draw(spriteBatch);
}



I tend not to like using the Game1 class, I think because I don't really know what it does. I'm one of those people who like to know exactly what something is doing (if you know what I mean). So what I do is create another class, something like Manager.

Then I create my own Initialize and Updater methods in that.

That way, I only have 2 lines of code in the Game1 class.

Manager.Intialize(parametres); In the Initialize method of Game1

Mangaer.Updater(parameters); In the Update method of Game1.

It's purely choice that I have it in 2 lines, and not 4, because I could be uisng Initialize, LoadContent, Update and Draw.

Now what this means, it that I only have 1 foreach loop for Updating and Drawing instead of 2. Like so.
public void Updater(GameTime gameTime, SpriteBatch spriteBatch)
{
   foreach (GameObject o in gameObjects)
   {
      o.Update(gameTime);
      o.Draw(spriteBatch);
   }
}



So that is the benefits. The Cons are I suppose that I will always be running through the Drawing stuff, whereas the framework is designed to have 2 seperate methods.

Is this a good Idea?
Or should I revert back to using 2 methods for Update and Draw?

Another benefit I thought of is that, I actually have all my objects draw and updated in a specific order. So an example is, anything under the pause screen is Update and Draw before the PauseScreen is actually Update itselft. If that made sense. Like this :

Object1.Update
Object1.Draw

Object2.Update
Object3.Update

Object2.Draw
Object3.Draw

And in some cases, it's important the order they're in.

Thanks in advance,
Daniel,

Wow. I just reread that, and could have just said, is using 2 foreach loops going to be less efficient that using 1? I must be getting that from BBeck;)



It's interesting that you're doing it this way.

I'm not sure I'm an "expert" on how to write the absolute most efficient XNA code, but I know Update and Draw are seperated in Game1 for a reason. One thing is that there may be times when one is called and the other isn't. For example, if your FPS get too slow, I believe it will stop calling Draw so that it can try and get caught up. Also, Update is for game logic, and Draw is for drawing in the sense of just keeping code for different purposes seperate and easy to find/read.

Creating a GameObject class is not a bad idea, but I think XNA has already done this for you. I "think" you're "recreating the wheel". I haven't actually used them - though I've read up on them a bit - but I think "Game Components" do basically what you're describing. I would suggest reading up on those. I think they do pretty much what you're describing with your GameObjects class. They are the primary reason you have to include that

base.Update(gameTime);

and

base.Draw(gameTime);

in your code every time.

Those two calls call all your GameComponent objects. Two lines of code can be doing all of the updating and drawing for your entire game from Game1.

Notice that there are two seperate GameComponent objects that you can inherit from. One that Updates and Draws and one that only Updates. (Some objects are game logic only that never draw anything to the screen.)

I agree that you should keep Game1 code sparse. Keeping it sparse is mostly a matter of keeping things well organized.

http://msdn.microsof...ecomponent.aspx
Was This Post Helpful? 0
  • +
  • -

#6 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 578
  • View blog
  • Posts: 1,282
  • Joined: 24-April 12

Re: Efficiency Question

Posted 11 June 2012 - 05:18 AM

View PostDanielLeone, on 08 June 2012 - 09:00 PM, said:

Hello,

As you know, the predefined Game1 class in a Windows Game, already has separate Update and Draw methods. I know these are used when the Game is running, in the way that it will Update 60 times a second, and only draw if it has the time. Something like that (you know what I mean).


Wow. You posted this last Friday and I'm just now reading it. I was starting to get a little burnt out from all the work on the website and whatnot. It's been all work in my spare time for weeks, trying to get the site running. I decided to load Skyrim on my PC and start up a new character. Of course with Skyrim on the PC you can mod it like crazy and then the mods cause the game to crash, so I really spent 60% of the time this weekend just trying to get it to work. Anyway, it was pretty refreshing and I was looking at everything in the game going "I wonder how they did that?"

Sorry, a bit off topic, but I was just explaining why it took me half a week to reply.
Was This Post Helpful? 0
  • +
  • -

#7 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 578
  • View blog
  • Posts: 1,282
  • Joined: 24-April 12

Re: Efficiency Question

Posted 11 June 2012 - 05:23 AM

View Postracidon, on 10 June 2012 - 08:12 AM, said:

Hi Daniel,


As for how your making objects, a handy class to be using is "DrawableGameComponent" and "GameComponent"

If you add this as base classes to your main classes you then add them to your "Components" of your Game class and when "base.Update()" and "base.Draw()" are called, the draw and update of each component that is enabled/visible are called.


Whoops. I didn't read far enough in the thread before posting. Racidon already said what I posted. Except, he managed to say it in two sentences, whereas it took me a book to say it. ;-)

I actually didn't know that about clonable objects. Thanks for pointing that out Racidon.
Was This Post Helpful? 0
  • +
  • -

#8 DanielLeone  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 177
  • Joined: 04-February 12

Re: Efficiency Question

Posted 11 June 2012 - 05:56 AM

Thanks for the replies.

So, I'm going to implement ICloneable, but I don't see how it works.

I assume that the class I'm wanting to inherit ICloneable is Screen? Seen as my 2 lists are List<Screen>, but then where is the Clone() method?

After typing ICloneable, I get the option to Implement, or Explicitly Implement the interface, but it just adds an object called Clone.

What then is the point of ICloneable, if I could type out this method anyway? I'm sure there's a perfectly logical answer, but I obviously don't know it.

And about adding a reference to memory. That sort of threw how I thought the compiler worked out the window :(.

I'm wondering why it would add the reference in the first place? How am I to know what adds a reference to memory, and what doesn't.

Does the same happen to dictionaries? Arrays? How can I know?

As I've said, I'm sure there's a perfectly logical answer, but I don't know.

As for DrawableGameComponents, I've only ever seen them used for the ScreenManager. Which I kind of a different situation to a GameObject. I honestly thought that creating a generic class for all GameObjects to inherit from was the 'way' of doing things. Only because all the tutorials I've seen and read, use this method.

I can understand where I could use these interfaces (DrawableGameComponent, GameComponent) but I don't really think it would suit how I've set my game up.
If it calls the Update and Draw method at base.Draw and base.Update, that would mean the last line of code. And as I said the way I've set it up, actually matters quite significantly, because I'm drawing Idle (behind pause screen) gameObjects before gameObjects in the pauseScreen, for obvious reasons.

To use the interfaces, you said that I've had to add them to game1.Components; That would mean access to Components, and as I've said, I don't like having a lot of stuff in the Game1, so to get there, there'd be alot of changes. Hope that made sense, and you understand.

Thanks again,
Daniel,

This post has been edited by DanielLeone: 11 June 2012 - 06:04 AM

Was This Post Helpful? 0
  • +
  • -

#9 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 578
  • View blog
  • Posts: 1,282
  • Joined: 24-April 12

Re: Efficiency Question

Posted 11 June 2012 - 06:43 AM

We'll have to wait for Racidon, or someone, to explain how to know which objects need to be cloned and which don't. I get what he's saying, but I haven't been in a situation where I used cloned objects before. It's an area that I know pretty much nothing about.

As far as game components. I think they were designed to do pretty much what you're doing. I'm not sure they were available in early versions of XNA, and I think they may be a little more difficult to actually implement than just a class. So, that may be a big part of the reason you don't see a lot of examples using them. But, I think Microsoft put a lot of thought into them.

As far as using them for startup screens and whatnot, I'm sure you could, but I think their primary purpose is more standard game objects. I think of them in terms of 3D models, terrain meshes, and every object that shows up on the screen for the Drawable class. And then I think of Input Handlers, Event Handlers, and other game logic for the non-Drawable class.

Order can certainly be critical, and I'm pretty sure they've thought of that as well. I seem to remember reading something about how you can specify what order they're called in. And I also remember that it was getting into Interfaces in order to allow objects that don't know one another's capabilities to communicate between each other. It looked really cool, and it's been on my "to-do" list to learn. But so far for me, it's been easier just to create my own base object.

Oh. That reminds me. I think pretty much anything that's created using the keyword "new" is a reference to a location in memory. All "objects" are pointers (references to a location in memory). Usually in C#, you don't have to really think about what's a variable, what's a pointer, and so forth. Having a knowledge of C++ really helps in understanding that stuff, and Assembly takes you even deeper.
Was This Post Helpful? 0
  • +
  • -

#10 Kilorn  Icon User is offline

  • XNArchitect
  • member icon



Reputation: 1356
  • View blog
  • Posts: 3,528
  • Joined: 03-May 10

Re: Efficiency Question

Posted 11 June 2012 - 07:01 AM

This is an unfortunate side effect of higher level languages. You don't normally control how memory is handled, so you don't think about it. The differences in this instance are between reference types, and value types. If you set a value type variable to equal another variable, it will take the value and create a new spot in memory that contains that value. If you set a reference type variable to equal another variable, then the first variable will now only hold a "reference", or memory address to the data that is contained in the second variable.

The way I've tricked myself into remembering whether a data type is reference type or value type, is to determine whether the data type has a finite possible pool of values. For instance, an integer is value type because it will only hold a finite number of possible values, up to the max value, which is -2147483647 to 2147483647 with a 32bit unsigned integer.

A string however is a reference type. There are limitless possible values that a string can hold. It could be "x", or "this is a string", or even "123123123123123123123". Arrays, all kinds of arrays, are reference type as well, even if their elements' data types are value types. For instance, an array of integers, while the actual elements hold value types, is a reference type.

Here is a nice little breakdown of the most common data types and whether they're reference type or value type.
Was This Post Helpful? 2
  • +
  • -

#11 racidon  Icon User is offline

  • D.I.C Head

Reputation: 59
  • View blog
  • Posts: 172
  • Joined: 27-August 11

Re: Efficiency Question

Posted 11 June 2012 - 08:51 AM

Hate to step on a forum leader's toes but that's not really a good way when it comes to c# atleast.

Value Types:
Structures
Primary Data (char/byte/sbyte/short/ushort/int/uint/long/ulong/string) - This includes their "Class Types"

Reference Types:
Classes
Arrays of ANY kind (dictionary/list/array/Mulit-Dimension array etc etc)


I will note however in your "string" variable it does just contain a reference to memory but each time you say myString = "new string" or myString = anotherString it will create a new reference to memory of the character array (which is what a string is)
So basically I'm saying follow the rules as above, string is the exception.
I would assume string works like this because the definition of the = operator in the string class is most likely set to create a new character array, along with the + operator would also do this.



As for ICloneble, although yes you could just implement your own clone method, it's not good practice for a class that you want to be cloneble as the interface will force you to implement the method, where as a class without is not required.


As for your screens cloning, that will not happen by a method within your screen class, since that is a List<T> class you will use the List<T>.Clone() method. example:

Screens = (List<GameScreenClass>)tempScreens.Clone();



Don't forget the casting, as all Clone methods return the base object.
Was This Post Helpful? 2
  • +
  • -

#12 DanielLeone  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 177
  • Joined: 04-February 12

Re: Efficiency Question

Posted 11 June 2012 - 05:17 PM

Thanks for the replies,

View Postracidon, on 11 June 2012 - 11:51 PM, said:

Value Types:
Structures
Primary Data (char/byte/sbyte/short/ushort/int/uint/long/ulong/string) - This includes their "Class Types"

Reference Types:
Classes
Arrays of ANY kind (dictionary/list/array/Mulit-Dimension array etc etc)


That makes pretty much sense, and makes it easier to know what to expect from now on.

I still don't know how to see the Clone method though. It's probably something simple I'm missing, but don't see it in the list of methods for List<T>.

Thanks,
Daniel,
Was This Post Helpful? 0
  • +
  • -

#13 Kilorn  Icon User is offline

  • XNArchitect
  • member icon



Reputation: 1356
  • View blog
  • Posts: 3,528
  • Joined: 03-May 10

Re: Efficiency Question

Posted 11 June 2012 - 05:29 PM

The ICloneable interface is not implemented on the List class. You'll either have to use a collection that can be cloned, or you could simply use the CopyTo(T[]) method and copy all of the elements into an array. I haven't tested if this can be done with other types of collections such as another list, but you can easily copy the data from a list to a single dimensional array using this method.
Was This Post Helpful? 1
  • +
  • -

#14 racidon  Icon User is offline

  • D.I.C Head

Reputation: 59
  • View blog
  • Posts: 172
  • Joined: 27-August 11

Re: Efficiency Question

Posted 11 June 2012 - 06:10 PM

Sorry I assumed it was implemented.

You can use the following:

Screens = new List<T>();

Screens.AddRange(tempScreens);


Was This Post Helpful? 0
  • +
  • -

Page 1 of 1