• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
  • entries
    20
  • comments
    11
  • views
    24507

Toasty Update #1

Sign in to follow this  
Followers 0
CRYP7IK

993 views

The first update is here, and it has a few things in it that I would like to show off. This might be very long.

So first thing's first, to start using the game engine you can create a GameSystem object like so:Toasty::GameSystem* system = new Toasty::GameSystem();
Now you don't have to use a GameSystem but it is useful in doing these things:

Automatic Unique ID Assignment



This makes use of the template class UniqueIDHandler, which allows any type with a ++ operator to be used. You just call GetNextID and RemoveID(T id) to use it. Anything dealing with this should use the same type, or be able to implicitly convert from it. I use unsigned 32-bit ints in the GameSystem at the moment, so the technical maximum number of entities are 4, 294, 967, 295 (Should be enough). I am still toying around with whether or not the GameSystem should allow selection of the type to use, maybe your game only needs 256 entities in it at any one time?

Automatic Assignment of a Valid MessageSystem* to Entities



Entities are basically a simple container of an ID (of type T, which should match the UniqueIDHandler type that you are using) and position, scale, rotation and a possibly non-unique name. They require a MessageSystem* so it can notify any listeners of position, scale, rotation and name changes.


MessageSystem Creation and Passing to Systems



The way systems and components communicate is via the message system, to facilitate an easy way to make sure systems match the same MessageSystem the GameSystem creates it's own and passes it to a system when it is added, if a System wants it, it can keep it and listen for messages it wants. Now keep in mind performance is not currently the goal, features are so at the moment the MessageSystem will immediately deliver the message to all listeners which thrashes the cache. I would like to perform this for a maximum amount of time at the end of a frame (Before scene unloading \ loading or entity destruction) instead.

Automatic Timing



Using the default timer (std::chrono aka Toasty::ChronoTimer) the GameSystem is able to easily time each frame and calculate Dt and FPS. You are able to extend from BaseTimer and create your own timer for use within the GameSystem. Also making use of the timer, you can get an average fps or the exact last fps!

Scene Loading and Unloading



The GameSystem allows safe Scene loading and unloading into and from systems. It will unload all scenes requiring to be unloaded at the end of the frame and then load any scenes that need to be loaded in. I am toying around with a co-routine style loading of scenes with it continuing onto the next frame if a certain amount of time is taken while loading it. Unloading a scene will not delete the memory.

System Updating



If you call this function:system->Run();
All systems added to the GameSystem will be updated in reverse order that you added them as well as timing them (This is an infinite loop). If a system returns false in it's update, that means it wants the whole GameSystem to shutdown. Run doesn't have to be used, Tick can be used to perform a single frame. I plan on doing research into multi-threading because I would like to be able to mark systems as multi-threaded and have the GameSystem perform their updates on other threads. Being able to change order of systems is something I might add as well.


Entity Lookup



The gamesystem obviously provides an easy way to get either a group of entities by name (Names aren't unique remember!) or a single entity by ID out of all entities added to it.

Attached component lookup



Being able to find other components in the GameSystem is a must, so you can easily get a vector of all components added to an Entity pointer or ID. On top of that you can also get a specific system by name and get any components attached to your entity that way (some systems may allow multiple components attached to it). If you get it via a vector you will have to dynamic_cast it until you find the one you want.

Plugin Loading



the point of Toasty is to be ultra modular. No graphics, physics or anything is included with it but are done in other modules which you can either link to statically, dynamically or at load them at runtime (Which this handles). Actually loading a plugin at run time instead of linking to it makes it kind of difficult to actually use the things it loads in, but at the moment you could write a Serialiser and then in some text editor write out a file that would load the plugin and use components from it and attach them to entities, if you then wanted to do something in game logic you might need some kind of scripting language or other way to glue it together.

You could do that all yourself manually if you liked though, as the GameSystem class is just a wrapper around a whole bunch of useful classes in Toasty.

Continuing on you would call:system->Run();
Which would perform the main game loop, although seeing as there isn't any scenes, entities or any other systems nothing will happen. Lets fix that:Toasty::GameSystem* system = new Toasty::GameSystem();Toasty::BehaviourSystem* behaviourSystem = new Toasty::BehaviourSystem(system);system->AddSystem(behaviourSystem, true);
So, the behaviour system just allows one to add a behaviour to a Entity similar to Unity, but we need a behaviour so let's make one!#include "BehaviourComponent.h"#include "ConsoleLogger.h"#include class Test: public Toasty::BehaviourComponent{public: Test(Toasty::GameSystem* system, Toasty::Entity* ent) : BehaviourComponent(system, ent) { } virtual ~Test() { } virtual void Initialise() { Toasty::LogInfoPositive(entityAttachedTo->GetName()); } virtual void Shutdown() { } virtual void Update() { Toasty::LogInfo("FPS: " + std::to_string(gameSystem->GetFPS())); }};
and this just logs out the FPS every update of the 'script' and the name of the entity it is attached to, but to actually use it we have to do this: // Create game system and set it up with a timer. // It automatically gets set with the default ChronoTimer. Toasty::GameSystem* system = new Toasty::GameSystem(); //Create the systems we are going to use. Then add them to the gamesystem we are using. Toasty::BehaviourSystem* behaviourSystem = new Toasty::BehaviourSystem(system); system->AddSystem(behaviourSystem, true); // Create an entity to attach a behaviour component to Toasty::Entity* myFirstEntity = new Toasty::Entity(); // Give the Entity the message system and a UniqueID. gameSystem->AddEntity(myFirstEntity); // Add the test 'script' to the Entity. Test* test = new Test(system, myFirstEntity); behaviourSystem->AddEntity(myFirstEntity, test); // Run the system! system->Run(); // Cleanup delete system; delete test; delete myFirstEntity; delete behaviourSystem;
Notice the cleanup requires you to delete all memory you created? That's by design, at least for the moment I am still contemplating whether or not to use smart pointers to handle memory.

What follows are images of a Windows, Linux and Mac OSX machine (Thankyou cmake!) running this test with an image of their specs and interesting data about the compiled forms on each one.

Windows



systemspecs.PNG



FirstFrame.PNG

Followed by this on the Nth frame:

nthFrame.PNG



ToastyGameSystem DLL filesize: 68 Kilobytes


ToastyGameSystem Lib filesize: 72 Kilobytes


ToastySystemTest.exe filesize: 42 Kilobytes


Linux



linuxstuff.png



libToastyGameSystem.so filesize: 103 Kilobytes


ToastySystemTest binary: 19 Kilobytes



Mac OSX



MacSpecs.png

macstuff.png



libToastyGameSystem.dylib filesize: 114 kilobytes


ToastySystemTest binary filesize: 25 kilobytes



What's interesting is the performance of the windows computer seems the worst (It doesn't even hit 1k fps!!) even though it has the better specs! Maybe you guys can guess as to why that is...I'll probably give you the answer in the comments later on. On the next post I'll be talking about the coolness of scenes, how they can be used, the simple math side of things, extending the system and things I still need to do before ToastyGameSystem is done!


