Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Re:creation - a top down action adventure about undeads [hiatus]  (Read 499749 times)

0 Members and 11 Guests are viewing this topic.

Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re:creation - a top down action rpg about undeads
« Reply #240 on: September 08, 2015, 10:35:50 pm »
5 years old? So the laptop might have a dual core cpu with >2 GHz per core? That's quite much for 2D gaming :)
Fair enough. I should test it using other PC's. The game is currently taking 34 Mbs of ram. I think it's pretty okay from RAM point. As for CPU usage, can't be quite sure.

Can you give us a short sketch of your architecture? :) You were talking about your ECS which is object-oriented. What I mean: How do the components message each other? Is there a virtual interface each (sub-)component implements of even overrides? Or do you handle all game logic by calling bound lua functions?
There's a bit of architectural stuff at the beginning of this thread.
I've also written this post about how I use Lua here: http://forums.tigsource.com/index.php?topic=49336.msg1163401#msg1163401
I'll also post a new part of "Using Lua with C++ in Practice" which will show some implementation details which I use in my game (but a bit simplified).

As for messaging... Components don't message each other. Systems do. For example, when some entity dies, it can send a message that a particular entity is dead. DropSystem will receive this message and make this entity drop some item. Messaging greatly reduces dependencies between systems and components. DropComponent and HpComponent don't need to know about each other.
Most logic is stored in Lua, so I don't have virtual functions for entities, pointers to Lua functions do their work instead.
I hope that I don't leave some important details. Feel free to ask more questions!

I really love the screenshots of your project. It is very motivating to see a project wich is already so far in its progress :)
I hope you will finish it that we can actually try and play it! Keep up the nice work! :3
Thanks a lot. I'm glad you like them and I'm glad that my game is motivating. :)

Have you taught the whole programming stuff to yourself?
Yes. Mostly using awesome programming books.

And do you recommend the ECS engine for a 2D-SFML-Game or would you like to change it after you've got to experience it yourself for quite some time? I just ask because I'm planning to start a game-project by myself and am still not sure wich approach to choose...
Once you understand ECS and see how powerful it is, it's hard to go back to standard OOP hierarchy. It just works poorly for games.
Some people only use parts of ECS, but generally composition is the way to go. This is one of the most defining things about ECS.

As for using ECS in you own project, it depends on your programming experience.
If this is one of your first games, I recommend to try out inheritance for a few classes that your game would have.
Then I recommend to start with simple component architecture:
http://gameprogrammingpatterns.com/component.html
You should see the improvement in using this method versus inheritance trees, I think.
Then you can try to implement a simple ECS and try to make some small games with it. Implementing ECS is pretty hard and can take some time, but it's worth it. But on the other hand it may lead you to confusion. :)
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler

Otherian

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re:creation - a top down action rpg about undeads
« Reply #241 on: September 08, 2015, 11:17:13 pm »
Yes. Mostly using awesome programming books.
[...]
As for using ECS in you own project, it depends on your programming experience.
If this is one of your first games, I recommend to try out inheritance for a few classes that your game would have.
Then I recommend to start with simple component architecture:
http://gameprogrammingpatterns.com/component.html
You should see the improvement in using this method versus inheritance trees, I think.
Then you can try to implement a simple ECS and try to make some small games with it. Implementing ECS is pretty hard and can take some time, but it's worth it. But on the other hand it may lead you to confusion. :)
Thanks for your advice :)
Do you have a book recommendation for ECS? (just in case yours was perfect :P)


Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re:creation - a top down action rpg about undeads
« Reply #242 on: September 08, 2015, 11:50:04 pm »
You're welcome.
I didn't read any books which talked about ECS. I recommend you to check out these articles:
http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/
http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/
My approach is not exactly the same as described there, but it's pretty close.
I would also recommend you to check out "Game Engine Architecture" by Jason Gregory. It doesn't talk about ECS but shows lots of useful stuff which may be useful when developing a game engine. It's a fantastic book.
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler

SpeCter

  • Full Member
  • ***
  • Posts: 151
    • View Profile
