Jump to content

  • Log In with Google      Sign In   
  • Create Account


Coding a Point-Click Adventure Game Engine from Scratch


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
18 replies to this topic

#1 satsujin   Members   -  Reputation: 139

Like
0Likes
Like

Posted 09 November 2013 - 08:03 AM

Hello Everyone,

 

I haven't coded for a long time now(used to do it as a hobby when I was younger) but recently got the urge to create a point and click adventure game engine. I would like some info about getting articles and documentation on how to go about this.

 

My concept of a game engine is some form based IDE that lets you specify rooms, sprites, backgrounds, events. I assume the events would be scripted somehow but have no clue how to work on a scripting engine and how a custom script becomes compiled code. For the graphics I would use one of the free graphics libraries for Windows C# out there.

 

The functionality of the game I would want to create with my engine would be pretty limited at first. Just want 2 rooms, objects you can look at and add to your inventory and a defined screen region for walking.

 

Can anyone help? Thanks....



Sponsor:

#2 HappyCoder   Members   -  Reputation: 2241

Like
0Likes
Like

Posted 09 November 2013 - 05:07 PM

Ah, yes. A point and click adventure. That has been on my list of games I want to make for quite some time. Unfortunately it has never been at the top of that list.

Having not had experience making such a game I cannot give a lot of detail on how to make that but as for general game making my first piece of advice is to not make a game engine. Make a game. I have tried in the past to make a game engine and you end up burning out pretty quickly because you are trying to come up with solutions to hypothetical problems. Instead of having a specific need to be met by a game I was coming up with lots of different possible uses for a game engine and ended up coding up many different features that I never used. Mostly because the engine project died out. Later, I made a game and the engine kinda built itself around the game. While the game isn't perfect I at least have something working that can be considered finished and the core of the game is reusable. So I could use it to create more game projects.

So decide on a game you want to make and start to work on the game. My advice is to keep it as simple as you can. Don't try and add too many features. Focus on only what is necessary at first. Then work your way up from there. This means you will probably have to let go of the IDE style game maker for now. You will probably have to have your levels be created by writing json or xml files by hand. Having some sort of game editor with a WYSIWYG interface will have to come much later. Keep your focus on the game. Your tools should simplify making the game, not get in the way of it.

Also, if you really haven't make a 2D game before I would recommend starting with something simpler. Recreate a classic game such as pacman or tetris. Pick something that will challenge you but that you can complete. This will give a firm grasp on how to manipulate game objects on the screen and their interactions with each other.

If you already have some experience with 2D and think you are up to the challenge then I would start to study good oop practices such as cohesion and coupling. Look up component based game architecture.

#3 warnexus   Prime Members   -  Reputation: 1380

Like
0Likes
Like

Posted 09 November 2013 - 06:32 PM

Point and click should give you a hint that this application would be very "GUI-based": 

 

Get your feet wet with GUIs, 2D Graphics, Events(Interactions with the User with the mouse, keyboard or any button components) in the context of C#.

 

Agreed with the above post. I would say just go start implementing. Just start with one feature. Once that is done, move on to the next one.

 

Do not get blogged down with a huge design.



#4 satsujin   Members   -  Reputation: 139

Like
0Likes
Like

Posted 09 November 2013 - 10:03 PM

Ah yes. I have read a lot of the posts re Beginning Game Engines on the forum and I think all the ones I read have suggested starting with a game instead. Maybe I shall attempt to do just that. I assume the elements of the game would be hard coded? Objects for the graphics through XNA or OpenTK? Event handlers to respond to the interface? Maybe IronPython to incorporate some scripting? Or would that even be needed since this is hardcoded so I can write everything in c#?

 

I realize a lot of the code between an engine and a game are interchangeable but since I've already written graphics and input code for games I wanted to see how one would implement creation of a game through an interface. I know I can create a game in 2D. I've not made a point-and-click adventure but have made smaller scale 2D games like Snake, Breakout and a text adventure with graphics for the rooms. It was trying to understand how not to create a hardcoded version of a game but a scripted one thru an interface that appealed to me.

 