0
Sign in to follow this  
Followers 0


2 Comments


Hi there.  Good to see another Entity/Component framework in the pipeline!  I have a few comments I thought of while reading I wanted to share that might provide some improvements.

 

It might be a little name confusion that you have your whole Framework being called a system (GameSystem in this case) while a "system" is a defined and integral part of your framework already.  It's a pretty minor thing, but just something I thought about.

 

It seems you could reduce some redundancy when creating systems (not GameSystem) considering, currently, you have to pass the GameSystem to the system's constructor, but you also have to call AddSystem().  I would think AddSystem() could pass the GameSystem being used to the system (lots of "systems" heh).

 

Similar thing with Components, you pass the entity and system to the Component's Constructor, then call GameSystem::AddEntity() and pass both the entity and component. I think you should be able to emove so many references to systems and entity.

 

BTW, when adding multiple components, do you continually call AddEntity() with the entity and Component?  I would think you should call AddComponent() to the entity (or, the reverse, AddEntity() to the Component), and only once call the GameSystem::AddEntity() with the give entity.

 

You might want to provide a GameSystem::Update() as well as a ::Run() if some user would want to do things outside the Toasty Game Engine.

 

Also, you might want to provide built in methods of creating objects in your system instead of relying on new and delete (ex: GameSystem::CreateEntity(), which returns a entity, and GameSystem::DeleteEntity().  It may even use smart pointer under the cover).

 

 

Just a few thoughts I had while reading this.  I'd love to see how you create your systems as well.  Good luck, and keep it up!

0

Share this comment


Link to comment

Hey BeerNutts!

 

I always love comments!

 

Yeah that is a good point, It's technically an entitycontainer, systemcontainer with helpful functionality and I'm not quite sure what to call it, any ideas? I am not so sure about calling it Framework or Engine...

 

I actually want to remove any dependency on GameSystem, it's more of a helper class (similar to Root in Ogre) which you don't have to use but makes things a lot easier on you. Not all systems will have to be the same, that's why I keep dependency injection in the constructor, if that's what the system needs then it needs it!

 

 Same as above with this, each component should have it's dependencies in the constructor, if that happens to be a GameSystem then so be it (Although I think if it requires a GameSystem something is wrong).

 

So you would only add an entity once to the GameSystem then you would add it to any other system you want, like:

// Create an entity to attach a behaviour component to, 0 for the first param means 
// that we don't want to use the message system.
Toasty::Entity* myFirstEntity = new Toasty::Entity();

// Create a new behaviour that we made (print entity name and FPS).
DebugInfoTest* test = new DebugInfoTest(system, myFirstEntity);

// Add the behaviour to the entity.
behaviourSystem->AddEntity(myFirstEntity, test);

// Create a render component
2DRenderComponent* renderTest = new 2DRenderComponent("image.png");

// Add render component to the entity.
myRenderSystem->AddEntity(myFirstEntity, renderTest);

Because each system is (or should be) independant you must call AddEntity with the entity and component you want on each system you want it in. Entities do not know anything about the components that are 'attached' to it, although adding the entity to a component is a decent idea, I have it that way for fast component lookup if you have the entity pointer.

 

I may do this, not sure at the moment as the GameSystem should be something you can use easily, if you need more control you can just use the same classes that GameSystem uses (EntityContainer, SystemContainer, SceneContainer, UniqueIDHandler, MessageSystem) and customise the way it all works as much as you need.

 

I already have a DestroyEntity (It doesn't destroy the memory, but it removes all the components from all the systems in the GameSystem at the end of the current frame) and I'm thinking of overriding AddEntity to have no arguments and just return an Entity pointer.

 

Your thoughts were intriguing and have given me much to think about! I'm in the middle of writing the next update now so you can see that soon!

0

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now