I want to create a simple game where my character can walk, jump, shoot. But I got stuck on how to call the update method from another class? At the moment all of my code is in Game.cs (the main class), but I want to create different classes, depending on my needs. How can I do this?
Your update code is called many times each second automaticly (Depending on your frame rate).
Unlike regular C# programming that uses events and must update on its own, in XNA your update code will loop every few milliseconds.
If you want to have other classes make their own updates you can use a GameComponent, or simply create a method in another class.
Here is an example of your main class:
public class Game1 : Game
{
Level level;
protected override void Initialize()
{
// TODO: Add your initialization logic here
level = new Level();
base.Initialize();
}
protected override void Update(GameTime gameTime)
{
// TODO: Add your update logic here
level.Update(gameTime);
base.Update(gameTime);
}
And your other Level class
public class Level
{
Vector2 CharacterPosition;
public Level()
{
}
public void Update(GameTime gameTime)
{
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
//Move the character
ChactacterPosition.X += elapsed * speed;
}
}
you could create custom classes with an update and a draw method to call on every update from game.cs.
this is the best place to start learning xna:
http://xbox.create.msdn.com/en-US/education/tutorial/2dgame/getting_started
if you go through the first parts of the tutorial, you'll get exactly the examples you need for your question.
Related
I'm working on a hobby project in Unity. I have MonoBehaviour scripts for my characters that use component objects for each behavior the character has. When I create new characters, I inherit a new class from the base class for whichever component behaves differently.
When certain triggers occur, I send characters back to their initial state by calling a Reset() method exposed by the base class that sets fields back to their initial values. I'm wondering how to send that call down through the inheritance chain. Right now, the base class has a protected virtual ChildReset() that gets called in Reset() and does nothing by default. If child classes have fields to reset, they override this method. It feels like a really awkward way of doing it.
I like the idea of implementing something similar to the messaging system Unity uses. If a monobehavior doesn't use the Update() message, then the class just doesn't define an update. It eliminates unnecessary calls. I have no idea how I would do something like that.
Any thought invested in this is much appreciated! I've written out the way my project is structured below just in case these details are useful for answers.
public class Character : MonoBehaviour
{
private Motion motionController;
private Interaction characterInteractionController;
//etc
private void Update()
{
motionController.DoStuff();
characterInteractionController.DoStuff();
}
private void Reset()
{
motionController.Reset();
characterInteractionController.Reset();
}
private void OnEnable() => ResetTrigger.OnReset += Reset;
private void OnDisable() => ResetTrigger.OnReset -= Reset;
}
public class Motion : Component {}
public class Interaction : Component {}
public abstract class Component
{
public void Reset()
{
/* set fields to default values */
ChildReset();
}
protected virtual void ChildReset() { }
public abstract void DoStuff();
}
There is no need to send a call down through the inheritance chain. You do not have two different objects. An object of the child class contains everything declared in the base class. Why not directly make Reset() virtual?
public abstract class Character : MonoBehaviour
{
public virtual void Reset()
{
...
}
}
public class ChildCharacter : Character
{
// If ChildCharacter has stuff to reset, override this method, otherwise don't!
public override void Reset()
{
base.Reset(); // Call this to reset stuff from the base class.
//TODO: reset child stuff.
}
}
If Reset is overridden in the child class, then calling Reset will call ChildCharacter.Reset() even if called on a variable statically typed as Character.
Character c = new ChildCharacter();
c.Reset(); // calls ChildCharacter.Reset() when overridden
If Reset is not overridden in the child class, then calling Reset will call Character.Reset() even if called on a ChildCharacter.
ChildCharacter child = new ChildCharacter();
child.Reset(); // calls Character.Reset() when not overridden.
The update method in enemyHealth wants me to make targetHealth a static but if I do that then I won't be able to make unique enemies.
{
public Text enemyHealth;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
enemyHealth.text = EnemyVitals.targetHealth.ToString();
}
}
{
public double targetHealth = 100;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (targetHealth <= 1)
{
Destroy(gameObject);
}
}
}
as far as I understand, this: enemyHealth.text = EnemyVitals.targetHealth.ToString();
tries to access targetHealth like you would access static classes for example Vector3.up. These static classes/methods allow you to use their methods without making an instance of that class. So in your case, you would need a reference to an EnemyVitals instance and call .targetHealth on that instance. You can for example instantiate one via EnemyVitals enemyVit = new EnemyVitals(); or declare a public field in your first class like so: public EnemyVitals enemyVit;, then in the editor drag and drop the EnemyVitals reference to that field. I think you might rather want to get the reference somehow otherwise in-game, for example with raycasting to possible enemy objects etc..
From what you posted it seems to me that the latter is more what you would want to go for.
I'm currently programming a 2D Game Engine in C# using GDI+ and at the moment I'm trying to implement a component based structure.
The idea is that my GameObject class has a list of components. Each component can be completely different to the next.
I represented components by creating a Component class, which looks like this:
public class Component : BaseObject
{
/// <summary>
/// The game object this component is attached too.
/// </summary>
private GameObject gameObject = null;
/*
* Below I called the protected virtual methods from the "BaseObject" class.
* The base object class only contains these 4 protected virtual methods. Nothing else.
*/
public void Load()
{
OnLoad(this, EventArgs.Empty);
}
public void Unload()
{
OnUnload(this, EventArgs.Empty);
}
public void Update(GameTime gameTime)
{
OnUpdate(this, new UpdateEventArgs(gameTime));
}
public void Render(GraphicsEngine graphicsEngine)
{
OnRender(this, new RenderEventArgs(graphicsEngine));
}
public GameObject GameObject
{
get { return gameObject; }
set { gameObject = value; }
}
}
In my game object class, every component that is within the components list gets updated and rendered like so:
internal void Update(GameTime gameTime)
{
OnUpdate(this, new UpdateEventArgs(gameTime));
// All components being updated
components.ForEach(c => c.Update(gameTime));
}
With all of that being said, I've created a SpriteComponent class, which is meant to render a simple 2D sprite, based on the game objects position, it's overrided render method looks like this:
protected override void OnRender(object sender, RenderEventArgs e)
{
e.GraphicsEngine.DrawBitmap(bitmap, GameObject.Transform.Position);
base.OnRender(sender, e);
}
However for some reason this happens (This is the render method of the GameObject class):
internal void Render(GraphicsEngine graphicsEngine)
{
if (Enabled)
{
// Rendering a sprite component like this works fine
// Here I've created created a SpriteComponent inside the game object class to test it
if(sprite != null)
graphicsEngine.DrawBitmap(sprite.Bitmap, transform.Position);
OnRender(this, new RenderEventArgs(graphicsEngine));
// But rendering it using it's own method doesn't work
//sprite.Render(graphicsEngine);
// and this doesn't work properly either
// components.ForEach(c => c.Render(graphicsEngine));
}
}
And here is a picture of the result when I either iterate through the components list and render it, or render the sprite component by it's self:
I would look into you calling the OnRender. It is not best practice to call these event handlers. The has to be some other method you need to call which will invoke the OnRender.
Similar to OnDraw (Event handler) and Update (Invoke method)
I think you did override wrong method, As I see you have override the OnRender
While probably you calling Render method.
Try to make the Render method virtual and override it in child classes
I am building an XNA game and I have used this method to create new levels.
First I make an abstract class called Level:
public abstract class Level {
public abstract void Update(GameTime gameTime);
public abstract void Draw(SpriteBatch spriteBatch);
}
In the Game1 object, I declare a public static Level currentLevel;
and after initialising it (Like : currentLevel = new GameLevel()), call it's update and draw methods in the Game1.Update and Game1.Draw. When I want to change the level, I do Game1.currentLevel = new RandomLevel()
I load my textures for all my levels in Game1.LoadContent by calling the static Load method in my levels.
My actual levels look like this:
class GameLevel : Level {
Background sky = new Background(new Vector2(0, 0), -0.2f);
Background land = new Background(new Vector2(0, 0), -0.2f);
public static void Load()
{
...
}
public override void Update(GameTime gameTime)
{
...
}
public override void Draw(SpriteBatch spriteBatch)
{
...
}
}
My problem:
If my textures are static in the levels, I can load them in my static Load method which I call in the Game1.LoadContent. It works fine only if there are static textures(In fact, It works like that in my other levels). But in this level, I have a normal background objects. So I can't call sky.Load and land.Load in a static method. I want to create a lot of backgrounds with different textures. So how do I load the texture for my each of my background objects at the start of the GameLevel?
I was thinking of using a DrawableGameComponent and inherit it in GameLevel but I can't. Because I already inherited Level. I also got to know that GameComponents are deprecated.
I made a static ContentManager reference in Game1and assigned Game1's Content to it. Then I used that content to load the texture for the Background object in the constructor of the GameLevel object. I didn't think it will work before because I thought the contents are only loaded once per game. (As it was written in the comments of the LoadContent method. It worked anyway.
If there is a better way to do it, please do tell me.
I'm trying to implement screen management into my XNA game.
So far I've successfully implemented Example 3 from this link: http://www.xnadevelopment.com/tutorials/thestateofthings/thestateofthings.shtml
My current screen switch event is as follows:
public void GoToScreenOverview(object obj, EventArgs e)
{
screenStart = null;
screenOverview = new ScreenOverview(this, new EventHandler(GoToScreenOverview), globalVariables);
mCurrentScreen = screenOverview;
}
This moves from the (initial) screen "Start", and moves the game to the next screen "Overview". The equivalent reciprocal method GoToScreenStart does the opposite.
My question is this: How do I manage all the events?
Let's say I have 20 screens. Each screen Class will need 19 EventHandlers passed to it, which seems massively inefficient, and makes it a pain to add a new screen. Currently GoToScreenX type are events are in the Game1 class, but it seems to me that it would make more sense for all the events to be in the "BaseScreen" class, which each Screen inherits from.
If I were you, I would create a ScreenManager class. You could start with something like this:
public class ScreenManager
{
List<GameScreen> screens;
bool isinitialized = false;
public override void Initialize()
{
base.Initialize();
isinitialized = true;
}
protected override void LoadContent()
{
foreach (GameScreen screen in screens)
screen.LoadContent();
}
public void AddScreen(GameScreen screen)
{
screens.Add(screen);
if (isinitialized) screen.LoadContent();
}
// also create a removescreen
public void Draw(Gametime gametime)
{
foreach (GameScreen screen in screens)
{
screen.Draw(gametime);
}
}
// also create a similar method for Updating
}
You could make ScreenManager a DrawableGameComponent (recommended), or you could have the maingame call ScreenManager.Update() and ScreenManager.Draw() in it's respective methods. Finally, you'd have to create an abstract GameScreen class that has update and draw methods, and then have all your other Game Screens inherit from the GameScreen class. hopefully this will give you some ideas.