So, I ask again: Can anyone on this board please recommend books or websites with open source code for the kind of software I'm looking for? After all if you see from my first post I dont want my engine to implement sound, conversation trees, Z-buffering etc. at this stage The most complex part would be the event handler. I've even decided to delegate scripting(if i need it) to IronPython. I just don't understand how a form based interface would be used to create a game. Do we use use the variables from the form to generate a script that will be parsed? Or do we create a runtime handler that accesses the necessary variables and calls functions as needed? Or something else entirely?


Edited by satsujin, 09 November 2013 - 10:10 PM.


#5 wintertime   Members   -  Reputation: 1601

Like
3Likes
Like

Posted 10 November 2013 - 04:07 AM

The core of a point and click adventure should be simpler than a gui. Just draw a fullscreen picture of your background art; maybe just part of the texture that can be moved, if the texture is larger than the screen/window. Maybe add some extra sprites for changeable items.

Then wait for mouse click events and if one is inside a rectangle (or other shape) above some clickable thing make the game do something with it.

The hard part will be drawing all those art pieces for the game and writing intelligent messages telling a good story.



#6 Khaiy   Crossbones+   -  Reputation: 1342

Like
0Likes
Like

Posted 10 November 2013 - 11:54 AM

I agree with wintertime. A point and click adventure game shouldn't be any different than the casual "find the hidden object" games that have been so successful in the last few years.

 

This type of game is a picture on a screen, with various items in the picture producing some reaction when clicked. That's it. The "game" elements come in by connecting various pictures (the scenes of the game) to each other and a story to guide the player from one to the next. Plus some "triggers" to activate some objects in pictures or cause certain objects to have different effects.

 

I think you may be overthinking this. I don't know of any open source software, books, or guides tailored to making this kind of game. The golden era of adventure games was in a time when only professional studios would be making them. Today, they are minimally popular (though I still like them) and also not very complex as compared with other software. These two factors make it unlikely that there's much out there like what you're looking for, but the fact that they aren't so complicated also means that you shouldn't need them too much.

 

For an exercise, try this:

 

Have a screen with a blue background and a few red squares in it. Define events for the squares so that when they're clicked they change to a different color. Have one square cause a transition to a new screen, with a green background and blue squares and a similar click-and-change design.

 

Once you've done that, you've demonstrated all the basic skills you need to make this kind of game. Seriously. The rest (from a programming perspective) is basic game loop kind of stuff, which you say you've done so that shouldn't be an issue. The rest (from a polished game perspective) is better art and a story that determines the screens a player can visit, and under what circumstances.



#7 satsujin   Members   -  Reputation: 139

Like
0Likes
Like

Posted 10 November 2013 - 11:44 PM

Fine. I won't post again until I work out Khaiy's suggestion. My problem is that C# seems to have changed a bit since I last used it several years back.  I am currently reading C# Game Programming for Serious Game Creation by Schuller to get back on track so I wont post for a while. Schuller is using elements like delegates for game loops. I'm currently reading about them online. Seem to be some way to pass functions as arguments.

 

And I've pretty much scrapped the engine idea until I can first recreate my two room goal as a game first. 



#8 satsujin   Members   -  Reputation: 139

Like
0Likes
Like

Posted 11 November 2013 - 12:48 PM

This is my first Windows game so I'm somewhat confused. I'm using xna 4.0. I can create clickable Rectangle objects that change color but am not sure how to create separate screens. Do I define each screen as a GameComponent with its individual Draw and Update logic? If I want to exit one screen and go to another is there some event I can create like ChangeScreen where the current screen is removed as a Component and replaced with the new screen (maybe in GameComponentCollection)? 


Edited by satsujin, 11 November 2013 - 12:49 PM.


#9 Khaiy   Crossbones+   -  Reputation: 1342

Like
0Likes
Like

Posted 11 November 2013 - 05:00 PM


Do I define each screen as a GameComponent with its individual Draw and Update logic?

 