Re:creation - a top down action rpg about undeads
« Reply #243 on: September 09, 2015, 09:25:19 am »
The book does have a second edition which came out recently btw.

Glocke

  • Sr. Member
  • ****
  • Posts: 289
  • Hobby Dev/GameDev
    • View Profile
Re:creation - a top down action rpg about undeads
« Reply #244 on: September 09, 2015, 10:04:46 am »
I'll also post a new part of "Using Lua with C++ in Practice" which will show some implementation details which I use in my game (but a bit simplified).
Great! I'm also looking forward to it, because I plan to introduce Lua to my own game for AI Scripting.

Messaging greatly reduces dependencies between systems and components.
Hell yeah 8)

Can you give us a full list of your component types? I'm sometimes very confused which damage to split over components and which to hold at one place. Maybe I can inspire myself reading about your data split :)
Current project: Racod's Lair - Rogue-inspired Coop Action RPG

SpeCter

  • Full Member
  • ***
  • Posts: 151
    • View Profile
Re:creation - a top down action rpg about undeads
« Reply #245 on: September 09, 2015, 02:46:14 pm »
From my experiences with different kinds of entity component systems I have to say that the overhead of them is hardly noticabletm.
My current implementation stores components in an unordered_map(<std::type_index,std::vector<Component*>*>) and it can render >50000 moving entities just fine(55fps in debug, 150fps in release) and most time is spent rendering them not processing them.
I'm pretty happy with the results despite it being thrown together in a couple of hours.

You can take a look at it if you want(it is just two header files atm):
ComponentManager.hpp:

#pragma once
#include <vector>
#include <unordered_map>
#include <map>
#include <typeinfo>
#include <typeindex>
#include <algorithm>
#include <tuple>
struct Component
{
   unsigned int entity_id;
};



class ComponentManager
{
   using component_map = std::unordered_map<std::type_index,std::vector<Component*>*>;
public:
   ComponentManager() {}
   ~ComponentManager() {}


   template<typename T,typename... Args>
   void Add(unsigned int ent,Args&&... args)
   {
      std::vector<Component*>* container = map[std::type_index(typeid(T))];
      if(container == nullptr)
      {
         map[std::type_index(typeid(T))] = new std::vector<Component*>();
      }

      map[std::type_index(typeid(T))]->push_back(new T(ent,args...));

   }
   template<typename T>
   bool hasComponent(unsigned int ent)
   {
      auto container = map[std::type_index(typeid(T))];
      if(!container) return false;
      auto it = std::find_if(container->begin(),container->end(),
                             [&] (const Component* e)
      {
         return e->entity_id == ent;
      });
      return it != container->end();
   }
   template<typename T>
   T* getComponent(unsigned int ent)
   {
      auto container = map[std::type_index(typeid(T))];
      auto it = std::find_if(container->begin(),container->end(),
                             [&] (const Component* e)
      {
         return e->entity_id == ent;
      });

      return static_cast<T*>(*it);
   }

   template<typename... Args>
   std::tuple<Args*...> getComponents(unsigned int ent)
   {
      return std::make_tuple(getComponent<Args>(ent)...);
   }

   template<typename... Args>
   bool hasComponents(unsigned int e)
   {
      std::vector<int> result = {hasComponent<Args>(e)...};
      for(auto&& ok : result)
      {
         if(!ok) return false;
      }
      return true;
   }
   component_map map;
};

ComponentSystem.hpp:

#pragma once
#include "ComponentManager.hpp"
#include <iostream>
#include <vector>

struct ComponentSystemBase
{
   ComponentSystemBase()
   {

   }

   virtual void Update(float delta) = 0;
   virtual void EntityUpdated(unsigned int e) = 0;
};

template <typename... Args>
struct ComponentSystem : public ComponentSystemBase
{
   ComponentSystem(ComponentManager& mgr) : manager(mgr)
   {
   }

   virtual void Update(float delta) = 0;
   virtual void EntityUpdated(unsigned int e) override
   {
      if(manager.hasComponents<Args...>(e))
      {
         entities.push_back(e);
         components.push_back(manager.getComponents<Args...>(e));
      }
   }
   ComponentManager& manager;
   std::vector<unsigned int> entities;
   std::vector<std::tuple<Args*...>> components;
};
 