You can, but you don't need to have screen inherit from GameComponent just for this functionality. It's a valid approach, but make sure that you know why you want Screen to inherit from GameComponent. (I'm mentioning this because a lot of people do this sort of thing only because they saw something in a tutorial, which is a bad way to practice using inheritance).

 


If I want to exit one screen and go to another is there some event I can create like ChangeScreen where the current screen is removed as a Component and replaced with the new screen (maybe in GameComponentCollection)? 

 

That would work. However, I would suggest doing something that is a little bit simpler and clearer than relying on under-the-hood XNA stuff. If your Game class has a Screen field called currentScreen, you can assign whatever screen should be displayed to that variable and then, in your Draw method, call something like currentScreen.Draw(). It'll be easier to define your own events, event handlers, and keep your program flow straight if all of the objects and methods you're working with are easy to look at and review at need.



#10 satsujin   Members   -  Reputation: 139

Like
0Likes
Like

Posted 11 November 2013 - 11:44 PM

Here is the code I have in Game1.cs:

namespace Reflection
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        DrawableGameComponent room;
        GameComponentCollection complist;
        GameTime gt;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            room = new Level1(this);
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

        }

        protected override void UnloadContent()
        {
        }

        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            base.Update(gameTime);
            
        }

        protected override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);
        }

        public void ChangeScreen(DrawableGameComponent curroom, Type type)
        {
            room = (DrawableGameComponent)Activator.CreateInstance(type,this);
            this.Components.Remove(curroom);
            this.Components.Add(room);
            //room.Draw(gt);
        }
    }
}

Then, the modified DrawableGameComponent class in Level1.cs:

   public class Level1 : Microsoft.Xna.Framework.DrawableGameComponent
    {
        Game1 game;
        public Level1(Game1 game): base(game)
        {
            this.game = game;
        }

       public override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here
            game.ChangeScreen(this, Type.GetType("Reflection.Level2"));
            base.Update(gameTime);
        }

And the screen color changing code in DrawableGameComponet class Level2.cs:

       public override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Red);
            base.Draw(gameTime);
        }

I want this code to initially load the room Level1 class in Game1 which then immediately changes the screen  to Level2 . However, it only seems to run the Update and Draw loops in Game1. I want the DrawableGameComponent room variable to load the component specified in it and then loop that component's Update and Draw functions until changeScreen is called for new component(room) again. Each time only one room should be displayed but each room should be able to store multiple sub-components of sprites etc. That way you could set a current room to loop with its eventhandlers and sprites until a new room need to be load after exiting the current one.


Edited by satsujin, 12 November 2013 - 04:33 AM.


#11 satsujin   Members   -  Reputation: 139

Like
0Likes
Like

Posted 12 November 2013 - 04:38 AM

I added room to Game.Components before Game1's base.Initialize and now it seems to be working but do you think the definition of the changescreen function will lead to memory leaks? Or is there a better way to do it? Thanks for all your help and suggestion so far in any case. smile.png



#12 Khaiy   Crossbones+   -  Reputation: 1342

Like
0Likes
Like

Posted 12 November 2013 - 07:41 PM


do you think the definition of the changescreen function will lead to memory leaks?

 

I wouldn't worry about it. C# manages memory on its own with the garbage collector, and while memory leaks can happen I think that you'll be plenty safe. A bigger problem is that when there are no more references to an object it becomes eligible for garbage collection, which may not be what you want for something like a Room in a game (and especially one that might change as the player interacts with it).

 

 

 


Or is there a better way to do it?

 

This is something that's just about always true of any code. Programming is a pragmatic activity in the sense that if your code works as intended it's right enough. But in this case, I suggest the following as broad design approaches (take or leave these, as you like):

 

1. I don't like having each Room class (like Level1) as a direct descendant of DrawableGameComponent. Even though you will need to draw each Room, you don't need to use inheritance to make it happen. It can also force you, as it did in the code you posted above, to do some weird casting and makes for very unintuitive and hard to read/maintain code. You can manually call currentRoom.Draw the Game.Update method. If you really want to keep the inheritance from DrawableGameComponent, you can have an intermediate base class (Room, maybe) from which all individual rooms will inherit.

 

2. The ChangeScreen function seems overly engineered to me. In line with the above, I would prefer it to take a Room parameter rather than a DrawableGameComponent for clarity alone. I'm also not totally sure what you're planning to get by creating instances of Rooms on-demand this way or why you are using Type.GetType to identify the next room to be created. It's the kind of thing that's maybe a little hackish but gets the job done in a small demo-style project but will cause you headaches in the future, unless you have some specific reason for having set things up this way.

 

3. The function calls are well into spaghetti code territory. This too is something that works fine for a small test project but is a nightmare later. Game creates a Level1 object -> Game.Update itself calls Level1.Update (which is fine and normal) -> Level1.Update calls Game.ChangeScreen (this is less fine). Method calls shouldn't be reaching back and forth between distinct objects this way-- you're overly coupled and for no benefit. In general, you want calls to be as one-way as possible in terms of one class containing another as a field.

 

4. You may have a particular reason for on-demand generation of Rooms, but I'll urge you to consider an alternative approach. Because a room's contents, triggers, and other components might change as the game progresses creating previously visited rooms via their constructors can be a problem. The player removes an object from a room, for instance, so you don't want the object to be there again when the player backtracks through the same room. You can avoid this with fancy polymorphic constructors, but you might also have something like a container of Room objects which contains an instance of every room in the game and then access and update them as needed. That way you only have to deal with varying room states when saving and loading a game.

 

I think that the best general advice I can give is to try and think of your program as a set of discrete modules which plug into each other only and exactly as needed. It can be hard to see in a small test project like this one, because Game has so many things that are within its area of responsibility that it's easy to have Game do everything and only use other objects as data containers.


Edited by Khaiy, 12 November 2013 - 07:44 PM.


#13 satsujin   Members   -  Reputation: 139

Like
0Likes
Like

Posted 13 November 2013 - 02:19 AM

A bigger problem is that when there are no more references to an object it becomes eligible for garbage collection, which may not be what you want for something like a Room in a game (and especially one that might change as the player interacts with it).

 
I am hoping to always have a reference to Room as I will use to it to define what should be drawn on the screen(main menus,game rooms) at any given time until the game quits.
 
I agree with point number 1. I will create room as a separate class. I didn't think to call room.Draw(and I guess also room.Update) from Game.Update.
 

2.I'm also not totally sure what you're planning to get by creating instances of Rooms on-demand this way or why you are using Type.GetType to identify the next room to be created.

I'm creating Rooms this way since, for the actual game, the Room.Update function will use event handlers to check if the user has clicked on a door sprite and change room in Game based on that. I have never used Activator.CreateInstance before and though it has a slew of overloaded constructors, the one I'm using requires a Type parameter. If I'm missing something please let me know.
 

3. The function calls are well into spaghetti code territory. This too is something that works fine for a small test project but is a nightmare later. Game creates a Level1 object -> Game.Update itself calls Level1.Update (which is fine and normal) -> Level1.Update calls Game.ChangeScreen (this is less fine). Method calls shouldn't be reaching back and forth between distinct objects this way-- you're overly coupled and for no benefit. In general, you want calls to be as one-way as possible in terms of one class containing another as a field.

Where is Game.Update calling Level1.Update? I guess if I create Room as a separate class I should also call its Update function from Game.Update. Also, are you saying I should have changeScreen in the Room object? This will certainly change to the new room but would it be good practice to dispose the current Room from inside itself? I am passing a reference to the Game object with the variable game but would the following be ok if I am calling changeScreen from say inside Room.Level1?
- game.room = new Level2(game);
- this.Dispose();
 

4. You may have a particular reason for on-demand generation of Rooms, but I'll urge you to consider an alternative approach. Because a room's contents, triggers, and other components might change as the game progresses creating previously visited rooms via their constructors can be a problem. The player removes an object from a room, for instance, so you don't want the object to be there again when the player backtracks through the same room. You can avoid this with fancy polymorphic constructors, but you might also have something like a container of Room objects which contains an instance of every room in the game and then access and update them as needed. That way you only have to deal with varying room states when saving and loading a game.

I didn't think about this so thanks. I guess I will have to create some kind of List/Dictionary in Game that keeps track of items/sprites that have been removed from a room and generate/draw/handle those items in the respective Room based on some status field in the list/dictionary. Possibly one like Inventory for items and another for removed sprites.

As you can see, I have never created this type of game before and none in Windows so I appreciate your help. In fact, the only Windows 'game' I created before this was a program with a Texture2D appearing at a new random position every second in the window and a score and image change each time it was clicked.

Edited by satsujin, 13 November 2013 - 07:02 AM.


#14 satsujin   Members   -  Reputation: 139

Like
0Likes
Like

Posted 13 November 2013 - 04:14 AM