There are some things i'm not happy with like raw-owning pointers and stuff and I could probably add a convenience Entity struct/class which just stores an uid and enables me to write
entity.Add<Position>(10.f,10.f), but that is just nice to have and not needed for the ecs itself.


dabbertorres

  • Hero Member
  • *****
  • Posts: 505
    • View Profile
    • website/blog
Re:creation - a top down action rpg about undeads
« Reply #246 on: September 09, 2015, 10:00:34 pm »
How common is it to use RTTI (typeid) for ECS designs? That can slow things down or create bloat from what I've seen. I've used enums and been happy.

Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re:creation - a top down action rpg about undeads
« Reply #247 on: September 09, 2015, 10:11:12 pm »
The book does have a second edition which came out recently btw.
Yep, and this book became even more awesome! :D

Thanks for sharing the details of your implementation. It looks very similar to what I've implemented recently.

Can you give us a full list of your component types?
AIComponent, AttachComponent, AttackComponent, CollisionComponent, DamageComponent, DirectionComponent, DropComponent, GraphicsComponent, HealthComponent, InteractionComponent, ItemComponent, MovemenetComponent, NpcComponent, ScriptStateMachineComponent, TeleportComponent, TimerComponent, TriggerComponent.

I'm sometimes very confused which damage to split over components and which to hold at one place. Maybe I can inspire myself reading about your data split :)
I have one component for all types of damages, DamageComponent. It has a enum DamageType, so there's no need to create a separate Component for each type of damage.

How common is it to use RTTI (typeid) for ECS designs? That can slow things down or create bloat from what I've seen. I've used enums and been happy.
Hmm, I don't really know, I didn't check out the source code of different ECS designs. So far I've noticed no performance problems with it. (Well, I could have if I used lots of entities at the same time, but I don't!)

Btw,
Using Lua with C++ in Practice Pt. 2 is out. Check it out!
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler

SpeCter

  • Full Member
  • ***
  • Posts: 151
    • View Profile
Re:creation - a top down action rpg about undeads
« Reply #248 on: September 09, 2015, 10:15:41 pm »
Not that common I think(well entityx uses is as far as I remember) there was no real reason to use it to be honest, I was just lazy :-[

As an alternative you can use something like:
class Type
{
    static size_t counter;

public:
    template<typename T>
    static size_t ID()
    {
        static size_t id = counter++;
        return id;
    }
};
 

You invoke it like that:

Type::ID<YourTypeHere>()

It is threadsafe for most compilers and is resolved at compile time, so it should have almost no overhead.
Only downside is, that the id doesn't have to stay the same in different runs of your application, if that is not a problem it should be better than(imo) using enums, because you don't need any bookkeeping.

Edit:

Nice blogpost I enjoyed reading it(eventhough I don't like Lua..). You should consider using an unordered_map instead of map to store components if you don't care about their order ;)
« Last Edit: September 09, 2015, 10:22:16 pm by SpeCter »

Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re:creation - a top down action rpg about undeads
« Reply #249 on: September 10, 2015, 07:34:43 am »
I also have to say that my system is build in a way that typeid calls are not performed very often.
For example, every system gets a std::vector<SomeComponent*> and doesn't need to call typeid or casts ever again.
As for entities... Yep, when you get a component from entity, you call typeid, but that's just once and I've never noticed any perfomance issues.

It is threadsafe for most compilers and is resolved at compile time, so it should have almost no overhead.
Only downside is, that the id doesn't have to stay the same in different runs of your application, if that is not a problem it should be better than(imo) using enums, because you don't need any bookkeeping.
Yep, that's a good way of doing such things. I will use it if type_index becomes a problem. :)

Nice blogpost I enjoyed reading it(eventhough I don't like Lua..). You should consider using an unordered_map instead of map to store components if you don't care about their order ;)
Thanks! AFAIK, unordered_map requires more memory to store. Yes, it let's me to get elements in O(1). But std::map lets me get component in O(log(N)). The N is never more than 10, so the difference is not noticeable. But yeah, the order of components doesn't matter, I'm just worried about additional memory which unordered_map requires. (and this varies between implementations).
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler

Glocke

  • Sr. Member
  • ****
  • Posts: 289
  • Hobby Dev/GameDev
    • View Profile
Re:creation - a top down action rpg about undeads
« Reply #250 on: September 10, 2015, 09:20:12 am »
AIComponent, AttachComponent, AttackComponent, CollisionComponent, DamageComponent, DirectionComponent, DropComponent, GraphicsComponent, HealthComponent, InteractionComponent, ItemComponent, MovemenetComponent, NpcComponent, ScriptStateMachineComponent, TeleportComponent, TimerComponent, TriggerComponent.
Thanks! What's the exact use of TeleportComponent? Is it to cause teleports between maps? And could you also tell us about the AttachComponent? :)

You wrote that logic contained by the systems. So: Is damage calculated by the DamageSystem using the corresponding DamageComponent, and propagated to e.g. HealthComponent to finally inflict it (and may cause death - probably as another event?). Am I right?

I have one component for all types of damages, DamageComponent. It has a enum DamageType, so there's no need to create a separate Component for each type of damage.
Sorry, I wanted to write "data" not "damage" :D But yes, a damage type enum is great :) I have one too, very useful.