I think I should create a ScreenManager for the game since it is essentially a change to different screens based on user input. Having read only the basics of XNA game programming online through piece-by-piece tutorials I thought I should read Microsoft® XNA® Game Studio 4.0: Learn Programming Now! by Rob Miles. Thought it might be a good stepping stone. Would you recommend it? It seems pretty basic(what with trying to teach C# for the uninitiated also) but may be a good way to get a handle on XNA game architecture.

If there are other books you think might be better, please do let me know. It's a pity that most of the info out there either online or in books seems to focus on 3d games or side scrollers. Point-n-click games seem to have definitely gone out of style and they were such fun too.

Edited by satsujin, 13 November 2013 - 07:04 AM.


#15 Khaiy   Crossbones+   -  Reputation: 1342

Like
0Likes
Like

Posted 13 November 2013 - 06:03 PM


I am hoping to always have a reference to Room as I will use to it to define what should be drawn on the screen(main menus,game rooms) at any given time until the game quits.

 

I think I may have been unclear. When I say reference, I mean an appropriately typed variable which points to a memory address allocated when an object is instantiated. In the code you showed above, you have a field "room" which has Level1 assigned to it. As soon as your room variable switches to Level2 (in your ChangeScreen method), there are no more references pointing to the memory address where Level1 is. Not only does this mean that you can't access that object again (with no reference to that memory address, it's gone for all intents and purposes) but that object is also eligible for garbage collection (meaning that even if you knew the address, the data stored there could vanish at any time during execution).

 

There's no hoping on this one. Your design needs an explicit approach for accessing instances of variables whether or not they're drawn on-screen at any given moment. If you allow the active references to expire then your design will need an explicit approach for creating new instances correctly as needed.

 

 

 


I'm creating Rooms this way since, for the actual game, the Room.Update function will use event handlers to check if the user has clicked on a door sprite and change room in Game based on that. I have never used Activator.CreateInstance before and though it has a slew of overloaded constructors, the one I'm using requires a Type parameter. If I'm missing something please let me know.

 

It's not that you're missing anything so much as you're adopting a complex approach and I'm not sure that you are using (or are planning to use) that complexity for anything. If this is the case, then you should at least consider a simpler approach instead.

 

As for events, you define those in the class definition just like the fields, constructors, and methods. You then define methods and subscribe them to the event or events you want, and the methods will execute each time the event is raised. You don't need to fiddle with the Activator class at all, and if your plan is to use it only as a static factory class you may want to roll your own instead. There is no reason that you need Activator or any other class just to use events.

 

 

 


Where is Game.Update calling Level1.Update? I guess if I create Room as a separate class I should also call its Update function from Game.Update. Also, are you saying I should have changeScreen in the Room object? This will certainly change to the new room but would it be good practice to dispose the current Room from inside itself? I am passing a reference to the Game object with the variable game but would the following be ok if I am calling changeScreen from say inside Room.Level1?
- game.room = new Level2(game);
- this.Dispose();

 

My XNA is pretty rusty, but if I remember correctly when Game.Update runs it calls the Update methods of all game components. That's why you were seeing the effect of the Level1 method even though you weren't specifically calling any Level1 methods anywhere in the game loop. Conceptually you should want all active game objects (the ones that will be updating each cycle) to update at the same time, and since XNA already provides an Update method for the game loop that's a good place to do it.

 

I do not recommend putting the ChangeScreen method in Room. Your instinct was (and is) correct: doing so would be a bad and extremely messy idea. As your sample is laid out, Game is indeed the place where ChangeScreen should be. As your code base changes you should think of which class is "responsible" for managing screens. That may be Game, or it may be some other class.

 

But invoking Game.ChangeScreen from within a Room object is pretty dicey. My point was that any given Room object shouldn't be doing something like changing which screen is active in the Game object; as your code sample is laid out above this really should be handled by Game. A screen is changed, it does not do any changing of screens. That's a big break in encapsulation and produces tighter coupling than you need and for no benefit.

 

 

 


I didn't think about this so thanks. I guess I will have to create some kind of List/Dictionary in Game that keeps track of items/sprites that have been removed from a room and generate/draw/handle those items in the respective Room based on some status field in the list/dictionary. Possibly one like Inventory for items and another for removed sprites.

 

There are lots of ways you can do it, and it's a major design decision. It might help to rough out on paper a couple of sample rooms which have the kinds of features that you want the player to be able to interact with (like a take-able item, a flip-able switch, a clue that only appears after some plot event has been triggered) and think about different ways you might represent them as fields of that Room.

 

I'll suggest using an enum to indicate what kind of object an object is, and to indicate its state (present/taken, on/off, active/inactive). If you're using a list or dictionary you can have a generic Draw method that only renders the objects marked as present (or whatever) and not have to fuss with multiple containers with dynamic contents. But think about it before settling on an approach. Whatever design you choose will still need to have the implementation details figured out and will almost certainly need to be refactored as your project progresses.

 

 

 


I think I should create a ScreenManager for the game since it is essentially a change to different screens based on user input. Having read only the basics of XNA game programming online through piece-by-piece tutorials I thought I should read Microsoft® XNA® Game Studio 4.0: Learn Programming Now! by Rob Miles. Thought it might be a good stepping stone. Would you recommend it? It seems pretty basic(what with trying to teach C# for the uninitiated also) but may be a good way to get a handle on XNA game architecture.

If there are other books you think might be better, please do let me know. It's a pity that most of the info out there either online or in books seems to focus on 3d games or side scrollers. Point-n-click games seem to have definitely gone out of style and they were such fun too.

 

I don't really like Manager classes for most purposes, and for something like screens and screen changing you don't need one. But there's no reason you can't or shouldn't use one if you want, especially if that makes your program design clearer or more intuitive for you.

 

I haven't read the book so I can't give you an opinion on how good it is or isn't. If you want to use XNA in the future then it isn't a bad idea to get some material that will help you learn how the guts of it work. For now though, I think that it might be more of a distraction than a help to you. You may end up spending a lot of time reading and memorizing and not so much time programming. Actually coding is by far the best way to improve, far more than reading books, and obviously if you aren't coding you won't make much progress on your game.

 

The same goes for other books, particularly for the kind of project you're working on now. A key point to remember is that a point-and-click adventure game isn't some totally different animal than a 2D-side scroller or 3D-whatever. Point-and-click is a very simple case of applying the same general ideas about putting pictures on the screen and responding to input, and it's not that the others have information that's totally different so much as that they're focused on techniques you don't need for this.

 

Like I mentioned before, nearly all of the complexity in your current project will come from getting your hands dirty with program design and planning and producing content. By putting a picture on the screen and having it respond when a part of it is clicked you've already got the capability to do what you want.


Edited by Khaiy, 13 November 2013 - 06:11 PM.


#16 satsujin   Members   -  Reputation: 139

Like
0Likes
Like

Posted 14 November 2013 - 12:37 PM

Okay I'm back already. I was trying to implement a ScreenManager class so I tried to load a texture from another class but I get a ContentLoad exeception: GraphicsDevice component not found. I am trying to load the texture in the LoadContent of the class. It wont work there but it does work if I put the Content.Load in the Update method of the class. However, thats probably not a good place to load the texture. I also realize it's not good practice to have all these members as public but that was just a temporary fix until I created accessors for them. Here is the code, hope you can help. 

 

MainMenu.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace RoomGame
{
    class MainMenu : Screen
    {
        GameController gameController;
        Texture2D texture;
        Vector2 position;

        public MainMenu(GameController gc)
        {
            this.gameController = gc;
            this.isUpdating = true;
            this.isDrawn = true;
            //this.graphics = this.gameController.game.graphics;
        }

        public override void LoadContent()
        {
            texture = this.gameController.game.Content.Load<Texture2D>("Textures/Start");
            
        }

        public override void Update(GameTime gameTime)
        {
            //texture = this.gameController.content.Load<Texture2D>("Textures/Start");
            position = new Vector2(100, 100);
        }

        public override void Draw(GameTime gameTime,SpriteBatch sb)
        {
            sb.Draw(texture, position, Color.White);
        }
    }
}

Screen.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace RoomGame
{
    public class Screen
    {
        public ScreenController screenController;
        public bool isUpdating=true;
        public bool isDrawn=true;
        public GraphicsDeviceManager graphics;

        public virtual void Initialize()
        { }

        public virtual void LoadContent()
        { }

        public virtual void Update(GameTime gameTime)
        { }

        public virtual void Draw(GameTime gameTime,SpriteBatch sb)
        { }
    }
}

ScreenController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace RoomGame
{
    
    public class ScreenController
    {
        List<Screen> screens = new List<Screen>();
        GameController gameController;
        SpriteBatch spriteBatch;

        public ScreenController(GameController gc)
        {
            this.gameController = gc;
        }

        public void Initialize()
        {
            
            spriteBatch = new SpriteBatch(this.gameController.GraphicsDevice);
        }

        public void LoadContent()
        {


        }

        public void Update(GameTime gameTime)
        {
            foreach (Screen screen in screens)
            {
                if (screen.isUpdating)
                    screen.Update(gameTime);
            }
        }

        public void Draw(GameTime gameTime)
        {
            foreach (Screen screen in screens)
            {
                if (screen.isDrawn)
                {
                    spriteBatch.Begin();
                    screen.Draw(gameTime,spriteBatch);
                    spriteBatch.End();
                }
            }
        }

        public void AddScreen(Screen screen)
        {
            if (!screens.Contains(screen))
            {
                screens.Add(screen);
                screen.LoadContent();
            }
        }


        

    }
}

GameController.cs-> I realize MainMenu should be referenced in a variable so that it can be called on a ScreenCollections.Remove function which is not yet implemented

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;

namespace RoomGame
{
    public class GameController : DrawableGameComponent
    {
        public Game game;
        public ContentManager content;
        public ScreenController screenController;
        public GameController(Game g,ContentManager c)
            : base(g)
        {
            game = g;
            content = c;
            screenController = new ScreenController(this);
            screenController.AddScreen(new MainMenu(this));
        }

        public override void Initialize()
        {
            base.Initialize();
            screenController.Initialize();
        }

        protected override void LoadContent()
        {
            screenController.LoadContent();
            base.LoadContent();
        }

        protected override void UnloadContent()
        {
            base.UnloadContent();
        }

        public override void Update(GameTime gameTime)
        {
            screenController.Update(gameTime);
            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);
            screenController.Draw(gameTime);
        }
    }
}