Using Lua with C++ in Practice Pt. 2 is out. Check it out!
Nice!
Current project: Racod's Lair - Rogue-inspired Coop Action RPG

Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re:creation - a top down action rpg about undeads
« Reply #251 on: September 10, 2015, 09:48:09 am »
Thanks! What's the exact use of TeleportComponent? Is it to cause teleports between maps? And could you also tell us about the AttachComponent? :)
TeleportComponent is used for triggers which teleport you between levels or some places on the level. For example, trigger near every house has TeleportComponent with type "GoInside". Triggers near stairs have "GoUpStairs" or "GoDownStairs" type.

AttachComponent is used for entities which can grab and carry transport other entities. When some entity is attached to other entity, it's moving with this entity. This is used for platforms at the moment, it can also be used for entities which can pick up and carry other entities. (Like NPCs that can pick up boulders and throw them in you)

You wrote that logic contained by the systems. So: Is damage calculated by the DamageSystem using the corresponding DamageComponent, and propagated to e.g. HealthComponent to finally inflict it (and may cause death - probably as another event?). Am I right?
Each entity which has HealthComponent may have damaged function which takes damage value and damage type as parameters and later decides what to do with it.

For example, suppose you have an entity which is kinda resistant to fire damage but can be damaged with ice attacks. The damaged function may look like this:

damaged = function(damageValue, damageType)
    if(damageType == "Fire") then
         decreaseHealth(entity, damageValue / 2)
    elseif(damageType == "Ice") then
         decreaseHealth(entity, damageValue)
    end
end
 
DamageSystem may detect that some entity with DamageComponent collided with entity, it sends "Damaged" event and HealthSystem catches it and calls damaged function.

You have to map enum values to string values to use them in Lua, though.
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler

nebula

  • Jr. Member
  • **
  • Posts: 96
    • View Profile
    • Email
Re:creation - a top down action rpg about undeads
« Reply #252 on: September 10, 2015, 06:36:43 pm »
I have a question.
When you release your game, in which languages will it be available?

Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re:creation - a top down action rpg about undeads
« Reply #253 on: September 10, 2015, 09:03:18 pm »
I have a question.
When you release your game, in which languages will it be available?
It's originally written in English, I'll also make the Russian translation.(Because I'm from Russia, he-he).
As for other translations: I would love to have German, Spanish, French, Japanese and maybe other translations. If I find some people who would do these translations, this would definitely happen. (If I have enough money to pay them, or if some people volunteer).
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler

dabbertorres

  • Hero Member
  • *****
  • Posts: 505
    • View Profile
    • website/blog
Re:creation - a top down action rpg about undeads
« Reply #254 on: September 10, 2015, 09:15:36 pm »
You'll be happy to find this then! (Translations are on the Master sheet)