Game1.cs

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 RoomGame
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        public GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        GameController gameController;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            gameController = new GameController(this,this.Content);
            this.Components.Add(gameController);
        }

    }
}

Edited by satsujin, 14 November 2013 - 01:01 PM.


#17 Khaiy   Crossbones+   -  Reputation: 1342

Like
0Likes
Like

Posted 14 November 2013 - 08:50 PM


I also realize it's not good practice to have all these members as public but that was just a temporary fix until I created accessors for them.

 

Giving fields accessors by default isn't much better than leaving them public. Don't worry about it for now.

 


I was trying to implement a ScreenManager class so I tried to load a texture from another class but I get a ContentLoad exeception: GraphicsDevice component not found. I am trying to load the texture in the LoadContent of the class. It wont work there but it does work if I put the Content.Load in the Update method of the class. However, thats probably not a good place to load the texture

 

I'd need more information to say for sure, but from my hazy memory of XNA I'll suggest you're calling MainMenu.LoadContent (which is in turn calling Content.Load) before you're creating the instance of GraphicsDeviceManager. That would also explain why it works when you put the Content.Load call in MainMenu.Update, because that would almost certainly be happening after the GraphicsDeviceManager instance is created. But I don't see where these things are happening in the code you posted, so I'm not 100% confident about it.

 

I notice that you have a lot of LoadContent methods sprinkled around in your classes. There's nothing wrong with that, but it seems wrong to me to be calling Content.Load from them. Content.Load loads an image into memory and is kind of resource-heavy. It's generally done once, when the game starts up, and loads something like a whole sprite sheet or sheets at that time. Other classes that need specific images from the sprite sheet assign some shape from the sheet to a variable (like a Texture2D), and that's the kind of thing I would expect to see in a class' LoadContent method. This is another "if it works, it's right" kind of thing, but it's something to keep in mind going forward.



#18 satsujin   Members   -  Reputation: 139

Like
0Likes
Like

Posted 16 November 2013 - 12:11 AM

Hey Khaiy, sorry for not replying yesterday. To be honest, I kinda forgot.

I found the  error in my code, I was basically calling AddScreen in gameController's constructor and not the LoadContent method. I've currently got a program that starts by showing a screen with a texture that you can click on for a event and when you press 'P' in that screen it opens up a second screen, that shows a new texture but also still shows the previous screen but makes it unupdateable. This can be the baby steps to an element of of an interface where you can open an options menu on top of your current screen. I also defined the textures in a separate class called MyTexture that loads the texture, draws the texture, and return the screen Rectangle representing its position. This could be the beginning a a stationary sprite class.

 

My next goal is to create an isClicked bool method in MyTexture that will tell me if the texture has been clicked so I dont have to code the event in Update loop. I also want this method to only return true if a non-transparent part of the texture has been clicked. Maybe the MyTexture class will use delegates so I wont have to hardcode what happens when clicked. Not too clear on that aspect.

 

For my first steps into animation, I will want to load a spritesheet that first animates the texture at a fixed location and then back and forth along a horizontal/vertical line(to implement the effect of a e.g. non-player game character walking back and forth at a certain area).I have yet to use the GameTime class but from what I've understood in tutorials it is important for smooth animation. I am not sure how to go about encapsulating it though. Show it be in draw or Update? Should the code be in ScreenController or the Screen specific derived class?

 

Once I have a reasonable amount in animation classes, I will move on to the Player class which should incorporate those animations and also access to a the bounding box class for walkable regions in the screen defined by an n-sided concave/convex polygon.

 

Let me know if you think I am going too slow/fast with these goals in mind. I am doing this purely as an educational experience since it is something that interests me. I have no plans to release any game I make, this is just a hobby. My family has in fact found out I've come back to programming and is deadset against it because I have a medical problem that gives me seizures after I experience even minor stress. And, as I'm sure you know, debugging can be stressful. I already had one seizure a few days ago after being free of them for several months. Still, I love this too much to stop.

 

If you don't mind I'd like an easier way to communicate with you than this forum. Our timing seems to be way off. You reply while I'm sleeping and vice versa. You can reach me at anoopmalex AT gmail.com. Maybe we can chat on googleTalk. Ofcourse, I'll understand if you have better things to do.



#19 Khaiy   Crossbones+   -  Reputation: 1342

Like
0Likes
Like

Posted 24 November 2013 - 06:11 PM

Hi satsujin,

 

Sorry I didn't get back to this post earlier. I got slammed with real life stuff and have had about ten minutes to devote to something other than work/school over the last week.

 

For animation I think that you're conflating a couple of things. The standard way, as far as I'm aware, of animating stuff off of a sprite sheet is to have a sequence of pictures for a given animation. A game object should have a variable field like "currentFrame" to indicate what should be drawn onscreen, and when the object's Draw() method is called it renders currentFrame to the screen. For a sprite sheet, the current sprite image is a portion of the sprite sheet, in SFML generally a Rectangle which "cuts out" the picture to be drawn.

 

When an animation is triggered (like, the jump button is pushed) the currentFrame is updated to "cut out" the next image in the sequence over and over again until the animation is over. All of the rendering to the screen is done by the Draw() method. The only thing that is changing is what portion of the sprite sheet is assigned to the currentFrame variable. The key point to understand is that an animation is just a defined set of frames, usually with a particular frame (called a key frame) which is "neutral" between animations, for smooth transitions between different animations. Think of Mega Man standing still between running, jumping, dashing, etc., and you'll have the idea.

 

Positioning the sprite onscreen is totally separate from the animation. The sprite (say Mega Man, for example) should always have its position on the screen stored as a field. When the player pushes "right" on the input device, if moving to the right is valid then the "RunRight" (or whatever you want to call it) animation sequence starts and continuously updates the current frame to be drawn on the screen. Separately, but simultaneously, the position of Mega Man moves to the right.

 

Anything which changes the state of an entity in the game should probably be handled in the Update() method, and Draw() should be a pretty straightforward, un-fancy method which does just what it says.

 

The forums are the best way to reach me, given that a 24 hour turnaround time is the fastest I can realistically do. If you don't want to post back and forth feel free to send me a private message, although you'll get a better set of perspectives if you keep posting instead.






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS