SFML community forums

General => SFML projects => Topic started by: Elias Daler on May 02, 2015, 04:05:52 pm

Title: Re:creation - a top down action adventure about undeads [hiatus]
Post by: Elias Daler on May 02, 2015, 04:05:52 pm
(http://i.imgur.com/By9ICGM.png)

Site: https://eliasdaler.github.io/re-creation
Developers: Elias Daler (https://twitter.com/EliasDaler) (programming, art, game and level design, story, etc.), Torchkas (https://twitter.com/Torchkas) (music and sound effects)
Dev logs (old): https://eliasdaler.wordpress.com/tag/devlog/
Dev logs (new): https://eliasdaler.github.io/tags/#Dev+log
Progress screenshot album: http://imgur.com/a/luoFe
Twitter: @eliasdaler (http://twitter.com/eliasdaler)
Platforms: PC, Mac, Linux
Release date: When it's done

(http://button.indiedb.com/popularity/medium/games/42897.png) (http://www.indiedb.com/games/recreation)

The coolest screenshot yet (January 2016):
(http://i.imgur.com/n3eUCxD.png)

Hello, my name is Elias Daler and this will be a dev log of my game!
I'm a solo hobby developer and work on the game in my free time so the progress won't be very fast I hope I'll post some interesting stuff from time to time! You can read previous dev logs here (https://eliasdaler.wordpress.com/tag/devlog/).

The development of this game started in October 2013.
I'm writing the game in C++ and use SFML. I also use Lua for scripting. I'll try to explain how my game works in next posts. I'll write about how I use scripting, how my entity/component/system works and lots of more programming stuff!

Story
The main hero is an undead knight who was betrayed by his partner, Necromancer, during a fight with a giant demon. When the hero raises from the dead, he realizes that lots of time has passed since his death. The Great War between humans and undeads is being fought for several centuries. Necromancer is still alive. He actually became a Lich. He has lots of power and uses undeads as a cheap working force. The hero explores society of undeads and finds out that they don’t actually want to kill humans. They just don’t want people to use them for training and steal their treasure! The hero decides to stop the war and prove that undeads are not that evil as it seems.

(http://i.imgur.com/vg6jQ0x.gif)
Undead City becomes hero's new home.

Gameplay
The gameplay is very similar to top-down 2D Zelda games with the exception of the main mechanic of the game, called recreation.
At any point of the game, you can become a ghost and travel through objects easily.
You can also control enemies you killed with it to get their abilities and solve various puzzles. Here's how it works:

(http://i.imgur.com/qKa48U9.gif)

You can't carry any weapons other than a hammer in the game, so you need to control enemies with bows to be able to use arrows, enemies with shields, to be able to block attacks etc. If you're killed when you're controlling someone else, your ghost will automatically return to your body and the person which you were in will respawn shortly after (because you can't solve some puzzles without other bodies).

Here's are some puzzles which you can solve with recreation mechanic:

(http://i.imgur.com/pQ9culg.gif)

(http://i.imgur.com/u9CYS5p.gif)

Other gifs / screenshots:

(http://i.imgur.com/u8G0Opu.gif)
NPC's are interesting...

(http://i.imgur.com/W8VL5i7.gif)
Hero reacting to items he gets from chests

(http://i.imgur.com/RdZvdlI.gif)
Boss fight

As this is the first post, I'll edit it from time to time to add the latest and coolest screenshots and gifs.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 02, 2015, 05:17:11 pm
This is very outdated and doesn't reflect the state of the project well. I'll write about current architecture some day! (Posted on 21-02-17)

Some programming stuff.

I use C++11 with SFML and Lua for scripting. The most important aspect of the engine is entity/component/system model. Here's my implementation of it.
Entities are different objects in the game: characters, houses, items, etc.
Each entity has unique id (which is used to identify them) and a number of components.
So, characters have: GraphicsComponent, MovementComponent, CollisionComponent, HealthComponent, etc.
Static objects don't need all of that so they only have GraphicsComponent and CollisionComponent.

So, entities are made from "blocks". Those blocks can have unique behaviour by scripting. But I'll talk more about that later.

Basically, it looks like this in code:

class Entity {
public:
    ... // some stuff
private:
    int uid;
    std::vector<std::unique_ptr<Component>> components;
    ... // some other stuff
};

Component is simply a collection of data. For example, GraphicsComponent holds sprite and other stuff related to graphics, MovementComponent has velocity, etc.-etc.

Systems operate on components. Basically most of the game logics is there.
For example, MovementSystem iterates over MovementComponent's of active objects and adds  to a current position for each entity. Most systems operate on one type of component and it doesn't matter to them what entity any component belongs to. This makes adding new types of entities easy as I don't have to change logics very often.

Entity definitions are stored in Lua scripts. Here's an example of a chest entity: http://pastebin.com/P3mAD8NN
As you can see, every component parameter is here but I can also define functions in Lua script. This let's me specify object behaviour so it's not hard coded in C++! This is very useful as I don't have to recompile the game very often.
Lots of Lua function have bindings to functions in C++, so I can use this function in a script:
setAnimation(someEntity, "animationName")
which will call this function in C++
void setAnimation(ind entityId, const std::string& animationName) {
    auto e = engine_system.em->getEntity(entityId);
    ... // code to set animation
}

Notice, that I don't pass around pointers or entity references but instead pass ints which is faster.
Getting entity from id is also fast, as each entitiy is stoped in a hash map and can be quickly accessed by unique id.

Once the entity templated is loaded in C++, every entity of this "class" is created with the template which is a lot faster than reading properties from scripts over and over.

There's some basic support for "inheritance" so if some entities have lots in common, they can use other entities properties, overwrite some properties and add new components.
Here's an example of that a chest that uses different sprite:  http://pastebin.com/6pQKJz5P
As you can see, there's no need to copy-paste everything, I can just change some of the parameters, the rest will be copied from base entity.

(https://i.imgur.com/aMK1rfA.png)
Chest vs super_chest. The only thing different is the graphics and size.

(You can read more about inheritance and scripting here (https://eliasdaler.wordpress.com/2015/03/30/recreation-dev-log-march-2015/))

My game also has in-game level editor.
(http://i.imgur.com/rjedWLB.gif)
Bigger gif: http://i.imgur.com/8HtWIYU.webm
It has lots of features: tile map editing, multiple object selection and moving, object creation, undo, etc.

And that's basically it. If you have some questions, feel free to ask!
(I'll write about messaging between systems, events and decoupling soon!)
Title: Re:creation - a top down action rpg about undeads
Post by: Raincode on May 02, 2015, 06:13:00 pm
This looks pretty awesome! I could imagine it was a lot of work. When did you start it? Do you have some screenshots from earlier development stages?
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 02, 2015, 06:39:13 pm
This looks pretty awesome! I could imagine it was a lot of work. When did you start it? Do you have some screenshots from earlier development stages?

Thanks a lot! I've started it in October 2013 (should probably add this to the first post, ha-ha).
Here (http://imgur.com/a/luoFe#86) is a progress album of my game. (I'll add it to the first post too)
Title: Re:creation - a top down action rpg about undeads
Post by: Cirrus Minor on May 02, 2015, 07:11:59 pm
It looks really nice and fun!
Are you making the 2D-art?
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 02, 2015, 08:47:04 pm
It looks really nice and fun!
Are you making the 2D-art?

Thanks! Yes, I do. I would love to have an artist working with me, but I don't have money or artistic friends, so the only thing left to do is to do my own art. :D
Title: Re:creation - a top down action rpg about undeads
Post by: Lo-X on May 02, 2015, 11:09:33 pm
The game looks awesome but your post also is!

I'm very interested in reading more about systems and how they communicate with each other. I'm also interested in the Lua binding (what did you use, what did you bind).

What do you think about getting rid of the Entity class and just store arrays of components indexed by the entity ID ? It's something I read a lot about.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 02, 2015, 11:42:40 pm
The game looks awesome but your post also is!

I'm very interested in reading more about systems and how they communicate with each other. I'm also interested in the Lua binding (what did you use, what did you bind).
Thanks!

I use LuaBridge for binding. It's a fantastic and easy to use library and I've also written two articles about it on my blog. :)
I'm binding any function which needs to be called from the scripts. For example, here's how setVelocityX function looks in C++:

void setVelocityX(int entityId, float vx) {
    auto e = engine_system.em->getEntity(entityId);
    auto mc = e->get<MovementComponent>();
    if(mc) {
        mc->setVX(vx);
    } else {
        engine_system.log->write("Entity named" + e->getName() + " doesn't have MovementComponent!", LogManager::ERR);
    }
}

Then I can use LuaBridge and just write
getGlobalNamespace(L).addFunction("setVX", setVelocityX)

And then call it in scripts, for example in init() function (stored in entity template table) which is called when the entity is created:

init = function(this)
    setVX(this, 0.05)
end

So, when I call any Lua function, I pass entity id as a parameter which is later used to get entity in C++ after Lua function calls some C++ functions.

What do you think about getting rid of the Entity class and just store arrays of components indexed by the entity ID ? It's something I read a lot about.

I'm thinking about it and this can be a lot more efficient than what I use now. (Faster iteration, less cache misses, object pools...)
And I'll possibly implement it this way at some point in future and I won't have to change lots of code. (There's no need for it now though, as I don't see any perfomance related issues with the stuff I have now).
The only thing which I can't figure out is how to actually create arrays for each component and then easily get it.
For example, suppose I want to be able to get some component this way:
auto mc = get<MovementComponent>(entityId);
So, I need some kind of type/component array mapping. And while the key can be a std::type_index, what will the value of the map be? I can't store arrays of different types in one std::map.
Title: Re:creation - a top down action rpg about undeads
Post by: dabbertorres on May 03, 2015, 01:31:46 am
As I've understood, one way of doing it is by having each System own an array of the Component it manages.

Something like:
template<typename T, typename std::enable_if<std::is_base_of<Component>::value>::type* = nullptr>
class System
{
      public:
            System();
           
            virtual void update(float dt) = 0;
           
            T& get(int idx);

      private:
            container_of_your_choice<T> components;
};
 

Something like that. It can be pretty much however you want of course.
Then just derive from that for each System/Component type, implement any virtual functions you have, and there you go.

So like:
class GraphicsSystem : public System<GraphicsComponent>
{
      // stuff goes here...
};
 

I'm planning to adjust my own code base to something like this soonTM.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 03, 2015, 08:39:41 am
I've done this before, but this led to another problem: I couldn't store Systems in one collection and had to update them like this:
void EntityManager::update() {
    renderingSystem->update();
    collisionSystem->update();
    ... // etc.
}
So, every time I add a new system, I need to add it to update, process and other
 functions, because I can't just iterate over all of them. (And I had to insert it in particular order everywhere, because it matters)

I have this instead now, because I have a base class EntitySystem and std::vector<EntitySystem*> systems:
void EntityManager::update() {
    for(auto it != systems.begin(); it != systems.end(); ++it) {
        (*it)->update();
    }
}

RenderingSystem looks like this, for example:
class RenderingSystem : public EntitySystem {
public:
    ...
private:
   std::vector<GraphicsComponent*> components
}
So, every system has it's own vector of components (and if systems needs to operate on two different types of components, it can!), but I still can store systems in one place and easily add new systems.
Title: Re:creation - a top down action rpg about undeads
Post by: dabbertorres on May 03, 2015, 07:56:31 pm
Ah. I see. Well, I guess you could then have a BaseSystem class of sorts that System<T> inherits from, and then have a container of BaseSystem*s or something, if each System<T> is all going to have the same functions. Then you could iterate over all the systems. And just add them to the container in the order you need them to update.

Though I do like your method as well.

It's interesting to see the different methods people come up with!
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 04, 2015, 10:55:37 am
That's a good suggestion, maybe I'll try it out someday. :)

And I love to see different ways of doing stuff, I hope my dev log will inspire others and they'll show off their ways of doing things.
Title: Re:creation - a top down action rpg about undeads
Post by: ChronicRat on May 04, 2015, 11:11:47 am
Cool, I don't like "pixel" styled games but this one is really fun.
Title: Re:creation - a top down action rpg about undeads
Post by: Tank on May 04, 2015, 12:08:18 pm
This looks stunning! :-)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 04, 2015, 01:32:11 pm
Cool, I don't like "pixel" styled games but this one is really fun.

Thanks! I use pixel art because creating high-res art is really hard while working solo. It also looks less professional when done by not very skilled artist. I try to make my pixel art look unique, though!

This looks stunning! :-)
Thanks a lot! :)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 05, 2015, 12:41:52 am
(http://i.imgur.com/4ujBOn8.gif)
Made smooth level transition. Area name is displayed.
Title: Re:creation - a top down action rpg about undeads
Post by: fakepotato on May 05, 2015, 02:23:22 am
Awesome ... just have no other words to express my feelings about this...
And your second post forced me to acknowledge component-based system and LUA-scripts.
It's really inspiring thread!
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 05, 2015, 07:50:53 am
Awesome ... just have no other words to express my feelings about this...
And your second post forced me to acknowledge component-based system and LUA-scripts.
It's really inspiring thread!

Thanks!
ECS and scripting are one of the greatest things ever. They make code a lot cleaner and flexible. If you have some questions about implementation, feel free to ask!
Title: Re:creation - a top down action rpg about undeads
Post by: Grimshaw on May 05, 2015, 01:28:43 pm
Pretty great project! Do you do all gameplay logic in systems? You always process your game data in a serial fashion, rather than the old inner object logic?

Also, each system gets its own storage container of components it acts on?
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 05, 2015, 02:27:51 pm
Pretty great project! Do you do all gameplay logic in systems? You always process your game data in a serial fashion, rather than the old inner object logic?

Also, each system gets its own storage container of components it acts on?

Thanks!
No, not all logic is in systems. There are also some common Entity state classes (idle, attack, move, dying, falling, etc.) which have a bit of gameplay logic. And there is also gameplay logic in scripts because some entities have unique behaviour which needs to be scripted. For example, the witch in Undead City which turns pages in the book, her behaviour is not just a simple animation: it's scripted (here's the script (http://pastebin.com/9B3rnyDm)).

Most data is scripted but there's some data which is stored in C++ code. This is mostly temporary because making this data scriptable takes some time, it's just faster to write non-scripted code.

Systems have vectors of pointers to components. When entity is created, it's passed in each system which checks if it has component the system uses. If entity has one, system adds pointer to the component to the vector. This is not the ideal way of doing things, but it works pretty good for now.
Title: Re:creation - a top down action rpg about undeads
Post by: Grimshaw on May 05, 2015, 02:38:36 pm
Thanks for your answer. You are a very sensible engineer, you only deserve praise here :)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 05, 2015, 02:43:40 pm
Thanks for your answer. You are a very sensible engineer, you only deserve praise here :)

No problem. Thank you. :)
Title: Re:creation - a top down action rpg about undeads
Post by: Jesper Juhl on May 06, 2015, 05:32:19 pm
Wow. This looks amazing.
Well done.
Title: Re:creation - a top down action rpg about undeads
Post by: iride on May 06, 2015, 05:37:19 pm

I'm thinking about it and this can be a lot more efficient than what I use now. (Faster iteration, less cache misses, object pools...)
And I'll possibly implement it this way at some point in future and I won't have to change lots of code. (There's no need for it now though, as I don't see any perfomance related issues with the stuff I have now).
The only thing which I can't figure out is how to actually create arrays for each component and then easily get it.
For example, suppose I want to be able to get some component this way:
auto mc = get<MovementComponent>(entityId);
So, I need some kind of type/component array mapping. And while the key can be a std::type_index, what will the value of the map be? I can't store arrays of different types in one std::map.

The way i implemented that is assigning unique ids(starting at 0) to each component at compile time.
Then you store these components in a vector.
Then you can retrieve each component by its id.
If an entity doesn't have that component, it can return nullptr.

template <class C>
C * get(int id)
{
     std::vector<Component*> & v = getComponentsofEntity(id);
     return static_cast<C*>(v[C::getUniqueID()]);
}
 
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on May 06, 2015, 05:40:55 pm
Damn, this game is ridiculously amazing. It honestly looks like the sort of gameboy game that I would still buy. I tried to make something similar a couple of years ago. Two years and 14000 lines of code later, it is pitiful compared to this. I am amazed by the quality of things like this that people put on here.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 06, 2015, 06:33:51 pm
@Jesper Juhl Thanks a lot!

@iride That's almost how I do it now (I use dynamic_cast instead of component ids, though. But we were talking about components being stored in arrays of particular component type. Something like std::vector<GraphicsComponent>, std::vector<MovementComponent>, etc. Getting components from there is an issue.

@shadowmouse
Thanks! That's my biggest project ever. 20k lines of code and still doing well. It's mainly because of scripting and ECS, I think. If I tried to use OOP for this, I wouldn't be able to progress that far. :)
Title: Re:creation - a top down action rpg about undeads
Post by: Grimshaw on May 07, 2015, 02:17:35 am
I am dying to see how the game will play. I am so supporting this :D

btw, my first serious game also had 20k loc, but didn't get to be as clean or good as yours, unfortunately :)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 07, 2015, 07:55:42 am
@Grimshaw Thanks! Glad to hear it. :)

Progress update.

Okay, so arrows are not hard coded anymore!
(http://i.imgur.com/LxUaeEW.gif)
I've added some of Lua/C++ binding functions to be able to script arrows. Here's how item system works now.
Each item has its "use" function which gets called every time player or entity uses an item. In case of bow, "use" function sets player in AttackState and sets current attack to "bow_attack".
Each attack has its enter, execute and exit functions. Enter function is called when the attack starts, execute function gets called every frame during the attack and exit function is called when the attack stops.

In case of bow_attack, its "execute" function looks like this:
execute = function(vars, owner)
    if(getCurrentAnimationFrame(owner) == 1 and not vars.createdArrow) then
        arrow = createEntity("arrow", getPosition(owner))
        setChildEntity(owner, arrow)
        setDirection(arrow, getDirection(owner))
        setScriptState(arrow, "IdleState")
        vars.createdArrow = true
    end
end
Arrow is not created when bow animation starts. Animation has a little delay.
vars is a table which gets created when attack starts. It can be used to store variables in different parts of attack scripting code. When this function is called the first time, vars.createdArrow is nil, but when vars.createdArrow = true line is called, variable "createadArrow" is created in vars table which I can later use to not create arrows twice (player animation can be on second frame of animation for some time).

Arrow scripting code is a bit trickier. Here's how its ScriptStateMachineComponent looks:
ScriptStateMachineComponent = {
    states = {
        IdleState = {
            enter = function(self, entity)
                direction = getDirection(entity)
                moveSpeedX = getMoveSpeedX(entity)
                moveSpeedY = getMoveSpeedY(entity)
               
                setAnimation(entity, "idle." .. direction)
                setDamageDirection(entity, direction)
               
                if(direction == "Up") then
                    setVelocity(entity, 0.0, -moveSpeedY)
                    setDamageRect(entity, 0.0, 0.0, 9.0, 4.0)
                elseif(direction == "Down") then
                    setVelocity(entity, 0.0, moveSpeedY)
                    setDamageRect(entity, 0.0, 8.0, 9.0, 4.0)
                elseif(direction == "Left") then
                    setVelocity(entity, -moveSpeedX, 0.0)
                    setDamageRect(entity, 0.0, 0.0, 4.0, 9.0)
                elseif(direction == "Right") then
                    setVelocity(entity, moveSpeedX, 0.0)
                    setDamageRect(entity, 0.0, 10.0, 4.0, 9.0)
                end
               
                playSound("res/sounds/arrow_shoot.wav")
            end,
            execute = function(self, entity)
            end,
            exit = function(self, entity)
            end
        },
        StuckState = {
            enter = function(self, entity)
                setAnimation(entity, "stuck." .. getDirection(entity))
                startTimer(entity, "killTimer")
                setVelocity(entity, 0.0, 0.0)
                disableComponent(entity, "CollisionComponent")
                disableComponent(entity, "DamageComponent")
            end,
            execute = function(self, entity)
                if(timerFinished(entity, "killTimer")) then
                    killEntity(entity)
                    stopTimer(entity, "killTimer")
                end
            end,
            exit = function(self, entity)
            end
        },
    }
},
It's mostly self explanatory. There's some other code for arrow collision and damaging, but I won't post it as its pretty obvious. :)
Title: Re:creation - a top down action rpg about undeads
Post by: ChronicRat on May 07, 2015, 12:27:48 pm
Lua is beautiful. Do you use some sort of OOP realisation under Lua or only table like these?
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 07, 2015, 01:20:50 pm
Indeed. Tables are pretty much enough for such tasks. If I need to get some values from them in C++, I can easily do it with LuaBridge. :)
Title: Re:creation - a top down action rpg about undeads
Post by: Grimshaw on May 07, 2015, 02:32:13 pm
Do you actually find Lua beautiful?
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 07, 2015, 02:58:18 pm
Do you actually find Lua beautiful?
Yeah. It's simplicity is pretty great. Speed is another cool thing about it. And it's pretty easy to bind Lua with C++ using binding libraries.
Title: Re:creation - a top down action rpg about undeads
Post by: dabbertorres on May 07, 2015, 07:31:38 pm
I just noticed that you use parentheses around the condition in if statements in Lua, is that a style preference?
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 07, 2015, 08:32:06 pm
Added archers!
(http://i.imgur.com/LNGqqXe.png)

dabbertorres, yeah, it's just easier to find the condition visually.
Title: Re:creation - a top down action rpg about undeads
Post by: Ricky on May 07, 2015, 09:41:38 pm
Do you actually find Lua beautiful?
Yeah. It's simplicity is pretty great. Speed is another cool thing about it. And it's pretty easy to bind Lua with C++ using binding libraries.

I was using LuaGlue for a bit but the project owner hasn't updated in a while and LuaBridge also allow JIT
Title: Re:creation - a top down action rpg about undeads
Post by: ChronicRat on May 08, 2015, 06:43:55 am
Do you actually find Lua beautiful?
What else could be simpler, smaller and faster? Lua is ideal! =)
Title: Re:creation - a top down action rpg about undeads
Post by: Grimshaw on May 08, 2015, 01:58:56 pm
simpler smaller and faster, its debatable but I can agree on, but I was asking about beautiful.. it looks like the ugliest thing ever to me, despite knowing its advantages and having used it before
Title: Re:creation - a top down action rpg about undeads
Post by: ChronicRat on May 08, 2015, 03:04:58 pm
It looks like you just never met ugly code. =) And Lua code by Elias Daler is really good.
Title: Re:creation - a top down action rpg about undeads
Post by: Grimshaw on May 08, 2015, 05:25:14 pm
Call me biased but I am just more of a C style syntax man :p
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 09, 2015, 07:27:47 am
By the way, here's a new gameplay gif!
You can't carry bows or any other weapons other than your hammer (it's too heavy!).
So, in order to shoot arrows, you need to kill archers and control them with your ghost. Also, ghost can fly which helps too.
(http://i.imgur.com/jJ0qLxR.gif)
Title: Re:creation - a top down action rpg about undeads
Post by: Grimshaw on May 09, 2015, 02:16:49 pm
That ghost idea is really cool! Looking forward to feel how it plays :D
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 09, 2015, 11:40:33 pm
Thanks!
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 14, 2015, 07:47:30 am
Don't have much time to work on the game this games (lots of study!).
But I've recently optimized level drawing a lot. I was using sf::Sprite for each tile and was drawing every one of them seen on the screen. Now I use chunks of sf::VertexArray. This improved rendering perfomance by 4x-5x which is very awesome.
(http://i.imgur.com/rkz3gmu.png)
Title: Re:creation - a top down action rpg about undeads
Post by: Grimshaw on May 14, 2015, 12:44:30 pm
Did you really struggle to render a few sprites on the screen? This kind of game usually needs no optimization in rendering, modern cards hold a lot more draw calls than that :D
Title: Re:creation - a top down action rpg about undeads
Post by: fakepotato on May 14, 2015, 04:28:50 pm
Your tutorials about Lua bindings are awesome.
I have question, though. What about security? Everyone can see and edit scripts.
You recommend encode them to binary/resource files, or compile as libraries? What's your method?
As far as i know, your re:creation game won't be open source, so i suppose you solved that problem somehow to hide realization from users.
Thanks for replies  :)
Title: Re:creation - a top down action rpg about undeads
Post by: Lo-X on May 14, 2015, 05:17:16 pm
You recommend encode them to binary/resource files, or compile as libraries? What's your method?

I don't know what he does but Lua is "compilable" with luac
Title: Re:creation - a top down action rpg about undeads
Post by: fakepotato on May 14, 2015, 05:25:32 pm
So luac is 100% safe?
Title: Re:creation - a top down action rpg about undeads
Post by: Jesper Juhl on May 14, 2015, 05:40:02 pm
Are you trying to say that you think something is "safe" (from tampering) because it is in binary and not script form?  If so, you are mistaken - and that goes for not just lua but your c++ object files as well.
Title: Re:creation - a top down action rpg about undeads
Post by: Ricky on May 14, 2015, 06:05:56 pm
So luac is 100% safe?

I say embrace modding because just look what it did for Minecraft. It helps build a community around your product and also means that the community is making content that you don't have to and you still make sales!

I'd totally let the community tear the game apart and do what they wanted.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 14, 2015, 06:23:52 pm

 
Did you really struggle to render a few sprites on the screen? This kind of game usually needs no optimization in rendering, modern cards hold a lot more draw calls than that :D
Nah, it was running in 60 FPS all the time. Rendering was just taking too long compared to other stuff and I've thought I could optimize it a bit. This chunk system even helped me realize how to store levels more efficiently so it's a double win!

Your tutorials about Lua bindings are awesome.
I have question, though. What about security? Everyone can see and edit scripts.
You recommend encode them to binary/resource files, or compile as libraries? What's your method?
As far as i know, your re:creation game won't be open source, so i suppose you solved that problem somehow to hide realization from users.
Thanks for replies  :)
Thanks!
I have no problems with users reading and editing my scripts. I can say I even embrace that. Modding is awesome (this is what got me into gamedev!) and I'll do some stuff to help modders mod my game if they show some interest in it (some documentation, some tools like level editor, etc.). I think it's a good thing that people may use my scripts because it may help them improve their scripting or see awesomeness of Lua!
As for luac... Maybe I'll use it if scripts slow down my game. But it makes modding harder which is not what I want. :)

So luac is 100% safe?

I say embrace modding because just look what it did for Minecraft. It helps build a community around your product and also means that the community is making content that you don't have to and you still make sales!

I'd totally let the community tear the game apart and do what they wanted.

Totally agreed!
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on May 14, 2015, 06:39:43 pm
Can you tell me the advantages of using scripts instead of just writing it in c++? I was just thinking how hard can it be to just translate the lua into c++ and then not have to use another language.

P.S. I'm pretty sure you've been stealing my ideas directly out of my head, because about a year ago, I was going to make a game which used a similar game mechanic as the game, but with a different context, I never told anyone about it, didn't finish or post it, and then a year later you've made what looks like a brilliant game based around a concept I couldn't be bothered to make the artwork for.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 14, 2015, 07:13:16 pm
Can you tell me the advantages of using scripts instead of just writing it in c++? I was just thinking how hard can it be to just translate the lua into c++ and then not have to use another language.
The main advantage is getting rid of hard coded values and hard coded gameplay logic in C++. Scripts make your code a lot more flexible (no need to recompile if you change anything in them). They are also useful in Entity/Component/System because you can't create a class for each type of an entity and writing lots of if/else stuff for different objects is just awful.
So, for example, when I have objects which will behave uniquely if you collide with them, I just write a script function and it gets the job done.

P.S. I'm pretty sure you've been stealing my ideas directly out of my head, because about a year ago, I was going to make a game which used a similar game mechanic as the game, but with a different context, I never told anyone about it, didn't finish or post it, and then a year later you've made what looks like a brilliant game based around a concept I couldn't be bothered to make the artwork for.
Great minds think alike, haha! Thanks. :)
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on May 14, 2015, 07:17:22 pm
Ah I think I get what you're talking about. Well, I get why you do it anyway, I don't think I'll ever leave pure c++ because I prefer the object orientated style, where I give classes identifiers so the in the given example, the class can tell whether or not the think it collided with is special. Oh, and for the record, I think your way of controlling enemies is better than mine because mine was something like venom from spiderman in that you played as a symbiotic goo and so I would have had to draw a player controlled version of every enemy instead of your way of just controlling them.
Title: Re:creation - a top down action rpg about undeads
Post by: dabbertorres on May 14, 2015, 07:20:30 pm
What about security? Everyone can see and edit scripts.
You recommend encode them to binary/resource files, or compile as libraries? What's your method?

There are plenty of Lua decompilers out there, and the output tends to be pretty straightforward.

Can you tell me the advantages of using scripts instead of just writing it in c++? I was just thinking how hard can it be to just translate the lua into c++ and then not have to use another language.

1. You don't have to recompile the whole game every time you make a change.

2. Lua is more flexible than C++ in some ways, which can make some tasks easier to accomplish in Lua.

3. Lua is a higher-level language than C++, generally, you can get more done in less time.

4. Makes it easier to include modding support.

5. Helps to keep your C++ code clean. Less implementation specific stuff clogging it up.

6. Almost requires a good design for your C++ code. Having messy C++ code can make it more difficult to bind it to Lua.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 14, 2015, 07:31:47 pm
Ah I think I get what you're talking about. Well, I get why you do it anyway, I don't think I'll ever leave pure c++ because I prefer the object orientated style, where I give classes identifiers so the in the given example, the class can tell whether or not the think it collided with is special. Oh, and for the record, I think your way of controlling enemies is better than mine because mine was something like venom from spiderman in that you played as a symbiotic goo and so I would have had to draw a player controlled version of every enemy instead of your way of just controlling them.

You can mix OOP and Lua quite easily. No need to recompile is a big thing for gamedev. I can change and fine-tune gameplay logic and different variables during the run time. This makes development a lot faster.

And dabbertorres wrote about some cool advantages I've missed. I strongly encourage you to try out scripts. If you don't like them - no problem, everyone has their own dev process. But just trying out different stuff is great and can improve your code a lot, especially scripting.
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on May 14, 2015, 07:34:20 pm
I have done some stuff with Unity, is that the same thing?
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 14, 2015, 07:55:38 pm
I have done some stuff with Unity, is that the same thing?
I've never used Unity, so I can't tell (but I know that it has cool scripting system so I think you can make changes when your game is running). Basically it works like this for my game:

1) Load the game
2) Test some stuff
3) Make some changes in a script
4) Reload the script using in-game console
5) Changes are now in the game and I can test stuff again. :)
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on May 14, 2015, 07:59:43 pm
Yeah that's pretty much how it is in Unity.
When you want to do that, you make the variable you want to change visible in the inspector and then change it while you're running the program. Then put the value in the scripts when you stop the program.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 15, 2015, 09:41:30 am
I've improved level format
(http://i.imgur.com/nOCWXng.png)
See these dark gray squares? These are empty chunks. There maybe a lot of them because levels may not be in form of a rectangle. 
When I didn't use chunks, I've had to save large empty areas because all tiles were stored in one big 2d array. So it looked like this in a file (-1 is an empty tile id):

1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,...
1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,...
1,1,4,1,5,1,1,1,-1,-1,-1,-1,-1,-1,...
1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,...
1,1,1,5,1,1,1,1,-1,-1,-1,-1,-1,-1,...
1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,...
1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,...

Lots of space wasted, right? Not anymore! Now I store levels like this (posX and posY indicate index of top-left tile in chunk):

...
chunk posX=-8 posY=-13
42,42,42,42,42,42,42,42,
30,30,30,30,30,30,30,30,
9,9,9,9,9,9,9,9,
13,13,13,13,13,13,13,13,
13,13,13,13,13,13,13,13,
52,52,52,52,52,52,52,52,
1,1,1,1,1,11,1,1,
31,1,11,2,1,1,23,1,
chunk posX=-32 posY=-5
1,1,1,1,1,13,13,13,
1,1,1,1,1,13,13,13,
1,1,1,1,1,13,13,13,
1,1,1,1,1,13,13,13,
1,1,1,1,1,13,13,13,
1,1,1,1,1,13,13,13,
1,1,1,1,1,13,13,13,
1,1,1,1,1,13,13,13,
...

Chunks are still stored in one 2d array (it's easier to work with them that way), but empty chunks are very lightweight (all they have is empty sf::VertexArray and std::vector<std::vector<int>>) so it's not a problem.
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on May 15, 2015, 10:32:50 am
Could I suggest filling the empty spaces with dense forest (just copy and paste your trees), because that makes it look more realistic, while still means you don't have rectangular levels.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 15, 2015, 04:27:16 pm
Could I suggest filling the empty spaces with dense forest (just copy and paste your trees), because that makes it look more realistic, while still means you don't have rectangular levels.
There's no need to do that, player won't ever see those areas, that's why keeping information about this areas is a waste of space.
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on May 15, 2015, 04:30:55 pm
I was thinking along the lines of if you were going to make the big open areas scroll continuously or if you might start zoomed out when the player enters a new area, so they got some idea of what it was like, and then you zoom in to their position. Oh and for the record, I didn't mean program in data about the trees I just meant have some record that that area was empty and make something that fills all empty areas in whenever they would be visible.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 15, 2015, 04:34:42 pm
I was thinking along the lines of if you were going to make the big open areas scroll continuously or if you might start zoomed out when the player enters a new area, so they got some idea of what it was like, and then you zoom in to their position. Oh and for the record, I didn't mean program in data about the trees I just meant have some record that that area was empty and make something that fills all empty areas in whenever they would be visible.
Yeah, if player will be able to see it zoomed out, I would do it. But probably I'll just make a map which won't represent game world 1:1 but will be like in A Link to the Past.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 19, 2015, 10:19:53 am
Doing some animations. What do you think?
(http://i.imgur.com/1zDC6z1.gif) (http://i.imgur.com/D6AEkWX.gif)

Old animation for comparison (it sucks!)
(http://i.imgur.com/vKVpOwu.gif)
Title: Re:creation - a top down action rpg about undeads
Post by: Tank on May 19, 2015, 10:21:41 am
I'm no designer, but: Nice! :-)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 19, 2015, 10:30:58 am
I'm no designer, but: Nice! :-)
Thanks. It's very hard to draw in that perspective. I've tried different shapes for character sprite and this one looks the best. It's very styled (don't even compare that with Chrono Trigger or Secret of Mana! :D) but I think it looks okay.
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on May 19, 2015, 08:03:16 pm
The top (new) graphics do look better than the bottom (old) graphic but the top-right one (new, clothed) looks like he has had his left arm amputated! :o

By the way, this project looks really well done. Good work! :)
Title: Re:creation - a top down action rpg about undeads
Post by: Jabberwocky on May 20, 2015, 12:46:50 am
Looks great, Elias.  Thanks for sharing.

I enjoyed your write-up on the ECS model you're using.  I'm also using ECS.  It can be a bit of work t get set up properly.  But once you do, there's massive flexibility in designing different kinds of game objects.  I doubt I'd ever go back to using anything different.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 20, 2015, 01:18:17 am
@Hapax Thanks!
Well, the right arm... it's just one pixel wide (instead of two). It looks a bit weird, but with two it looks even worse, but I'll try to find some balance (can't make it 1.5 pixels, unfortunately!)

@Jabberwocky Thanks! Glad you've enjoyed it.
Yeah, once you get ECS, there's no way back. I've tried to do normal OOP and ended with almost ECS (all classes differed mostly by data, so why not get rid of classes at all in that case? :D)

Oh, and I'm working on attack animation now. It's not perfect but starting to actually look decent.
(http://i.imgur.com/FOw3qBY.gif)
Title: Re:creation - a top down action rpg about undeads
Post by: Jabberwocky on May 20, 2015, 05:19:29 pm
I hope you don't mind a bit more discussion on ECS. 

Overall, our implementations of ECS seem pretty similar.

One minor, although significant difference is that you store a vector/array of pointers to components.  That will be totally fine for a game which doesn't have a huge number of entities/components operating at once, as looks to be the case with your game, given that it works screen by screen.

For a game that does process a huge number of entities at once, say a large, dynamic, open world game with entities that continue to operate while off-screen, you would lose some performance because of the pointers.  It's a cache miss problem, because while the pointers are arranged sequentially in memory, the actual component data is not.  So when a system iterates over an array of components, it's jumping all over memory.

It's more optimal to store a straight up array of components, not component pointers.  i.e.

class ComponentSystem
{
private:
   // not this:
   // std::vector<Component*> m_components;
   // but this:
   std::vector<Component> m_components;
};

Then, when you iterate over m_components, it's all sequential memory, which is really fast.  The biggest problem with this approach is that when m_components grows, as can happen when you add new elements, two tricky things happen:

1.  It invalidates any Component pointers or references which may currently be in use by your gamesystem code, since the vector moves in memory.  This can lead to some nasty dangling pointer/reference bugs if you're not very careful about when you add components to the vector, in relation to when you operate on components within the vector.

2.  It calls constructors and destructors on every component in the vector, which can lead to unintended consequences if you treat your constructors and destructors as meaning the entity/component is being created and destroyed in a gameplay sense.

Bottom line, arrays of pointers are easier (avoiding the problems above), provide all the flexibility of an ECS, and work great for most games.  They do lose some of the performance benefits of an ECS, but that's only important for a few kinds of massive, open world games.  So this is not a critique of your approach at all (it seems really good!), just some of the thoughts I've had. 
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 20, 2015, 06:13:32 pm
I don't mind this disscussion at all. In fact, I pretty much welcome it because it may lead to something interesting and help me and other people find out about different approaches and tricks.

std::vector<Component> m_components;
Nope, can't do that. How do I store different components in one vector? Only through pointers (well, I can use shared_ptr, but I'll fix that later). If you try to store derived classes instances in one vector, object slicing happens. :)

Just run this code and see what happens:

class A {
public:
    virtual void print() {
        std::cout << "A " << std::endl;
    }
};

class B : public A {
public:
    void print() override {
        std::cout << "B" << std::endl;
    }
};

int main() {
    A a;
    B b;
    std::vector<A> c;
    c.push_back(a);
    c.push_back(b);
    for (auto it = c.begin(); it != c.end(); ++it) {
        it->print();
    }
}
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on May 20, 2015, 07:33:15 pm
@Hapax Thanks!
the right arm... it's just one pixel wide
Ah, I think I see it now. I stand, though, by the fact it looks initially like that single pixel-wide part is a part of the sword so the arm looks like it's missing below the shoulder  :D
Title: Re:creation - a top down action rpg about undeads
Post by: Nexus on May 20, 2015, 07:54:43 pm
1.  It invalidates any Component pointers or references which may currently be in use by your gamesystem code, since the vector moves in memory.  This can lead to some nasty dangling pointer/reference bugs if you're not very careful about when you add components to the vector, in relation to when you operate on components within the vector.
As a solution to this problem, typical ECS implementations use a sort of handles (e.g. integers containing information to index) instead of pointers and references.

2.  It calls constructors and destructors on every component in the vector, which can lead to unintended consequences if you treat your constructors and destructors as meaning the entity/component is being created and destroyed in a gameplay sense.
This can be avoided by providing move constructor and move assignment operator. This adds more maintenance overhead however, so I wouldn't do it carelessly.

std::vector<Component> m_components;
Nope, can't do that. How do I store different components in one vector?
You don't. You use multiple vectors, one per component type.

Components would no longer be owned by entities; each vector would then store the components of multiple entities in the game.
Title: Re:creation - a top down action rpg about undeads
Post by: Jesper Juhl on May 20, 2015, 08:03:21 pm
The biggest problem with this approach is that when m_components grows, as can happen when you add new elements, two tricky things happen:

1.  It invalidates any Component pointers or references which may currently be in use by your gamesystem code, since the vector moves in memory.  This can lead to some nasty dangling pointer/reference bugs if you're not very careful about when you add components to the vector, in relation to when you operate on components within the vector.
Only if the vectors .size() is equal to its .capacity() will it reallocate. As long as .size() is below .capacity() you are guaranteed that no reallocation will happen and all iterators etc stay valid. So, if you know up-front the maximum number of elements you'll ever need to store you can .reserve() the needed capacity at the beginning and be sure it will never re-allocate.

2.  It calls constructors and destructors on every component in the vector, which can lead to unintended consequences if you treat your constructors and destructors as meaning the entity/component is being created and destroyed in a gameplay sense.
You can avoid that by implementing move constructors and move assignment operators for the objects you store in the vector, since then they can just be moved when the vector reallocates instead of being copied. But remember to make those functions 'noexcept (http://en.cppreference.com/w/cpp/language/noexcept)', since vector will only 'move_if_noexcept (http://en.cppreference.com/w/cpp/utility/move_if_noexcept)' to preserve the strong exception guarantee that C++98 mandates.
Title: Re:creation - a top down action rpg about undeads
Post by: dwarfman78 on May 20, 2015, 08:11:26 pm
i don't want to be nitpicking here but comparing ECS and OOP is like comparing mecanic and an internal combustion engine, one is just an organisation based on the concepts brought by the other. OOP is a paradigm and ECS is a pattern, well it's like you've discovered the lost ark but it exists among many patterns brought in the 90's by the "gang of four".  New paradigm brought by functional programing tends to make most of those design patterns a bit outdated but they still worth something in specific situations.

see here : http://en.wikipedia.org/wiki/Design_Patterns

To be more specific ECS is based on the Composite and Strategy patterns and polymorphism too.

In other words there's nothing wrong with OOP nor something "normal" or not with OOP, inheritance sucks over composition for sure and it tooks us a bunch of years and smell code to realize it, that's all.

btw Elias i'd love to be able to do my own pixel art for my own games as you do, they're very convincing. If i may try to be constructive here i would say that the archer guy is a bit too flashy compared to the other characters.
Title: Re:creation - a top down action rpg about undeads
Post by: dabbertorres on May 20, 2015, 08:59:41 pm
I see the method Jabberwocky is talking about. The idea is that there isn't one vector for all Components, there are multiple vectors, one for each Component type.

I went with something very similar to what he is describing.

One system per component type, which contains a vector of all Components of that type (well in a container I called an "AssocMap" (I should rename it to something like "AssocVector"), which is essentially a combined vector/hash map so I can access Components via entity ID, but also have sequential memory storage. Prolly not a novel concept or even a best solution, but I liked the result).

My System Implementation (https://github.com/dabbertorres/Swift2/blob/ecsRedesign/src/EntitySystem/System.hpp)

Then "entities" are simply an ID number, for which I use just use an unsigned int.

It's a little out of date, I have some changes I haven't pushed yet, but it should get my underlying concept across. :)


Anyway, as others have said, I'm absolutely loving the art and the art style!
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 20, 2015, 09:14:07 pm
Components would no longer be owned by entities; each vector would then store the components of multiple entities in the game.
Yeah, we've had some disscusion about this around the 2nd page of this thread.
I would love to implement this, but I need some ideas to be able to get particular component by its type. Like this:
auto graphicsComponent = componentSystem->get<GraphicsComponent>(entityId);
Any ideas how to do this if I have vectors for each component type in ComponentSystem?

As for creation and destruction of components... I'm thinking about object pools but I wonder how I could make this work, ha-ha.

i don't want to be nitpicking here but comparing ECS and OOP is like comparing mecanic and an internal combustion engine, one is just an organisation based on the concepts brought by the other. OOP is a paradigm and ECS is a pattern, well it's like you've discovered the lost ark but it exists among many patterns brought in the 90's by the "gang of four".  New paradigm brought by functional programing tends to make most of those design patterns a bit outdated but they still worth something in specific situations.
I should have been more exact. When I'm talking about OOP vs ECS, I'm talking about deep hierarchy trees (Entity->Character->NPC->Monster->Dragon etc.) vs ECS approach. Of course, I'm not against OOP. I'm using it a lot in other stuff. But it's not that great for entities and creating new types of stuff. It leads to well known problems and ECS is a great way to get rid of a lot of them!

In other words there's nothing wrong with OOP nor something "normal" or not with OOP, inheritance sucks over composition for sure and it tooks us a bunch of years and smell code to realize it, that's all.
Completely agreed! OOP is great for some things but sucks for others. Composition is not the only way to solve every problem. But ECS stuff is the main core of my engine that's why I talk a lot about it. :)

btw Elias i'd love to be able to do my own pixel art for my own games as you do, they're very convincing. If i may try to be constructive here i would say that the archer guy is a bit too flashy compared to the other characters.
Thanks and good luck! And I appreciate all the feedback so don't worry about providing it. I agree that it archers are more flashy than other characters, but I've yet to draw other characters. There's not many of them, so I'm just experimenting and look what stuff looks good and what stuff does not.
Some variety is good. :)

@dabbertorres, thanks for your idea, I'll see what I can come up with it in mind.
And thanks for your appreciation of my art. That means a lot to me, considering I'm a beginning artist. And I'm very glad that the style I'm doing my art in looks good enough. (It's not the greatest art I can do, but I can't spend a lot of time on art, so I have to throw out some shading, simplify some things, etc.)

Title: Re:creation - a top down action rpg about undeads
Post by: Nexus on May 20, 2015, 09:25:44 pm
I would love to implement this, but I need some ideas to be able to get particular component by its type. Like this:
auto graphicsComponent = componentSystem->get<GraphicsComponent>(entityId);
Any ideas how to do this if I have vectors for each component type in ComponentSystem?
You have to map types to associative keys that share one type and can be used at runtime. There are multiple approaches: integers returned from templates, std::type_index, ...

Type erasure is the keyword here. You have to transform static type information into dynamic one.


By the way, I completely agree with dwarfman78 regarding OOP vs ECS, unfortunately the term "OOP" is often used wrongly because people think of all the things that can be done wrong with it. Some time ago (http://en.sfml-dev.org/forums/index.php?topic=13793.msg96969#msg96969) I wrote something related:
Quote from: Nexus
I think we should not fall in the typical "OOP vs. components" discussion, in my opinion the view that these concepts are contradictory is a misunderstanding. Often, OOP is associated with overused inheritance and unflexible class hierarchies, and people forget that a entity component system is built on top of most OOP features, too (purists could even consider ECS as a sort of design pattern, but probably there's already another name for it).

Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 20, 2015, 09:31:46 pm
Type erasure is the keyword here. You have to transform static type information into dynamic one.
std::type_index is pretty cool, but how can I map it to particular std::vector?
std::map<std::type_index, std::vector<T>> componentVectors
would be cool to have but I can't do that. What are possible ways to do this?

So, this is what I hope to get:
T* getComponent<T>(int entityId) {
    auto componentVector = ...; // get vector!
    return &componentVector[entityId]; // and some error checking there, of course
}

By the way, I completely agree with dwarfman78 regarding OOP vs ECS, unfortunately the term "OOP" is often used wrongly because people think of all the things that can be done wrong with it. Some time ago (http://en.sfml-dev.org/forums/index.php?topic=13793.msg96969#msg96969) I wrote something related:
Quote from: Nexus
I think we should not fall in the typical "OOP vs. components" discussion, in my opinion the view that these concepts are contradictory is a misunderstanding. Often, OOP is associated with overused inheritance and unflexible class hierarchies, and people forget that a entity component system is built on top of most OOP features, too (purists could even consider ECS as a sort of design pattern, but probably there's already another name for it).
Yeah, I'll be talking about "deep hierarchy/inheritance trees" in the future because it seems to be a lot more accurate term.
Title: Re:creation - a top down action rpg about undeads
Post by: Jabberwocky on May 20, 2015, 09:46:05 pm
How do I store different components in one vector?

Ahh, right!  I somehow missed that you stored your components in the Entity, rather than in the system.  As dabbertorres pointed out (heh), this only works if you store your components in a system, not in the entity.

So there's a system for each component type, e.g. PhysicsSystem which stores a vector of Physics components, e.g.

class PhysicsSystem
{
public:
   // called per-frame.
   // iterates over and updates every Physics component in the game as required
   void Update();

   // retrieve a Physics component
   // simple implementation, in real life you'd want bounds checking
   Physics* GetPhysics(unsigned int index) { return m_physicsComponents[index]; }

   Physics*  CreatePhysics(...);
   void DestroyPhysics(unsigned int index);

private:
   std::vector<Physics> m_physicsComponents;
}
 

You can use c++ templates to make this work for any component in the game, although again this approach is more complex than you need for many types of games.

An Entity is then just a collection of components like this:

enum ComponentType
{
   Physics,
   Graphics,
   // etc...
};

class Entity
{
private:
   // Maps a ComponentType to the index of the component, which must be looked up
   // via the corresponding ComponentSystem.
   // (This particular implementation does not support multiple components of the same type.)
   std::map<ComponentType, unsigned int> m_components;
};


1.  It invalidates any Component pointers or references which may currently be in use by your gamesystem code, since the vector moves in memory.  This can lead to some nasty dangling pointer/reference bugs if you're not very careful about when you add components to the vector, in relation to when you operate on components within the vector.
As a solution to this problem, typical ECS implementations use a sort of handles (e.g. integers containing information to index) instead of pointers and references.

For sure, handles are the way to go.  But even then you can run into trouble.  At some point, you need to turn a handle into a pointer or a reference to call functions on it. 

Here's an example of where you might get into trouble.

void SummonPet(Entity* pEntity)
{
   // ...

   // check my Mana component (or Vitals component, or whatever) to see if I have
   // enough Mana to summon the pet.
   int nManaToSummon = 10;

   Mana* pMana = ManaSystem::GetMana(pEntity);
   if (pMana->GetCurrent() < nManaToSummon)
   {
      return false;
   }

   // ... code to create pet entity here ...

   // decrement mana
   pMana->DecrementCurrent(nManaToSummon);
   // *** CRASH ***
   // The ManaSystem's vector of Mana component may have shifted,
   // because we created a new Entity (the pet) which may itself have required a Mana
   // component, and called ManaSystem::CreateMana.  This invalidates our pMana
   // pointer (dangling pointer bugs, ew!).

   return true;
};
 

____________

re:  move constructors and move assignment operators:

Yep, this is totally one way to solve the problem.

Another way is to just rely on the default destructors and constructors (bitwise copy), for your components, and control your component's lifetimes with a Component::Init() and Component::Destroy() function, which is where you would handle any dynamic mem allocation, for instance.
Title: Re:creation - a top down action rpg about undeads
Post by: Nexus on May 20, 2015, 09:46:14 pm
std::map<std::type_index, std::vector<T>> componentVectors
would be cool to have but I can't do that. What are possible ways to do this?
Type erasure, as I said.
struct ComponentVectorBase
{
    virtual ~ComponentVectorBase();
};

template <typename T>
struct ComponentVector : ComponentVectorBase
{
    std::vector<T> components;
};
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 20, 2015, 09:51:51 pm
@Jabberwocky Thanks for your ideas!
But I'm afraid I need more generic approach to do this, because not every component has it's own system and I currently have 18 types of components. Who knows how many I'll add in the future?

@Nexus Oh yeah, that'll do it. Thanks!
Title: Re:creation - a top down action rpg about undeads
Post by: Jesper Juhl on May 20, 2015, 09:55:08 pm
re:  move constructors and move assignment operators:

Yep, this is totally one way to solve the problem.

Another way is to just rely on the default destructors and constructors (bitwise copy) ...
Where do you get the "bitwise copy" notion from?
The default copy ctor does not do a bitwise copy - it does a member by member copy.
And if you are memcpy()'ing (a bitwise copy) an object, then it better be std::is_pod (http://en.cppreference.com/w/cpp/types/is_pod) / is_trivially_copyable (http://en.cppreference.com/w/cpp/types/is_trivially_copyable).

What exactly do you mean?
Title: Re:creation - a top down action rpg about undeads
Post by: Nexus on May 20, 2015, 10:05:34 pm
Here's an example of where you might get into trouble.
True, but as a user of such an ECS you have to be aware that any change to the structure of the components (their addition or removal) invalidates all component pointers and references. That's why you would re-acquire a pointer from the handle.

A component handle can also be encapsulated, so that you don't have to call getComponent() again and again:
ComponentHandle<C> h(components, entity);
C& component = h.get(); // or simply *h

By the way, before everyone reinvents the wheel here: EntityX is a nice ECS library for C++. I don't like too much how it mixes its event system in, and the fact that they provide multiple syntaxes for everything obscures the API a bit, but design-wise, it's definitely worth having a look at. Keep in mind that one tends to overengineer quite a bit when delving too deep into possible optimizations; you should stay realistic about your game's scope before incorporating all kinds of features and neat tricks that you can never exploit.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 20, 2015, 10:12:08 pm
Keep in mind that one tends to overengineer quite a bit when delving too deep into possible optimizations; you should stay realistic about your game's scope before incorporating all kinds of features and neat tricks that you can never exploit.
Totally. That's why I won't rebuild my ECS in near future (maybe when I have some spare time to experiment...). Making stuff like this is fun but I have no problems with perfomance now. My main focus is getting game to very playable state so I can release some demo for people to play around with and give me their feedback. I hope to finish it by the end of this summer. I'm feeling pretty anxious about it, so the demo won't we public for some time, I guess. :)

And I'll take a lot at EntityX some time.
Title: Re:creation - a top down action rpg about undeads
Post by: Jabberwocky on May 20, 2015, 10:26:27 pm
Yep, honestly for a smallish-type game, I think your more simple ECS approach is probably best, Elias.  Like I said earlier, it gives all the flexibility of an ECS, a clean simple solution, but just not the performance benefits (which you likely don't need).


Where do you get the "bitwise copy" notion from?
The default copy ctor does not do a bitwise copy - it does a member by member copy.
And if you are memcpy()'ing (a bitwise copy) an object, then it better be std::is_pod (http://en.cppreference.com/w/cpp/types/is_pod).

What exactly do you mean?

Oh, yeah sorry.  That was confusing on my part.

What I mean is that normally the constructor, copy constructor, assignment operator and destructor is where you would (de)allocate new memory, if needed.  For example, let's say I have an ActiveEffects component, which stores what effects (e.g. spells in an RPG) an entity is currently affected by.

// This is a component which stores effects on an entity
class ActiveEffects
{
private:
   // These are the individual effects which this entity has.
   // e.g. Maybe I cast a spell called "wind runner" on myself that makes me run fast.
   // I need Effect* pointers because there are different kinds of Effect subclasses,
   // e.g.  MoveSpeedEffect, AttributeBoostEffect, etc.
   std::vector<Effect*> m_effects;  
};

Normally, you'd see those pointers and think, I need to write a whole lot of constructor/copy constructor/assignment operator/destructor logic, or I might end up with memory leaks or duplicate pointers. 

For example, your copy constructor might look like this:

ActiveEffects::ActiveEffects(const ActiveEffects& i_rhs)
{
   std::vector<Effect*>::const_iterator it = i_rhs.m_effects.begin();
   std::vector<Effect*>::const_iterator end = i_rhs.m_effects.end();
   for(; it != end; ++it)
   {
      const Effect* pOriginal = *it;
      // This next line doesn't even actually work, because Effect* is pointing at
      // a subclass, but you get the idea...
      Effect* pCopy = new Effect(*pOriginal);
      m_effects.push_back(pCopy);
   }
}
 

So, now every time your vector of ActiveEffect components moves in memory, the copy constructor and destructor is called on every each one.  This is a whole bunch of newing in the copy constructor, and a whole lot of deleting in the destructor.  That's really stupid, because we aren't changing any effects.

Move constructors can solve this.  But now every component in the game, and every data member they contain needs to have:

That's fine, and that's what they're designed for.But my approach is to skip all of those.

The default copy constructor does exactly what I want - it copies the pointers without newing or deleting the Effects.  But that means I can't delete any memory in the destructor (if I did, I would delete all my Effects every time the ActiveEffects vector grew).  Instead, I put my destructor logic in a function called Component::Destroy(), which is called by the ComponentSystem whenever we actually want to destroy a component, rather than just moving it.

Haha, wow this thread is going crazy.  2 new posts while I was typing this up!  Interesting game and tech discussion, I guess.  :)
Title: Re:creation - a top down action rpg about undeads
Post by: Jabberwocky on May 20, 2015, 10:39:33 pm
True, but as a user of such an ECS you have to be aware that any change to the structure of the components (their addition or removal) invalidates all component pointers and references. That's why you would re-acquire a pointer from the handle.

Totally agreed.  That's all I was saying, too. 
Title: Re:creation - a top down action rpg about undeads
Post by: Nexus on May 20, 2015, 10:52:38 pm
Move constructors can solve this.  But now every component in the game, and every data member they contain needs to have:
  • assignment operator
  • move assignment operator
  • copy constructor
  • move constructor
Yes, but that doesn't mean the user has to implement them all. For move constructor and assignment operator, he can benefit from the = default mechanism.

The problem is that you're using raw pointers to store memory, which is generally a bad idea (http://www.bromeon.ch/articles/raii.html). If you used std::unique_ptr instead, then destructor and move ctor/op= would come for free.

If you additionally need copy semantics, you can use aurora::CopiedPtr (http://www.bromeon.ch/libraries/aurora/v1.0/tutorial-smartptr.html), and things will just work fine. This smart pointer deep-copies through polymorphic hierarchies.
class MyClass
{
   std::vector<aurora::CopiedPtr<Effect>> effects;
};

MyClass origin = ...;
MyClass copy = origin; // BAM, deep-copy.

This is a really powerful idiom, I still wonder why not even Boost has something alike. Anyway, Aurora does :D


The default copy constructor does exactly what I want - it copies the pointers without newing or deleting the Effects.  But that means I can't delete any memory in the destructor (if I did, I would delete all my Effects every time the ActiveEffects vector grew).  Instead, I put my destructor logic in a function called Component::Destroy(), which is called by the ComponentSystem whenever we actually want to destroy a component, rather than just moving it.
Yes, that's also a possibility. The problem here is that you have to be extra-careful to call the right functions, while constructors and destructors impose a class invariant that guarantees this. For example, with exceptions, the manual calls can easily be forgotten.

@Elias: Tell us if we're going too much off-topic here, then we can continue in another thread ;)
Title: Re:creation - a top down action rpg about undeads
Post by: dwarfman78 on May 20, 2015, 10:53:17 pm
Make games not ECS. 8)

(click to show/hide)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 21, 2015, 08:47:02 am
Some great discussion happening here. ;)

I've posted new dev log on my blog: https://eliasdaler.wordpress.com/2015/05/21/recreation-dev-log-april-may-2015/
It covers what I did in last two months. I'm pretty proud about the progress!
Title: Re:creation - a top down action rpg about undeads
Post by: dwarfman78 on May 21, 2015, 10:19:05 am
Hi Elias, i am wondering as you're using lua scripts, do you intend to let the user modify them ? If not how are you going to package them ?
Title: Re:creation - a top down action rpg about undeads
Post by: eXpl0it3r on May 21, 2015, 11:28:58 am
He's using Lua and as stated before, he won't really pack them, because yay modding! :D
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 21, 2015, 06:02:08 pm
^ This. I've answered it here  (http://en.sfml-dev.org/forums/index.php?topic=18062.msg130620#msg130620)

For those who may have missed (damn it, my post was the last on the page!)

New dev log is here! (https://eliasdaler.wordpress.com/2015/05/21/recreation-dev-log-april-may-2015/)

I've made lots of stuff and I want you to check it out. ;)
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on May 21, 2015, 06:07:26 pm
I've just read your dev log and I honestly can't say enough good things about this. The callback system is brilliant and I think I'll try and put that sort of thing into the next game I make.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 21, 2015, 06:56:27 pm
I've just read your dev log and I honestly can't say enough good things about this. The callback system is brilliant and I think I'll try and put that sort of thing into the next game I make.
Thanks! You should definitely try. C# has that system already(events and delegates) and I needed to implement something similar in C++.
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on May 21, 2015, 07:01:30 pm
Did you use std::tr1::function for callbacks, or did you just let each class store references to all its observers, each of which would have a function that can be called (probably via inheritance)?
Title: Re:creation - a top down action rpg about undeads
Post by: Lo-X on May 21, 2015, 07:31:38 pm
Did you use std::tr1::function for callbacks

You can use std::function without ::tr1 for a little while now :)

Quote
gui->registerCallback(&GUIPlayingState::onHpChange);
player->addObserver(gui);
 
 
void GUIPlayingState::onHpChange(int senderId, const std::shared_ptr& e) {
    auto event = std::dynamic_pointer_cast(e);
    int hp = event->hp;
    ... // do some stuff!
}

With that code, how do you do the link between you HpChangedEvent and the right callback to call (as your registerCallback() method doesn't take the type of event as parameter. And how do you register callbacks with different signatures ?


I don't like that way of doing so much, because everything is done at execution. Plus you have to tell your Subject class (in that case Player) when the Observer is destroyed.
I prefer compile time Event Systems, zagabar has a good one in his Featherkit lib using structs. Again I guess it's harder to bind such a system to Lua compared to a simple Observer pattern (which does the job well anyway).
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 21, 2015, 07:36:12 pm
Did you use std::tr1::function for callbacks, or did you just let each class store references to all its observers, each of which would have a function that can be called (probably via inheritance)?
Yep, I use std::function (no need to write tr1 in C++11).
Basically, Observer has std::map<std::type_index,std::function> callbacks and onMessage function which just calls callbacks[type_index_of_event].
When Subject fires an event, it calls onMessage function of each observer.

With that code, how do you do the link between you HpChangedEvent and the right callback to call (as your registerCallback() method doesn't take the type of event as parameter. And how do you register callbacks with different signatures ?

I don't like that way of doing so much, because everything is done at execution. Plus you have to tell your Subject class (in that case Player) when the Observer is destroyed.
I prefer compile time Event Systems, zagabar has a good one in his Featherkit lib using structs. Again I guess it's harder to bind such a system to Lua compared to a simple Observer pattern (which does the job well anyway).
Oops, I should fix that. RegisterCallback takes event type as a template argument and maps a function to this type of events.
This should answer all your questions.

I'll check out compile time Event Systems. My system is just one of the first ones I've come up with. Maybe I'll find something more convenient and awesome. :)
Title: Re:creation - a top down action rpg about undeads
Post by: Lo-X on May 21, 2015, 07:47:12 pm
This should answer all your questions.

I'll check out compile time Event Systems. My system is just one of the first ones I've come up with. Maybe I'll find something more convenient and awesome. :)

Yes it does answer ! Maybe the template parameter has been considered as HTML, does happen sometimes on blogs.

The observer pattern way is fine, there's nothing wrong with what your doing. I just wanted to point out other way of achieving messaging, with different pro and cons.

Anyway your game isn't just amazing to see, the code looks nice even if we just have the right to see snapshots :)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on May 21, 2015, 09:18:09 pm
Yes it does answer ! Maybe the template parameter has been considered as HTML, does happen sometimes on blogs.

The observer pattern way is fine, there's nothing wrong with what your doing. I just wanted to point out other way of achieving messaging, with different pro and cons.

Anyway your game isn't just amazing to see, the code looks nice even if we just have the right to see snapshots :)

Nah, I probably just forgot to add it. ;)

I like to look at different approaches, so I appreciate when people tell me about different ways of achievening something I did.

And thanks for you kind words! I try to keep my code clean and nice and I'm really proud that people see it.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on June 02, 2015, 01:14:33 pm
So, I didn't have time to work on the game last week because I had to study a lot. I still have to study a lot (exams are coming...) but I now have more free time so I can slowly work on the game. I'm working on the dungeon level now. It's coming along nicely.
So, here's a new screenshot:
(http://i.imgur.com/CVZqnlF.png)
This witch (actually a powerful necromancer!) will help you a lot on your quest. How? I'll tell a bit later when I finish some animations. ;)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on June 08, 2015, 12:14:16 am
Still working on necromancer grandma. Drew a portrait. Still work in progress. :)
(http://i.imgur.com/ItlRxMd.png)

P.S. Also have some cool ideas for a level called Ghost Town. This was a town full of musicians but all its population is dead now and travels in ghost form. They can't return even become undeads... Why? I won't spoil it, you'll see for yourself later! :D
Title: Re:creation - a top down action rpg about undeads
Post by: JackPS9 on June 08, 2015, 02:00:20 am
Elias, please dont take this wrong only asking cause of your forum profile pic.
But is that necro grandma a family member?
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on June 08, 2015, 07:38:26 am
Elias, please dont take this wrong only asking cause of your forum profile pic.
But is that necro grandma a family member?
Ha-ha, no. I just drew my profile pic as a portrait inside the game.
But thanks for the question, it's great. :D
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on June 10, 2015, 12:54:35 am
I've been working on a platform puzzle (sorry, some tiles are not finished yet!).

See this platform? When you step on the button, it moves in another direction. When you step off the button, it moves as it did before.
(http://i.imgur.com/hqhB826.gif)

You can try to jump on the platform, but what's the point of it? You'll be returned back!
(http://i.imgur.com/rtqc56G.gif)

You have to use recreation to solve that thing. ;)
Title: Re:creation - a top down action rpg about undeads
Post by: ChronicRat on June 10, 2015, 11:28:52 am
You're tricky! =)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on June 11, 2015, 07:04:06 pm
You're tricky! =)
Yeah  ;)
Title: Re:creation - a top down action rpg about undeads
Post by: Jabberwocky on June 12, 2015, 04:03:38 am
Definitely a nifty game mechanic you've got going on, Elias.  Thanks for the updates.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on June 12, 2015, 10:29:02 am
Definitely a nifty game mechanic you've got going on, Elias.  Thanks for the updates.
Thanks! And thank you for reading them and giving feedback. :)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on July 08, 2015, 07:35:36 pm
Progress update
I've had lots of exams and successfully passed all of them. This means that I have two months which I can devote to my game. Lots of updates incoming!
 
I've spend some days paying off my "programmer's debt". Lots of bugs were fixed and lots of stuff was optimized. There isn't much to talk about there.
I'll talk about cooler stuff instead.

Forest
(http://i.imgur.com/2qq9TJH.png)
I've spent lots of time redrawing forest tileset. Lost of grass, flowers and cliff tiles... Compare it to the old screenshot:
(http://i.imgur.com/bA5XdJJ.png)

Quite a difference, don't you think?

Tile patterns in level editor
(http://i.imgur.com/rrI5iEb.gif)

This is very handy for level editing. For example, forest tileset has two grass tiles. They alternate between each other in checkboard pattern. Making it all by hand is just too slow, so I made tile patterns scriptable!

Here's how grass pattern script looks:
{
        tileId = 10, -- if this tile selected, pattern below is pasted
        pattern = {
            { 10, 37},
            { 37, 10}
        }
},

10 is first grass tile ID. 37 is another grass tile ID.
When some area is selected, I can press "P" to fill it with current tile's pattern. Each tile can have a corresponding pattern. Patterns can be of any size and it's useful for any stuff that has similar structure.

Input

I've spent some time making input more abstract. I can now save and load input bindings.
I already had a simple input manager which helped me check when some button is pressed, held or released.
Now it's even more abstract. Instead of checking for specific key in C++ code, I check for button tag.
Here's how I check for input now:
if(inputManager->isKeyHeld(ButtonTag::PrimaryAction)) {
...
}
 
Each ButtonTag has a corresponding sf::Keyboard::Key. 

I've also added gamepad support which was a bit harder to make abstract because Dpad and Sticks are not buttons, they have axes. What made it even worse is that coordinate systems for D-pad and left stick differ (so, when up is pressed on the D-pad PovY axis is 100. But when up is pushed on the left stick Y axis is -100!). This was easily fixed and gamepad works fine now.

Future plans
And that's just the beginning. I have lots of plans and ideas and I'm currently remaking some old levels to make them better and more interesting.
I'll have lots of cool stuff to show off soon (new NPC's, new art, some puzzles and all that stuff), so stay tuned!
Title: Re:creation - a top down action rpg about undeads
Post by: Brax on July 08, 2015, 08:25:50 pm
This is awesome!!!  :o
Great work!
Title: Re:creation - a top down action rpg about undeads
Post by: ChronicRat on July 08, 2015, 08:53:23 pm
Quote
Quite a difference, don't you think?
What was changed? =) Ah, flowers, yes, much better.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on July 08, 2015, 09:08:52 pm
This is awesome!!!  :o
Great work!
Thanks!

Quote
Quite a difference, don't you think?
What was changed? =) Ah, flowers, yes, much better.
Ha-ha, thanks. Flowers, grass (spent lots of time redrawing it, totally worth it because it's more natural and less blocky now) and I've added some cliffs :)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on July 16, 2015, 01:10:33 pm
Okay, this is going to get very technical. :D

I've been working for several days on a new Event Manager. Event manager is very important because it helps me decouple stuff and optimize perfomance a lot.
Previously I had a simple subject/observer system which let observers to subscribe to subjects and provide a callback function which was called if the subject sent an event. But it had some issues: messages could only be sent immediately and for some object to become observer/subject its class should inherit IObserver/ISubject classes. This caused lots of recompilation each time I realized that some object needed to become an observer or a subject and adding new events when they were already sent caused some troubles too.

So I've decided to completely remake event system and add some cool features.
I've made an event queue and got rid of IObserver/ISubject classes.
Each time something needs to send an event, it adds it to the global event queue.
If some entity subscribes to an event of this type, its callback is called during Event Manager sendMessages() function

Here's how objects can subscribe to events:
SomeClass obj;
engine_system.eventM->addListener<SomeEvent>(&obj, &SomeClass::onSomeEvent);

And here's how they can send them:
auto event = std::make_shared<SomeEvent>();
event->someParam = someValue;
engine_system.eventM->queueEvent(event);

I can later get event's parameters by casting them in a callback which is called during EventManager's sendMessages() function:
void SomeObj::onSomeEvent(const std::shared_ptr<Event>& e) {
    auto event = std::dynamic_pointer_cast<SomeEvent>(e); // this is totally a SomeEvent, because this function is called
                                                          // only when e has this type
    std::cout << event->someParam;
}

Callbacks are implemented using std::function and std::bind and here's how they should look:
void Class::CallbackFunc(const std::shared_ptr<Event>& e)

Objects can also subscribe to certain entities to receive events only from them. (Objects receive messages from everyone by default)

For example, GUIPlayingState only needs to know when player's hp changes, so it adds a playerEntity as a subject:
engine_system.eventM->addListener<HpChangedEvent>(&gui, &GUIPlayerState::onPlayerHpChanged);
engine_system.eventM->addSubjectToListener<HpChangedEvent>(&gui, playerEntity);
 

But it doesn't stop here!
I've implemented Lua/C++ event manager too!

Previously, if I needed to observe another entity's state, I called update() entity function in every frame. For example, if a bridge is lowered when a button is pressed, this function was called:

bridge.update = function(bridgeEntity)
    local button = getEntityByTag("BRIDGE_BUTTON")
    if(getScriptState(button) == "ButtonPressedState") then
        setScriptState(bridgeEntity, "BridgeLoweredState")
    end
end

This is obviously not a great solution, because calling this function 60 times per second may be expensive.  It also sucks that I need to check button's state every frame and this may be very expensive too. Especially if lots of entities have their own update functions.

Event manager fixes that problem by calling a callback function only when the button's state changes.

Entities can add callbacks in Lua this way:
addLuaListener(entity, "SomeEvent", func) -- func is some Lua function

They can also subscribe to entities:
subscribeToSubject(entity, "SomeEvent", subjectEntity)

Each time an event is queued in C++ or Lua, both C++ and Lua callbacks are called. And this it very cool, because it makes communication between Lua and C++ even simpler than before.

 Lua callbacks get an event table which can be used to get parameters:
f = function(event)
    print(event.someParam)
end

So, here's how the bridge can subscribe to the button:
addLuaListener(bridge, "ScriptStateChangedEvent", bridge.onBridgeButtonPressed)
subscribeToSubject(bridge, "ScriptStateChangedEvent", button)
   
And here's how a callback looks like:
onBridgeButtonPressed = function(this, event) -- this function is called every time button entity changes its state
    if (event.currentStateName == "ButtonPressedState") then
        setScriptState(bridge, "BridgeLoweredState")
    end
end

In C++ ScriptStateComponent emits ScriptStateChangedEvent everytime a state is changed. Then a callback Lua function gets called. This works!

The implementation is pretty difficult and required lots of template magic, error checking and optimization, so it would take me far too long to write about everything. Ask me any questions and I'll try to answer them. Maybe you have your own cool Event Manager: tell me about it!
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on July 17, 2015, 11:57:57 pm
New title screen. You select menu item with a ghost, just like you select corpses in the game! :D
(http://i.imgur.com/aWgFTlh.png)

Also, meet the Master of Recreation

Dialogue portrait:
(http://i.imgur.com/4dzbUGD.png)
In game sprite:
(http://i.imgur.com/c4jYUBm.png)

This man will teach you some neat combat lessons and he'll show you main principles of recreation technique.

I'm currently working on the tutorial part of the game. I'm trying to make it fun and sometimes unexpected.
I also came up with different situations which will show main concepts of recreation in practice, instead of just displaying them on screen. More of that later!
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on July 23, 2015, 10:48:47 pm
Re:creation TIGSource dev log thread is LIVE!  ;D
http://forums.tigsource.com/index.php?topic=49336.0
This doesn't mean much for people who read this thread, as I would post in both SFML and TIGSource threads. But this may probably give more attention to my game. I would like to hear your reactions in TIGSource thread too.

Btw, I've drawn new death animations and cliff tiles. Here's how the bridge puzzle looks now:
(http://i.imgur.com/u9CYS5p.gif)
I think it's looks less confusing than it did before. (http://i.imgur.com/jJ0qLxR.gif) (also a bit prettier, I think)

I also have some other cool things to show off and I will do it tomorrow, so stay tuned!
Title: Re:creation - a top down action rpg about undeads
Post by: Tank on July 24, 2015, 09:02:59 am
Personally I liked the gravestones, it gave the game some kind of charm in the world of dead bodies. ;)

Cliff tiles look neat.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on July 24, 2015, 11:25:22 am
Personally I liked the gravestones, it gave the game some kind of charm in the world of dead bodies. ;)

Cliff tiles look neat.

I liked them too, but those gravestones make gameplay a little bit confusing, because you don't see who're going to become. And thanks :)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on July 24, 2015, 01:38:59 pm
(http://i.imgur.com/ecDUZ3q.gif)
Gravestones are back. Now the player can see who's lying in the grave by looking at the weapons near graves!
(http://i.imgur.com/TV3Tl6U.png)
Title: Re:creation - a top down action rpg about undeads
Post by: dabbertorres on July 24, 2015, 06:11:52 pm
Talk about a developer listening to feedback!  ;D

Ok, I actually have a question, though it's more art than programming. Maybe it'd be better for twitter. Oh well.

How do you draw the game's perspective? With the game's sprites, I mean.
You have the "half top-down, half at-an-angle" perspective down really well I think.

Is it all in the art, or are you doing something on the programming side as well?

I've tried drawing sprites in that perspective as well, and I just can't seem to be satisfied with the results. I've never claimed to be an artist though. :)

So, I guess, main question is: Do you have any tips for drawing sprites in the perspective you have in Re:creation?
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on July 24, 2015, 06:37:35 pm
To add on to dabbertorres' questions I have a few of my own.
With the name "Re:creation", where did the colon come from? I actually thought up until now that you'd put two colons as a sort of coding mini-easter egg of having the scope operator in the title, but I just reread it.
Also, if you're open to suggestions I have a few (I appreciate that you can't just put everything everyone thinks of into your game, but if you like any of the suggestions, then please use them).
Slightly changing an enemy's appearance when you possess them. Mainly for convenience if there is a large group of the same type of enemy then it would get confusing as they all look the same as the one you control. Maybe a different skin tone.
An enemy (maybe a wizard of some sort) that can be possessed and has special abilities which mean that you need to possess them, but slowly saps your health when you do.
Ghosts that can possess your body while you are in ghost form and use it to attack you.

Finally, I thought my previous posts of how amazing this is weren't enough so a few more things that I really like, especially about the recent update.
The little flick of the arrow when it hits something is brilliant. It's the tiny details that make games like this great.
The animation of the grave coming out of the ground is really smooth and in general the animation you've done is brilliant.
I'm not sure how, but you've actually managed to make a grass tile that doesn't look repetitive.
:D
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on July 24, 2015, 09:49:39 pm
@dabbertorres Feel free to ask all types of questions here. Stuff gets lost on twitter, it's more accessible for other people there! :)
I've actually written the article about top-down drawing.
Here it is! (https://eliasdaler.wordpress.com/2013/11/20/z-order-in-top-down-2d-games/)
I've optimized it a bit. You can actually sort static (non-moving) objects by z-order only once they're created on the level. Dynamic (moving) objects need to be sorted each frame, and then you can quickly merge them with static object list in O(n) and then render it in the order which is explained in the article. If you have tons of moving objects, you may want to use grid partitioning to sort objects which are in one cell and then merge this stuff together.

With the name "Re:creation", where did the colon come from?
Ha-ha, I came up with this name when this game was a post-apocalyptic steam-punk rpg. So, it's kinda like someone said a reply to an e-mail with the subject "Creation".
 Lots of things have changed since then and I came up with a recreation mechanic. And I thought "Hey, this title still works!". As for colon: it has no meaning now. But I think it makes a game title more recognizable. I might change it someday to something like "The Recreation of Undead Knight" or "The Recreation of Undead *name of the hero*".

Slightly changing an enemy's appearance when you possess them. Mainly for convenience if there is a large group of the same type of enemy then it would get confusing as they all look the same as the one you control. Maybe a different skin tone.
It's already done. Maybe it isn't very obvious, but here's how normal and undead versions of the same NPC look like:
(http://i.imgur.com/R0K6dFK.png)

An enemy (maybe a wizard of some sort) that can be possessed and has special abilities which mean that you need to possess them, but slowly saps your health when you do.

That's a good idea :)

Ghosts that can possess your body while you are in ghost form and use it to attack you.

I've thought about it! :)
Maybe I'll come up with puzzles in which the player will have take care of his body, so nobody would be able to do harm to it. So you'd need to lock yourself in cells, block all paths with some objects, etc.! :D

Finally, I thought my previous posts of how amazing this is weren't enough so a few more things that I really like, especially about the recent update.
The little flick of the arrow when it hits something is brilliant. It's the tiny details that make games like this great.
The animation of the grave coming out of the ground is really smooth and in general the animation you've done is brilliant.
Thanks a lot! Sometimes I spend lots of time trying to fit those little details into tiny sprites. And it's worth it most of the time.

I'm not sure how, but you've actually managed to make a grass tile that doesn't look repetitive.
:D
Here's how.
(http://i.imgur.com/6poH6Ie.png)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on July 24, 2015, 10:31:56 pm
Progress update

Here's a tileset I've been working on for the past week! (Do you recognize the painting? ;))
(http://i.imgur.com/9sOqc3Y.png)
This is a house of Master of Recreation. He's the guy who will teach you the main principles of recreation and some combat stuff.
This tileset is quite reusable and I'll use it in other houses as most games do.

You can also go into buildings now.
(http://i.imgur.com/3Qv3tNy.gif)
This was quite interesting to make, because it involved attaching AIComponent to the player.
First, door's state is changed to "DoorOpenedState". Then I disable player's CollisionComponent (so he can go through houses's collision box). This is much more easier than making multiple collision boxes for houses.
Then a target inside the house is set and AI turns on, so the character walks in without player doing so. Then a transition effect happens and another target for AI is set and the character goes there. After he arrives at destination, AI turns off and  player can control the character again. CollisionComponent is enabled. Pretty easy and works perfectly well.
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on July 25, 2015, 12:57:12 pm
it's kinda like someone said a reply to an e-mail with the subject "Creation".
This is how I always thought it looked  ;)

You can also go into buildings now.
(http://i.imgur.com/3Qv3tNy.gif)
There's a pretty obvious tile edging visible in this GIF. When the player enters the building, the map moves to the right twice. The second time, a lot of vertical edges flash.

I'm impressed with the progress on this project. Good work  :)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on July 25, 2015, 01:17:35 pm
There's a pretty obvious tile edging visible in this GIF. When the player enters the building, the map moves to the right twice. The second time, a lot of vertical edges flash.
Yeah, this is something I really need to fix. I think it's because the camera's sf::View  has non-integer coords. I have to find a way to make sprite stay in the center of the screen. (It shakes a lot if I just use std::round for sf::View's coords)

I'm impressed with the progress on this project. Good work  :)
Thanks a lot!
Title: Re:creation - a top down action rpg about undeads
Post by: UroboroStudio on July 25, 2015, 02:00:04 pm
Great stuff over here!

I like this proyect, it reminds me the old school rpg but with modern ideas. Nice work!

The possesion mechanic is original and a lot of puzzles can be made around this.

Also, let me say, your code is very good and clean. Personally I don't like the composite pattern, I feel more natural and comfortable with hierarchy. But I see similarities in how approach the game structure.

In our game, we also do a z-order rendering but only with entities visible on screen, so we need to filter firts. The average map size is 8000x6000, with 15-25 rooms and 25-100 objects, depending of the room size. So yes, we need to filter the amount of entities to be drawn, and tilesets is the way to go.

Early in the development I used polimorphism to manage the differents enemy types, but adding LUA remove any need of polimorphism and the AI is purely made of lua scripts.

Also I like the way you managed the triggers and events in the game, is similar to ours, and this way is very flexible and customizable.

And believe me, as a programmer, I kwnow how hard and frustating can be doing your own art, but the results are worth it. Good job!

Keep it up!  :)
Title: Re:creation - a top down action rpg about undeads
Post by: Lo-X on July 25, 2015, 03:57:16 pm
I'm so glad you keep us up to date with your project, specially when you provide tech stuff :) Awesome work
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on July 25, 2015, 05:44:03 pm
@UroboroStudio Thanks a lot for you feedback! And thanks for providing info about your game.
Entity/component/system just makes it easier to create new types of objects with scripts only. No need to write classes, it's pretty cool. :)

@Lo-X Thanks! I'm glad to post updates too! :)

Also, here's a side attack animation I've made. It makes hits very satisfying!
(http://i.imgur.com/b3J3jOa.gif)
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on July 26, 2015, 01:41:29 am
...tile edging...
Yeah, this is something I really need to fix. I think it's because the camera's sf::View  has non-integer coords. I have to find a way to make sprite stay in the center of the screen. (It shakes a lot if I just use std::round for sf::View's coords)
Have you considered pre-rendering to a render texture? Non-integer values can then be used without edging artifacts.
Title: Re:creation - a top down action rpg about undeads
Post by: FRex on July 26, 2015, 06:11:21 am
Or you could try that renderer (evil self promotion :P): https://github.com/SFML/SFML/wiki/Source%3A-ShaderTileMap
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on July 27, 2015, 07:33:10 pm
Have you considered pre-rendering to a render texture? Non-integer values can then be used without edging artifacts.
Just tried it. Works well most of the time, but there are some artifacts when the camera is shaking a lot. Pretty strange. Are there any examples of doing this properly?

Or you could try that renderer (evil self promotion :P): https://github.com/SFML/SFML/wiki/Source%3A-ShaderTileMap
Sorry, that would require changing lots of stuff I've already wrote :S
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on July 27, 2015, 07:59:27 pm
Have you considered pre-rendering to a render texture? Non-integer values can then be used without edging artifacts.
Just tried it. Works well most of the time, but there are some artifacts when the camera is shaking a lot. Pretty strange. Are there any examples of doing this properly?
I'm not sure there is much to do 'properly'  ;D
What artifacts are you getting? I'm assuming that you're rendering to integer values on a render texture and then displaying the render "sprite" at non-integer (if required) and applying camera shake to this sprite.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on July 28, 2015, 09:22:40 am
Have you considered pre-rendering to a render texture? Non-integer values can then be used without edging artifacts.
Just tried it. Works well most of the time, but there are some artifacts when the camera is shaking a lot. Pretty strange. Are there any examples of doing this properly?
I'm not sure there is much to do 'properly'  ;D
What artifacts are you getting? I'm assuming that you're rendering to integer values on a render texture and then displaying the render "sprite" at non-integer (if required) and applying camera shake to this sprite.

Yes, I'm rendering to integer values and then randomly change view's position (non-integer coords).
I'll try it on a more simple examples, maybe I'm doing something wrong. :S
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 01, 2015, 10:30:24 pm
Nothing special to show off: I'm mostly refactoring my code and making some code a lot better :D
But I've made ladders today:
(http://i.imgur.com/xF1IWB5.gif)
The perpective is quite off, so I'll be working on that!
Title: Re:creation - a top down action rpg about undeads
Post by: Tank on August 03, 2015, 09:24:31 am
I wonder that there's perspective at all. ;)
Title: Re:creation - a top down action rpg about undeads
Post by: Nexus on August 03, 2015, 10:04:57 am
Not only the ladder's perspective, but especially the cliffs with a "sideward slope" have a strange perspective. Looking at the trees and game characters, the player is looking a bit from the front, I think you should maintain this consistently.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 03, 2015, 10:42:45 am
Yeah, I agree. To make the perspective better, I need to draw more tiles, though. This is pretty hard but I'll try :)
Check out cliff perspective in Mother 3 (http://starmen.net/mother3/walkthroughs/maps/Chapter%201%20Maps/Forest%20Grotto%20(smoke).png) or in ALttP (http://s1.hulkshare.com/song_images/original/3/f/0/3f081ebcf9d4b30e8e09de2ef939c3d0.jpg?dd=1388552400)
Both look kinda weird, but I think I want my cliffs to look more like in Mother 3.

I've made a quick fix to see how cliffs would look, it's a bit better than what I have now:
(http://i.imgur.com/RrkabAK.png)
Title: Re:creation - a top down action rpg about undeads
Post by: SpeCter on August 03, 2015, 11:56:30 am
I would make the ladders straight I think. Making it wider at the end looks weird, especially when your character doesn't get bigger climbing it.
Title: Re:creation - a top down action rpg about undeads
Post by: Nexus on August 03, 2015, 12:41:37 pm
Elias, the cliff already looks much better on the left edge (not on the right though ;)).

Yes, I'd make ladders straight too. Your graphics follow a parallel projection, so it looks weird when single objects have perspective.
Title: Re:creation - a top down action rpg about undeads
Post by: Tank on August 03, 2015, 01:23:23 pm
+1 Nexus
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on August 03, 2015, 08:52:22 pm
The cliffs look a whole lot better when seen consistently from one angle (the newer version), in my personal opinion.

The ladder is a weird one, though. It looks slightly odd having perspective but maybe it's necessary to suggest its angle. A flat width ladder would look more like a bridge.

You should also note that this "consistent angle from the front" is not a requirement of this particular style. See the inside scenes where you can see the inside of the "closest" wall.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 04, 2015, 01:08:12 pm
Thanks for the feedback, everyone. I'll try different perspective styles to see what looks the best.

Worked on the tileset today. I think it's a big improvement.
(http://i.imgur.com/8yYQaKg.png)
Still unsure about the perspective.
Here's another way to do it:
(http://i.imgur.com/EJzHdlj.png)
(Notice the bottom part. I don't like that one because it's not that obvious that there are different heights there)
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on August 04, 2015, 02:41:36 pm
I think you should always have a small border around cliffs to show that they are cliffs rather than just a different style of grass. I found an image of some cliffs from a Link to the Past to give an example. Note the cliffs south west from Link, you can still see the face in what is the same perspective as in Re:creation.
(http://s.uvlist.net/l/y2006/08/26447.jpg)
I do realise that depending on how you look at it, it could look like the rocky ground is below the grass in terms of altitude, but the shadows work well to show that they are cliffs.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 05, 2015, 07:00:12 am
@shadowmouse Thanks for your observation. I think not having grass on such cliffs helps to make contrast even more high.

As for the ladder... I've been thinking about perspectives in top-down games. Most games don't use Zelda's perspective (look at the side and bottom walls!)
(http://www.vizzed.com/vizzedboard/retro/user_screenshots/saves31/319161/SNES--Legend%20of%20Zelda%20The%20%20A%20Link%20to%20the%20Past_Jan9%2013_05_58.png)

They use other projection which makes other walls not visible.
Seiken Dentesu 3:
(http://venturebeat.com/wp-content/uploads/2013/03/sd33.jpg)
Chrono Trigger:
(http://www.mobygames.com/images/shots/l/65821-chrono-trigger-snes-screenshot-lucca-s-house.png)

I like this perspective more and it seems that drawing in that perspective is easier. But I feel that this may limit indoor level design. I want some rooms to be connected with each other, but there isn't a good way to show some doors: all doors must be on the wall which player sees. Zelda's perspective lets you put doors on every wall you like.

Any thoughts on this?
Title: Re:creation - a top down action rpg about undeads
Post by: Tank on August 05, 2015, 08:18:46 am
Form follows function; ergo the Zelda one would fit better, clearly.
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on August 05, 2015, 12:12:59 pm
A similar discussion about this kind of perspective (it started with this post (http://en.sfml-dev.org/forums/index.php?topic=14965.msg118035#msg118035)) came up on the forum for Witch Blast, which - as you can see from that thread - ended with sticking to the original perspective, after trying out the other type and considering doors on the near wall etc., although Cirrus Minor did seem to personally prefer the original perspective so it could just be down to your own personal preference.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 05, 2015, 02:12:43 pm
@Tank, indeed!

@Hapax, I'll stay with Zelda-ish perspective for now until I see something that fits the game more. I think I'll mix perspective styles as long as it looks good. :)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 09, 2015, 12:00:55 am
Didn't have much time to work on the game in the last few days, but I still managed to do something cool.
Levels now support multiple tilesets. I can easily switch between them in the level editor.
(http://i.imgur.com/Zd7TiIT.gif)
Previously, I only had one tileset per level, because I've thought that having city tileset / forest tileset / dungeon tileset etc. for each level would be okay. But then I've realized that it would be cool to mix tilesets instead of copy/pasting some tiles between tilesets
Another issue I'm thinking about is how to assign unique ids to tiles. I've previously used integer ids which were assigned like this:
(http://i.imgur.com/cWR9kDa.png)
This is pretty straightforward approach and it lets me easily get texture coordinates of the tile by its id.
But it leads to some problems:
1) Changing the width of a tileset breaks ids, because they correspond to other tiles.
2) If I change the ordering of tiles, I need to replace their ids with new ones in the level.
So, I need a better approach. I think that generating some tileset file like this:
x=0,y=0,id=G
x=16,y=0,id=G2
...
Then I can freely change width of tileset and swap tiles by changing their ids in a tileset file.

What do you think of that? Maybe there are some cooler methods to store tilesets and levels? :)
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on August 09, 2015, 10:53:28 am
It might well be similar to what you are doing, but you could make an unordered_map which has a key type of either string or int (depending on how you store your level data) and a value type of a user defined struct which stores a reference to an sf::Image (which contains the relevant tile set) and an sf::IntRect for position. This way the code wouldn't be in an easily modifiable file, and you could even store it in a dll so that you can update it easily if you plan on releasing patches rather than entirely new builds of the game.
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on August 09, 2015, 07:28:49 pm
What do you think of that? Maybe there are some cooler methods to store tilesets and levels? :)
I think integer IDs is reasonable for most cases. Changing the width of a tileset is, in effect, inserting new tiles into the set so IDs being reassigned is an expected repercussion. Prepare the width of the tileset in advance, once  :P

That said, an enum could ease this rearrangement (albeit in a rather verbose way):
(click to show/hide)
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on August 09, 2015, 07:32:22 pm
I was going to suggest that, but I thought having position independent from width would make it easier to add tiles as you could just add things at the end of the list with a position that isn't at the bottom of the image.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 10, 2015, 08:50:17 am
It's hard to know the width of the tileset which would be enough. Sometimes I arrange tiles into large chunks, so then it's easier for me to create levels. Using enums is not possible, as it would require hardcoding.
So I think I'll stick with randomly generated ids for now. :)
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on August 10, 2015, 12:52:06 pm
Using enums is not possible, as it would require hardcoding.
Yes, but only once  :P
Much better than having to re-assigning all the IDs manually and it's pretty lightweight.

Having customised textureRects for each tile seems like overkill for a tileset in a grid but it'll work. The added advantage of this is that you can then start to use irregular tilesets  ;)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 10, 2015, 02:53:19 pm
Yes, but only once  :P
Huh? But I would need to change this enum each time I add new tile type. And then I would need to recompile. Nope!
And I don't plan to have customized textureRects, all I need is (x,y) coordinate, the tile size would stay the same for all tiles.

Much better than having to re-assigning all the IDs manually and it's pretty lightweight.
I would re-assign only those IDs which I would change in the tileset if I use the method which I talked about.

Suppose that level is stored this way:
GGGGGG
GGGGGG
GGRRGG
GGGGGG
...

G is a grass tile and R is a road tile.
Suppose tileset file looks like this:
x=0,y=0,id=G
x=16,y=0,id=R,
...

What if I've decided to move grass tile in other place in the tileset, like (32,32)?
All I need to do is replace x and y coordinates in tileset file.
x=32,y=32,id=G
x=16,y=0,id=R,
...
The level file would not change at all. :)
If I change the width of the tileset, nothing would change in a tileset, all I need to do is add new tile ids in a tileset file.
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on August 10, 2015, 03:31:33 pm
And I don't plan to have customized textureRects, all I need is (x,y) coordinate, the tile size would stay the same for all tiles.
By customised, I mean that the textureRect's position is customised i.e. out-of-order. In fact, it could be off-grid if the x and y co-ordinates are texture resolution (and it could have a custom size), but I realise now you probably mean that the x and y would be grid positions e.g. x = 6 for the seventh tile on that row.

Much better than having to re-assigning all the IDs manually and it's pretty lightweight.
I would re-assign only those IDs which I would change in the tileset if I use the method which I talked about.
"Re-assigning all the IDs" here meant your original IDs, where you would have to change them all manually.

x=0,y=0,id=G
x=16,y=0,id=R,
...
This is where the enum could still be used: the "id"; you'd be using an identifier anyway.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 10, 2015, 05:30:39 pm
By customised, I mean that the textureRect's position is customised i.e. out-of-order. In fact, it could be off-grid if the x and y co-ordinates are texture resolution (and it could have a custom size), but I realise now you probably mean that the x and y would be grid positions e.g. x = 6 for the seventh tile on that row.
I originally thought about having x and y be positions on the texture, but now I realize than this is not necessary, grid positions are all that is needed.

"Re-assigning all the IDs" here meant your original IDs, where you would have to change them all manually.
Well, that's not that hard, I think :)

This is where the enum could still be used: the "id"; you'd be using an identifier anyway.
As I said before, I can't let myself hardcode stuff (there will be lots of tile types, sometimes near hundred or more), creating some file and then creating std::map from it  seems better for me.
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on August 10, 2015, 06:01:01 pm
"Re-assigning all the IDs" here meant your original IDs, where you would have to change them all manually.
Well, that's not that hard, I think :)
I meant changing the the level manually, as was your first concern.

As I said before, I can't let myself hardcode stuff (there will be lots of tile types, sometimes near hundred or more), creating some file and then creating std::map from it  seems better for me.
Fair enough. Enums can get pretty long, pretty quickly  ;D
The consideration with using an std::map is what to use as the key. Would that still just be an integer? A string?
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 11, 2015, 08:07:50 am
I meant changing the the level manually, as was your first concern.
I won't change the level manually, I will change the tileset manually, but maybe I'll write a short program which will let me do this with some cool GUI ;)

Fair enough. Enums can get pretty long, pretty quickly  ;D
The consideration with using an std::map is what to use as the key. Would that still just be an integer? A string?
Enums also make modding harder. People can't create custom tilesets that way, only redraw the existing ones. :)
I think I'll use strings because this would let me assign meaningful ids to some tiles.
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on August 11, 2015, 04:29:38 pm
Going back to an earlier subject, I remembered that you had a problem with implementing a render texture. Did you fix this? An idea came to me randomly: the views on the render texture and window would need to be controlled individually. Odd views may have caused your vibration. I think that's the problem you were having, right?
If it's not this, or you fixed it anyway, just ignore this post  ;D
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 12, 2015, 03:59:40 pm
Going back to an earlier subject, I remembered that you had a problem with implementing a render texture. Did you fix this? An idea came to me randomly: the views on the render texture and window would need to be controlled individually. Odd views may have caused your vibration. I think that's the problem you were having, right?
If it's not this, or you fixed it anyway, just ignore this post  ;D

I think that the problem I was having is that view's coordinates were not integer during screen shake (I forgot about that when I was trying to fix that). I'll come back to it later. :)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 19, 2015, 08:54:43 am
Sorry for the lack of updates. Some RL stuff going on + I have lots of other stuff to work on/learn. :)
I'm mostly doing refactoring now and thinking about making some fundamental systems in the game better and more stable.
There's a lot of stuff to do to make game more polished. This is sometimes very hard and boring, but it needs to be done.
And I've almost completed the first article of "Using Lua in practice" series. I hope to release it today or tomorrow.

I'm also learning some OpenGL. What are some books/tutorials would you recommend? (Preferably OpenGL 3.x because my graphics card doesn't support OpenGL 4, heh).
Title: Re:creation - a top down action rpg about undeads
Post by: victorlevasseur on August 19, 2015, 09:10:00 am
Here is one I used to learn a bit of modern OpenGL : http://www.opengl-tutorial.org/
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 19, 2015, 11:08:32 am
Here is one I used to learn a bit of modern OpenGL : http://www.opengl-tutorial.org/
Thanks, I've read some articles there and they are pretty good :)

Also, Using Lua and C++ in Practice (https://eliasdaler.wordpress.com/2015/08/10/using-lua-and-cpp-in-practice/) is out.
Title: Re:creation - a top down action rpg about undeads
Post by: dabbertorres on August 19, 2015, 09:14:28 pm
I'm also learning some OpenGL. What are some books/tutorials would you recommend? (Preferably OpenGL 3.x because my graphics card doesn't support OpenGL 4, heh).

I'm a fan of https://open.gl/. It even has a guide of setting up an OpenGL context and input handling with SFML (along with SDL and GLFW).
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 20, 2015, 07:10:02 am
I'm a fan of https://open.gl/. It even has a guide of setting up an OpenGL context and input handling with SFML (along with SDL and GLFW).
Thanks, I'll check it out :)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 21, 2015, 05:47:04 pm
Making walking animations.
(http://i.imgur.com/kh0tCj6.gif)
(http://i.imgur.com/EmQKopQ.gif)

I've made enemies more detalized. I'm a lot more satisfied with how they looks now.
(http://i.imgur.com/YgDbvSe.png)

I need to draw three attack animations (up, down, side) and then I'll work a lot on the battle system. I'll try different stuff.

In most games like top-down Zeldas enemies can attack you in two ways: either by running into you or shooting/throwing some stuff at you.
I want to make attack animations for enemies who carry swords. Zelda doesn't have them, enemies with swords just run into you. But making sword attack work good is harder. I think I'll try to create some pre-attack animation which will indicate that enemy is going to attack so that the player can dodge. Any thoughts on this? I can't think of top-down games like Zelda which had good real time battle system (I want to see how other people have done it)
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on August 21, 2015, 06:11:48 pm
Those animations and new sprites are really good. I like the idea of adding sword swinging as the zelda enemies often look like they have some sort of pike or something and can't swing it, which is stupid (either than or they're just trying to stick you with the pointy end). As for the pre-attack animations, maybe they move their sword arm out, then swing it across they're body to attack? Are you making multiple versions of the knight armour? Like maybe a commander with a different helmet in each group. One suggestion I'd have is to actually draw several versions of the knight (by copy and paste) and give each different hair (black, brown, blond and the occasional ginger), then in your files which hold the data for where you place knights (I'm presuming you didn't hardcode this) you can specify a hair colour, or by default it could be black. This would mean that large groups of knights won't look like clones. It's a similar idea to in Besiege where each time you kill someone, it tells you their name so as to give each enemy some individuality.
Title: Re:creation - a top down action rpg about undeads
Post by: dabbertorres on August 21, 2015, 06:24:31 pm
For the attacking, an event/message/etc might work well. Play the attack animation like any other animation, but, make it send a message at the point when you want the attack to damage something.
Have some sort of listener that checks if there is a damageable object in range of the swing. If so, damage that object. If not, do nothing.

Though, that would only make the swing damaging at one point in time. If it's a wide swing, for example, technically it should damage anything it intersects at any point during the animation. In that case, maybe a collision box around the weapon would be good. Then you can just use your existing collision system, probably.
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on August 22, 2015, 12:10:42 am
Looking good :)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 22, 2015, 09:00:02 am
@shadowmouse No, the armor would be the same for sword guys, maybe some colors will differ. Making different hair is a good idea, but I need to create some system which will replace colors in sprites, because copy-pasting sprites by hand is a waste of space and time

@dabbertorres The problem is not technical, I'm just thinking what would feel and play the best. It's a game design problem.

@Hapax thanks! :D
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on August 22, 2015, 09:56:04 am
Maybe make a version of green screening and colour the hair a colour that isn't found anywhere else in the sprite then you can pass the exact value of the green colour and its replacement? You might be able to find a standard green that you can use as a default.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 23, 2015, 08:56:25 am
Maybe make a version of green screening and colour the hair a colour that isn't found anywhere else in the sprite then you can pass the exact value of the green colour and its replacement? You might be able to find a standard green that you can use as a default.
Yeah, this should work, thanks.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 23, 2015, 11:05:26 am
New character! A mysterious cute cat with no name. (yet)
(http://i.imgur.com/MW2oSOH.png)

I'm also drawing sprites for Undead Bar. Lots of cool stuff is drawn already will show off soon!
Here's one of the sprites. I love how much depth the shading adds.
(http://i.imgur.com/6vcRPf1.png)
Title: Re:creation - a top down action rpg about undeads
Post by: SpeCter on August 23, 2015, 02:44:19 pm
I'm also learning some OpenGL. What are some books/tutorials would you recommend? (Preferably OpenGL 3.x because my graphics card doesn't support OpenGL 4, heh).

I'm a fan of https://open.gl/. It even has a guide of setting up an OpenGL context and input handling with SFML (along with SDL and GLFW).

I prefer http://learnopengl.com/ it starts out almost the same, but has more stuff to do.
Title: Re:creation - a top down action rpg about undeads
Post by: namosca on August 24, 2015, 11:06:54 pm
I would really like to download the game, but I really didnt manage to find the link?

Could you post it to us?

I would prefer (if possible) to have the binaries for windows, instead of having to compile everything myself. I am tiring of compilling errors all the time.

If the game is fun, I would also like to have a look at the source if you can make it available for us!!

Thanks!!
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 25, 2015, 08:27:48 am
@SpeCter thanks, I'll check it out!

@namosca The game is not out yet. When the public game is released, you'll know about that either by this thread or my twitter. There will be Win/Linux/Mac OS X binaries, of course.

I'm thinking about open sourcing my game's code, but I think I'll do it after some time after release and if the code is good enough for other people to look at. :)
Title: Re:creation - a top down action rpg about undeads
Post by: SeriousITGuy on August 25, 2015, 11:51:21 am
Thanks for the progress update and the LUA articles. Exactly the thing I want to learn right now. Keep up the great work. Maybe one day you can actually sell this already cool looking game (Steam Greenlight, Itch-io or similar).
And I am very interested in your code, from what I've seen from your articles it must be good quality, so I would be very glad to work through your code base. Maybe you could also right some articles on key points of your engine.
Title: Re:creation - a top down action rpg about undeads
Post by: Tank on August 26, 2015, 08:55:53 am
The cat is great! Nice work. :)
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on August 26, 2015, 08:10:44 pm
The cat is too cute. Take it away or I may have to steal it and adopt it! <3
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on August 26, 2015, 08:41:58 pm
Have you thought of a name for it or will you be taking votes?
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 26, 2015, 11:30:35 pm
@SeriousITGuy, you're welcome. And thank YOU for reading my articles and dev log. Glad you've enjoyed it. :)
As for the code... As I've said before, only the best parts get posted. My code has some quickly written parts which kinda work but are not good. I'd fix them if I had time... but I don't always have enough.
I plan to write articles about my engine's structure (some of it can already be found in my dev logs and some will be in "Using Lua in Practice" series)

@Tank, thanks!

@Hapax, thanks! :D
And it's not even its final form of cuteness. I will post even more cuter portrait soon.  ;D

@shadowmouse, didn't think of a name for it yet. I need to come up with something clever to show its true character. ;)
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on August 27, 2015, 12:24:35 am
it's not even its final form of cuteness. I will post even more cuter portrait soon.  ;D
You're going to kill me!
Is what you're suggesting even possible?  ???
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 27, 2015, 01:11:21 am
it's not even its final form of cuteness. I will post even more cuter portrait soon.  ;D
You're going to kill me!
Is what you're suggesting even possible?  ???

Ha-ha. I still don't know the limit of the cuteness I can make! :D
Title: Re:creation - a top down action rpg about undeads
Post by: Tank on August 27, 2015, 08:13:04 am
Re:cuteness - a top down action rpg about kittens
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on August 27, 2015, 08:24:34 am
Maybe when you finish the game once, you unlock cute mode and all characters become kittens.
Title: Re:creation - a top down action rpg about undeads
Post by: SeriousITGuy on August 27, 2015, 09:52:21 am
Why everyone on the internet freaks out about cats, I don't get it :D
( ok from a game designer point of view a cat could make up a very cool character, something like the cat from Alice in Wonderland :D )

@Elias: Hey it's your code you can do whatever you want. If you plan on writing articles about your engine it is more than enough for me to study on ;)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 27, 2015, 10:53:47 am
@Tank, that's a good idea for a spin off game! :D

@shadowmouse, that would be cool, but just imagine how much of the artwork I'd have to create!

@SeriousITGuy, cats are cute. People like cute things. ;D
The cat has even more value from the game design point. (It's a secret for now!)
As I write "Using Lua with Practice" articles, I realize that Lua connects a lot in my engine and that's why looking at Lua/C++ stuff I've got is going to give you a pretty good idea of what's going on it my engine. :)

(P.S. I wish there were some good articles/books like this. Game Engine Architecture is the closest I've seen to what I need so far.)
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on August 27, 2015, 12:56:13 pm
Why everyone on the internet freaks out about cats, I don't get it :D
Did you not see it?
(http://i.imgur.com/MW2oSOH.png)

It's bordering on being as cute as:
(http://i.imgur.com/NwcdVvG.jpg)

The cat has even more value from the game design point. (It's a secret for now!)
Is it related to Egypt?  :D
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 27, 2015, 07:21:25 pm
@Hapax, nope :P

I've spent 3 hours drawing carpets today. They're pretty hard to draw (especially the round one!)
The stone wall tile was drawn a while ago and I've finally found a place to use it. I'm a lot more satisfied with the look now. (compare it to a previous screenshot!)

(http://i.imgur.com/lFqs8uq.png)
Another carpet:
(http://i.imgur.com/Z8Ipjaj.png)
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on August 27, 2015, 07:30:32 pm
That stone and carpet combine really well with the general theme of the place, I think they make it look a lot less generic. Just to clarify, it wasn't generic the first time (especially because of the cat), but it is now even more not generic.
Title: Re:creation - a top down action rpg about undeads
Post by: Tank on August 28, 2015, 08:49:00 am
That looks so cozy that I immediately want to play some x-mas tunes and drink tea while watching the snow outside...just that there's none. Looks nice, I really like your art style :)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 28, 2015, 06:03:09 pm
@shadowmouse, thanks! I was trying out some colors (I wanted to see if the place would look better with more of them). Turned out quite good :)

@Tank, thanks! After reading your post I've decided to add some cozy music to this place. I've already written bossa nova track for my game and I think it may fit nicely here. :)

By the way, my awesome GF made this for me!
(http://i.imgur.com/uf4kKio.jpg)

Zelda's "Got item" sound
(http://i.imgur.com/SCO5CYT.png)
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on August 28, 2015, 10:14:43 pm
By the way, my awesome GF made this for me!
Let's hope you don't change the graphics again!
That's right; today, I looked at your progress album...
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on August 28, 2015, 11:07:58 pm
By the way, my awesome GF made this for me!
Let's hope you don't change the graphics again!
That's right; today, I looked at your progress album...

Ha-ha, well, I can make Re:creation Woolly World now!

What do you think of the progress album?
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on August 29, 2015, 01:58:22 pm
I found it interesting. It's comforting to know how often people change their minds during development!
Still, think of how far along the game would be now if you'd've put all the time into the game development instead of drawing new graphics  ;D
Title: Re:creation - a top down action rpg about undeads
Post by: nebula on August 29, 2015, 04:02:49 pm
Dude this is awesome work.
Really like what you did there!

Keep it up ;-)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 01, 2015, 08:36:03 am
I found it interesting. It's comforting to know how often people change their minds during development!
Still, think of how far along the game would be now if you'd've put all the time into the game development instead of drawing new graphics  ;D

Yeah, I like to look at the progress albums for the same reason. (And it's also pretty interesting to look at my game's progress too! :D)
Yep, the game would be a lot larger and more developed. But think how far along it would be if I worked on it full time? Or if I didn't spend so much time posting about my progress/reading some stuff on reddit/etc.?
There's a lot of reasons for a game taking long to develop. Doing art for yourself is just one of them. And previously I didn't like it (even hated it sometimes). But now I'm pretty okay with that, lots of times I even have lots of fun drawing art. I've just accepted as a fact that finding an artist who's willing to work for revenue share is almost impossible, so all I can do for now is to deal with it! :D

@nebula, thanks!

Progress update
Finally I've figured out the way to store components continuosly in memory. It may not give the significant speed up (but I'll post the results of testing!) but it will be very helpful for the future. (And for other games I'll work on using the same engine).

I'm still working on this, but I will post the source code soon (probably this month) so people can use it for their own games. I would also love for people to propose some ideas about how I can make this system better.
Note that I won't post the source code of my engine. It's a completely separate prototype project with some tests but it would show most of the stuff I'll integrate into the game later.

The main principle is what someone later proposed in this thread.

I have this class:

class IComponentList {
...
};

and this class:

template <typename T>
class ComponentList : public IComponentList {
...
private:
    std::vector<T> components;
}

and then this map:

std::map<std::type_index, IComponentList*> componentLists

where key is std::type_index is std::type_index(typeid(T)) where T is a type of the component a corresponding value (a component list) holds.

I can currently get the list I need like this:

auto& list = ComponentManager::getInstance().getComponentList<SomeComponentType>();
 
The entity class interface remains the same, though. I still have:

class Entity {
...
    std::vector<Component*> components;
}

But now the entity points to components inside the component lists.
This is harder to implement than it looks, because:

1) Changing the position of a component in a component array invalidates the pointer in Entity so I have to change it manually
2) If I insert some new components in some vector L and the size of the vector is more than it's capacity, it will reallocate which means that every component pointer (of component type which L holds) in every entity becomes invalid.

This is not a big problem, though!

The first problem is easily solvable. The second is a bit harder, though.
I can fix it by reserving enough memory for each component vector so it won't reallocate again when the game is running (vectors would need to change it's sizes during level load but this is not critical, changing some pointers is not that hard during that.)
How can I know how much components of each type there will be? Easy. I have a list of every entity on the level in a level file which means that  I can count how much of each component time I would need.
What about entities which could previously create entities when the game was running (like bows which created arrow entities). I won't do this anymore! Allocating memory on when the game is running is bad anyway.
So, each entity can explicitly show that it can create new entities and each component list would get additional size to allocate.
For example, you won't see more than 1-2 arrows flying from the same bow on the screen. This means that I can reuse the same arrow entity over and over again. I will create arrow entity for each bow entity when the level loads and there's no need to create entities during gameplay anymore.
So, those limitations lead to some great improvements of other things! There are more aspects which I'll cover later.

P.S. Anyone knows any good articles about C++ templates? Especially about header dependency aspect of it. I want to make templates the way that they won't cause more recompilation then necessary (this is very easy to make if you're not careful).
Title: Re:creation - a top down action rpg about undeads
Post by: Jesper Juhl on September 01, 2015, 09:06:39 am
P.S. Anyone knows any good articles about C++ templates? Especially about header dependency aspect of it. I want to make templates the way that they won't cause more recompilation then necessary (this is very easy to make if you're not careful).
Using 'extern template's can help a great deal with that often. See this: http://en.cppreference.com/w/cpp/language/class_template (the section about "Explicit Instantiation")
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on September 01, 2015, 10:22:36 pm
But think how far along it would be if...
I didn't mean to suggest that it is progressing slowly. I'm sorry if it came across that way.
I think it's coming along great and I find its progress fascinating  :)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 01, 2015, 11:17:47 pm
@Jesper Juhl, thanks. I've read the article but don't have an idea how to use this effectively (probably because I don't know some stuff about templates and header dependency). Can you provide any useful examples of using extern template in my case?

@Hapax, no offence taken.
Thanks, glad you like the progress :)
Title: Re:creation - a top down action rpg about undeads
Post by: Nexus on September 01, 2015, 11:22:52 pm
Quote from: Elias Daler
What about entities which could previously create entities when the game was running (like bows which created arrow entities). I won't do this anymore! Allocating memory on when the game is running is bad anyway.
A static pool wastes lots of memory and is a really bad idea. Unless you have really low memory requirements, I wouldn't go this way out of lazyness to implement a proper solution ;)

Quote from: Elias Daler
P.S. Anyone knows any good articles about C++ templates? Especially about header dependency aspect of it. I want to make templates the way that they won't cause more recompilation then necessary (this is very easy to make if you're not careful).
Explicit instantiation (see Jesper's post) and type erasure/PImpl are the most promising approaches, but they can only be applied in special cases.

Unfortunately, in most cases you simply don't have another option than keeping templates in the headers. Still, try at least to outsource parts that aren't dependent on template parameters, and avoid too deep dependencies... Sometimes it's worth trading off compile-time type safety for less code bloat and compilation time.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 02, 2015, 06:58:07 am
@Nexus, most additional entities (arrows, bombs, etc.) would be pretty lightweight compared to big ones. For example, one arrow contains GraphicsComponent (sf::Sprite which shares sf::Texture with other arrows) and CollisionComponent (two pointers and one sf::FloatRect).
What's the better way of doing this instead of using object pools? I have one idea: I can still benifit from creating object pool of size which all entities on the level reqiure (I need to load them all anyway). Then I can create additional component lists for entities which may be created during gameplay. When some of these lists need to expand, I would manually swap the pointers after reallocation which won't invalidate the pointers of components stored in a bigger vector (which was used for all entities on the level).

Unfortunately, in most cases you simply don't have another option than keeping templates in the headers. Still, try at least to outsource parts that aren't dependent on template parameters, and avoid too deep dependencies... Sometimes it's worth trading off compile-time type safety for less code bloat and compilation time.
I guess I just don't get how dependant some files become from each other if I use templates.
For example, I have a createComponent<T> free function in ComponentManager.h
If I change some stuff about components for which this template function is created, would this cause ComponentManager.h to recompile too?
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 03, 2015, 08:01:06 pm
Small progress update.
Still working on new ECS implementation. Improvements are quite nice. (Sorry, no pretty pictures, working on code)

Suppose I have two entity types:

ghost = GraphicsComponent
tree = GraphicsComponent + CollisionComponent

What if I need to create 4 ghosts and 10 trees? I need to create 14 GraphicsComponent's and 10 CollisionComponent's.
But, simply adding them via push_back to std::vector of GraphicsComponent and CollisionComponent is a bad idea. Why? Because vector will reallocate it's memory array several times invalidating all pointers to GraphicsComponent's and CollisionComponent's! (It will also make lots of copies when doing this).
Imagine if I had hunderds or thousands of components and copying them was not fast...

So, I've used std::vector::reserve instead which makes sure that no allocation will take place.
First, I count how much of each component types will be created. Then I reserve enough memory for each vector. And then I can safely create every entity. No allocations happen during this, yay!
Counting the number of items to reserve is not that easy as it may sound but it didn't take long to implement.

I hope to release source code to this ECS stuff soon! :D
Title: Re:creation - a top down action rpg about undeads
Post by: Nexus on September 04, 2015, 08:57:30 am
The pointer invalidation problem you're talking about is the reason why common ECS implementations store handles, not pointers.

If you have to specifiy an upper bound to the number of components and allocate a fixed number up front, you're severely limiting the usage of your ECS. It may work well for your specific game right now, but you'll have to rethink everything at one point...
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 04, 2015, 01:52:37 pm
@Nexus. Just impelemented handles. They work fine :D
Well, if I don't have an upper bound, this means that a vector may reallocate when some entity is created during the gameplay. This may cause lots of copying which may take a long time causing perfomance drop. The only way to prevent this (that I can think about) is to allocate enough memory up front (and add some additional memory for temporary entities, for example). Are there any other solutions to this problem?
Title: Re:creation - a top down action rpg about undeads
Post by: Laurent on September 04, 2015, 02:02:00 pm
Why don't you allocate components individually, and store pointers to them into your vector? It looks weird to use value/copy semantics on components.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 04, 2015, 03:07:06 pm
Why don't you allocate components individually, and store pointers to them into your vector? It looks weird to use value/copy semantics on components.
Because storing components in one array is better for cache, considering I have to iterate through them in every frame. If you allocate components individually (which I've done before), you get lots of cache misses.

This may seem like an over optimization and I've yet to test speed improvements, but I didn't spend much time making this, so I may throw it away then. :D
Title: Re:creation - a top down action rpg about undeads
Post by: Laurent on September 04, 2015, 03:21:43 pm
Quote
This may seem like an over optimization
This is very likely.

The problem now is that it drives a non-negligible part of your design and implementation. So you should really benchmark now, to avoid this kind of issues, and to possibly save one complete rewrite of the system in a near future ;)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 04, 2015, 04:45:29 pm
The problem now is that it drives a non-negligible part of your design and implementation. So you should really benchmark now, to avoid this kind of issues, and to possibly save one complete rewrite of the system in a near future ;)

Okay, I'll do that very soon, will report the results in this thread :)
Title: Re:creation - a top down action rpg about undeads
Post by: Nexus on September 04, 2015, 06:42:49 pm
The only way to prevent this (that I can think about) is to allocate enough memory up front (and add some additional memory for temporary entities, for example). Are there any other solutions to this problem?
Yeah, of course. std::vector is not the only container in the world.

[Premature optimization] is very likely.
This is probably true for medium-scale games like Re:creation, but the same can be said for many parts of the ECS, maybe even the choice of an ECS design itself. I think it can't hurt to know some alternatives, even if one is not going to use them in a game. But I definitely agree that profiling makes sense.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 04, 2015, 10:49:52 pm
Yeah, of course. std::vector is not the only container in the world.
I can't think of many data structures which store the data continuously in memory.

[Premature optimization] is very likely.
This is probably true for medium-scale games like Re:creation, but the same can be said for many parts of the ECS, maybe even the choice of an ECS design itself. I think it can't hurt to know some alternatives, even if one is not going to use them in a game. But I definitely agree that profiling makes sense.
There are several reasons for all this new ECS stuff. But yeah, this may not improve the perfomance a lot and I throw away the code without any hesitation.
It was just an interesting challenge which has taught me some things about templates, vectors and some C++11 which I've never knew before. I didn't spend much time doing this, so no regrets. :)

I agree that I have to do profiling. What is the best way to do this? Do I need to create some test data which I'll use or do I need to integrate this new system to be completely sure?
The one way I think I can test this is to compare how much time each system's update() function takes. It involves iteration through std::vector of related components so it may make some difference.
Title: Re:creation - a top down action rpg about undeads
Post by: lezebulon on September 05, 2015, 01:44:01 am
I've been looking at game designs things for year and I always see people praising ECS everywhere, except that I've never seen an ECS actually working well for a medium-sized game or more. Like, I get that an entity is any aggregation of components but I don't get how the logic will be simplified, because the logic would have to be working on the whole entity itself, and not each component independently anyway....

Anyway Elias, you don't need *absolute* contiguous memory for the whole iteration of all the components of a single type. You could store things in like an std::vector < std::array < ComponentType, 128 > > , so that 128 items will be contigous. From an index i, you can easily work out that the object should be placed at index (i/128, i %128), which will end up being calculated really fast. I admit this requires re-coding a whole new data structure but with the requirements you are saying, there is no way around that.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 05, 2015, 06:28:58 am
@lezebulon, ECS worked very well for me. I was getting stuck with standard OOP way of doing things and adding new stuff to the game wasn't this easy.
The logic doesn't have to be working on the whole entity. Most of the time (especially for collision, movement and graphics which is what the game is doing most of the time, other stuff is taking less much time) you don't need the whole entity, you are fine with just a component. So, when I draw entities, I just use graphics components which tell me nothing about what entities are these. When I check collision, I don't care what entities collided, I just care that they're collided and I just call their Lua response functions.

Well, that's a good idea, thanks. This way I can be sure that the vector doesn't take too much space. :)
I'll see if storing components contiguously is giving me advantage first, though. :)
Title: Re:creation - a top down action rpg about undeads
Post by: Nexus on September 05, 2015, 12:09:53 pm
Because storing components in one array is better for cache, considering I have to iterate through them in every frame.
By the way: this whole cache story is only true as long as you iterate over a single component type. And in my experience, many systems need access to multiple components. For all those cases, performance is thrown out the window again.

I agree that I have to do profiling. What is the best way to do this? Do I need to create some test data which I'll use or do I need to integrate this new system to be completely sure?
The profiling should be done on data that is somewhat representative of a typical situation in your game. Ideally, you profile the game itself, but you can already draw conclusions from smaller experiments.

Whether you measure time in code or with an external profiler is your choice.

I admit this requires re-coding a whole new data structure but with the requirements you are saying, there is no way around that.
Such a data structure already exists in the standard library, even if it doesn't let you specify the bunch size. It's called std::deque. Know your tools 8)

Other than that, you have trade-offs like boost::stable_vector and what not. There are enough C++ libraries out there to have a look at before reinventing the wheel ;)
Title: Re:creation - a top down action rpg about undeads
Post by: lezebulon2 on September 05, 2015, 12:54:12 pm
@lezebulon, ECS worked very well for me. I was getting stuck with standard OOP way of doing things and adding new stuff to the game wasn't this easy.
The logic doesn't have to be working on the whole entity. Most of the time (especially for collision, movement and graphics which is what the game is doing most of the time, other stuff is taking less much time) you don't need the whole entity, you are fine with just a component. So, when I draw entities, I just use graphics components which tell me nothing about what entities are these. When I check collision, I don't care what entities collided, I just care that they're collided and I just call their Lua response functions.
But for instance, if thé collision response is to move back the object, how do you tell the graphics component that it has to move?

Àbout needing your data to be contiguous: as I said you probably don't care if instead of iterating over 300 items in an array you do it 3 times for 100 items per array, I doubt thé cache miss world be important
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 05, 2015, 04:37:08 pm
By the way: this whole cache story is only true as long as you iterate over a single component type. And in my experience, many systems need access to multiple components. For all those cases, performance is thrown out the window again.
Yup, agreed. Didn't think of it.

Such a data structure already exists in the standard library, even if it doesn't let you specify the bunch size. It's called std::deque. Know your tools 8)
Didn't know it stored data contiguously. (Well, sort of...). My bad :)

But for instance, if thé collision response is to move back the object, how do you tell the graphics component that it has to move?
Events. Collisions don't happen frequently, so this is not a big perfomance issue.

Progress update
Okay, so I've created this wonderful scene:
(http://i.imgur.com/V3brnTW.gif)
Lots of entities, moving randomly.
I've tested this scene with old ECS system (components are stored randomly in memory) and new ECS system (components are stored contiguously in std::vector).
The results shocked me: there was no perfomance increase.
This is not a dissapointing result for me (but kind of stange... I was expecting at least some perfomance increase). In fact, I'm quite relieved that I don't have to integrate the new system into my project (this would be painful and long).
But this was not a complete waste of time. I've come up with lots of useful improvements for my old system when I was writing the new system, so I'll improve my old system with that. I'll come back to actually making the game soon. So, expect to see some cool screens in the future :)

P.S. Thanks for being critical, everyone. I would be stuck much longer with all that ECS stuff without a healthy dose of a good criticism. :D
Title: Re:creation - a top down action rpg about undeads
Post by: Nexus on September 05, 2015, 04:54:44 pm
Events. Collisions don't happen frequently, so this is not a big perfomance issue.
When I experimented a bit with ECS- and event/message-based systems, I initially had an event system capable of abstracting component inter-dependencies completely. That is, by introducing intermediate event types, a lot of classes wouldn't need to know each other. The event thus acted as an interface.

Everything looked great, but as my design became more complex, I found myself adding a lot of different event classes, most of which were merely adapters to their corresponding components. The need to duplicate data as well as the additional complexity in the data flow led me to rethink this idea. I concluded that code becomes far more understandable if as much functionality as possible is handled in systems, and a system would only affect the components it depends on (as a contract), not components on the other side of the world through events. There are still events for certain features, but it's no longer the main communication approach.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 05, 2015, 05:01:10 pm
@Nexus, so, if CollisionSystem needs to change some entity's speed because of collision, it would just use MovementComponent of the entity which collided directly instead of sending a message to MovementSystem? Am I understanding this right?
Title: Re:creation - a top down action rpg about undeads
Post by: Nexus on September 05, 2015, 05:15:25 pm
That's one possibility, however this design couples the collision detection with collision response. The collision system needs to know all the consequences of colliding, which is not ideal.

The systems affected by collision are already dependent on collision classes, as they react to collision events. So they could as well check the collision component directly. Systems will tend to depend on multiple component rather than one component and multiple events, so the cache aspect might be a bit worse, trading off code flow simplicity (and event's aren't free either). You can also work with both approaches and see what works better.

Sometimes you do need event queues, for delayed processing for example. What I wanted to say, is that in my opinion, the main idea of ECS is to handle communication between components in systems, and handling communication through events is somewhat contradictory to this idea. So I wouldn't use events exclusively, it also makes it quite difficult to understand what happens when. But as usual, combining multiple approaches can lead to the best results.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 05, 2015, 05:35:19 pm
@Nexus, yep, that's kinda what I'm doing at the moment. Sometimes events can lead to non-readable code.
Do you use some scripting for collision response, for example?

Title: Re:creation - a top down action rpg about undeads
Post by: Nexus on September 05, 2015, 05:38:36 pm
No, I only used Lua to load configuration settings so far. It has been more an experimental project I've worked on a while ago, when I had more time... Not a complete game.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 05, 2015, 05:42:51 pm
So, how are you doing collision response then? There a lot of unique ways and object may react to collision based on its type. I wonder how it can be done without scripting.
Title: Re:creation - a top down action rpg about undeads
Post by: Nexus on September 05, 2015, 06:23:03 pm
Why would you need scripting? The logic can as well be implemented in C++, it's just a question of flexibility.

I used aurora::DoubleDispatcher (http://www.bromeon.ch/libraries/aurora/v1.0/doc/classaurora_1_1_double_dispatcher.html) for collision response.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 05, 2015, 07:07:24 pm
So, do you create free functions for each type of collision response and then bind it to Entity type?
I use scripting because it lets me quickly change the collision response logic quickly. I also use it for interaction response (what happens with entity if player interacts with it by pressing "interact" button)
Title: Re:creation - a top down action rpg about undeads
Post by: Grimshaw on September 05, 2015, 11:54:32 pm
Great job Elias.. very impressed with this project! It creeps me out how similar your ECS looks like to my previous approach. So much is exactly the same to what I used to have. Some parts I still have it, others not so much.

Either way, I think you are doing most things correctly, so just keep going! I don't really agree with some opinions here that oppose yours, but I'd have to support them a bit in saying that you should avoid complexity in favor of usability when the hit isn't very big.

Sometimes the time you save in development by doing something slightly less correct can pay off as well. Engineering time is a resource as much as memory or CPU, consider that :D
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 06, 2015, 09:02:45 am
@Grimshaw, thank you for encouraging words!
Do you store components contiguously or not?

Sometimes the time you save in development by doing something slightly less correct can pay off as well. Engineering time is a resource as much as memory or CPU, consider that :D
Yep, but it can improve the engine design a lot and save me lots of time in the future. It's hard to be sure from the beginning. :D
Title: Re:creation - a top down action rpg about undeads
Post by: Glocke on September 06, 2015, 03:47:02 pm
It's hard to be sure from the beginning. :D

That's right! I faced this at my project, too. But finally my major performance problems were fixed after reimplementing my ECS. Btw I use a contiguously approach for components only. More highlevel gameplay elements (like items or spells) are dynamically allocated. I haven't tested this referring to performance yet, but I think (of course depending on the type of game) it might be acceptable.

Btw: Your screenshots etc. look really great! I'm curious about the final version :)
Title: Re:creation - a top down action rpg about undeads
Post by: dabbertorres on September 06, 2015, 08:12:42 pm
Just to add other container types to the discussion, I've used Google's dense hash map (https://github.com/dabbertorres/GoogleHashMaps) (I exported from Google Code, I haven't found an official repository since it closed) and haven't noticed issues with it.

In addition, I've found and heard b-trees (https://en.wikipedia.org/wiki/B-tree) (not binary trees) can be a good choice as well.
Title: Re:creation - a top down action rpg about undeads
Post by: lezebulon on September 06, 2015, 09:58:50 pm
Events. Collisions don't happen frequently, so this is not a big perfomance issue.
Sorry I don't get it,
I'm assuming that for collision you run the collision update method on something like std::vector<ColisionCpt> , right ?
In that case, how do you know which entities the event should refer to ? Or does your collision component hold a pointer to an entity ?
And when firing the event, by what system do you know that entity A should respond to the collision by dying (for instance), and that entity B should respond by moving back? Is that because the collision response is a virtual method?
Title: Re:creation - a top down action rpg about undeads
Post by: Grimshaw on September 07, 2015, 02:31:21 am
@Grimshaw, thank you for encouraging words!
Do you store components contiguously or not?

Sometimes the time you save in development by doing something slightly less correct can pay off as well. Engineering time is a resource as much as memory or CPU, consider that :D
Yep, but it can improve the engine design a lot and save me lots of time in the future. It's hard to be sure from the beginning. :D

Yes I do, but its not a hard requirement. I basically have one pool per component type, which hands me N component instances when I ask for them.. So most of them should be contiguous, most of the time, but the world subsystem will work with even components allocated with new if I prefer it. You should totally commit to making the best library of components you can, either with behavior in component or component + system.

How you put these components together could and should be less hardcoded and allow more flexibility from game code.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 07, 2015, 08:48:31 am
@Glocke, well, reworking the system didn't help me. Guess the performance of my game was always pretty okay. Storing components contiguously was more like an exercise, I guess. And thanks!

@dabbertorres, thanks, that looks interesting. Didn't know about those structures.

@lezebulon, yep, all components store the pointer to Entity which owns them. (But I would store entity's id in the future, because I can quickly get entity by its id). So, one system may construct event which contains entity's id and other system will process it.
But I sometimes use the approach which Nexus has told about. Sometimes it's better for system to handle multiple components. In my case, if I need to change some components in one system, I may get this component by another component's owner pointer.

And when firing the event, by what system do you know that entity A should respond to the collision by dying (for instance), and that entity B should respond by moving back? Is that because the collision response is a virtual method?
This is all done by scripting. When two entities collide, a Lua function for each entity is called which does all the stuff.

@Grimshaw, did you notice any perfomance differences when storing components contiguously and not contiguously?
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on September 07, 2015, 01:00:16 pm
Please forgive me if I'm being dense here (I haven't used Lua) but what advantage does the scripted onCollision function have over a C++ std::function callback? Is it purely so that you can change it on the run without recompiling? Or is it something else?
Title: Re:creation - a top down action rpg about undeads
Post by: Glocke on September 07, 2015, 01:35:49 pm
Guess the performance of my game was always pretty okay.
This is all done by scripting. When two entities collide, a Lua function for each entity is called which does all the stuff.
On which type of system have you tested that your performance is pretty ok? I'm curious about testing it on my netbook (despite it is of course no gaming computer^^).
Title: Re:creation - a top down action rpg about undeads
Post by: lezebulon on September 07, 2015, 09:20:12 pm
This is all done by scripting. When two entities collide, a Lua function for each entity is called which does all the stuff.

Sorry I'm really not being clear :)  what I didn't get was, how do you determine which Lua function to call on the entity? At this point, you only know that 2 entities collided, and each entity is defined only by the list of its component (if I understood). So based on this, how do you figure out which Lua response to call ? I can think of several ways of doing it, but none that would be flexible enough and be in O(1)

Sorry I'm asking so much btw, I've always seens tons of ECS thrown around , but on every implementation it seems they never manage to make the whole thing work in constant time (with respect to the number of total component, system, etc). Whereas for me the point of ECS is that it's really easy to scale
Title: Re:creation - a top down action rpg about undeads
Post by: Nexus on September 07, 2015, 11:02:45 pm
Implementing a double dispatch system in O(1) is relatively easy: you create a 2D table of function objects/pointers, where each row and column is indexed by the entity type. Each cell contains the function for the combination of the row and column types. The type can be any criterion stored in any component.

You should really have a look at aurora::DoubleDispatcher (http://www.bromeon.ch/libraries/aurora/v1.0/doc/classaurora_1_1_double_dispatcher.html), it uses std::unordered_map and thus amortized O(1). :)
Title: Re:creation - a top down action rpg about undeads
Post by: lezebulon on September 08, 2015, 01:05:55 am
Implementing a double dispatch system in O(1) is relatively easy: you create a 2D table of function objects/pointers, where each row and column is indexed by the entity type.
Yup, but how is the concept of "entity type" even defined ? Usually the "type" is defined by the class hierarchy, but since there's no class hierarchy in an ECS, for me it's either:
- an entity type is an instance of an entity, which means a full vtable for each instance (still doesn't explain according to what criteria it should be filled)
- an entity type is a given combination of components, which means that they are 2^N possible entity types for a total of N components. Which means that we have to careful think about which combination of component should be dispatched to which virtual function.

I mean, it seems to me that there's always a point where, if we want to keep everything flexible, we are facing a combinatorial explosion simply because an entity could be any combination of components
Title: Re:creation - a top down action rpg about undeads
Post by: Nexus on September 08, 2015, 06:18:15 am
Yup, but how is the concept of "entity type" even defined ?
The type can be any criterion stored in any component.

It may be meaningful to store an attribute in the collision component, if dispatching is used for collision response. Make your dispatcher generic so that it can extract the type as you wish -- that's also what Aurora's implementation does.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 08, 2015, 08:09:22 am
Please forgive me if I'm being dense here (I haven't used Lua) but what advantage does the scripted onCollision function have over a C++ std::function callback? Is it purely so that you can change it on the run without recompiling? Or is it something else?
Yep, I could have used std::function for the same effect. Yep, I mostly use scripts to make quick changing possible. It also helps me to not search the source code when I want to see how some entity works: all entity properties and callback functions are stored in a corresponding script.

On which type of system have you tested that your performance is pretty ok? I'm curious about testing it on my netbook (despite it is of course no gaming computer^^).
I don't really remember which is the oldest PC I've tested it on, but I must say that my laptop is 5 years old and not that powerful. There's nothing to worry about in terms of perfomance. There isn't many sprites on the screen in one moment. There isn't any physics or complex AI.

what I didn't get was, how do you determine which Lua function to call on the entity? At this point, you only know that 2 entities collided, and each entity is defined only by the list of its component (if I understood). So based on this, how do you figure out which Lua response to call ? I can think of several ways of doing it, but none that would be flexible enough and be in O(1)
I store the corresponding function's luabridge::LuaRef in CollisionComponent (this is like a pointer to a function which lets you call this function). O(1)! :D
Title: Re:creation - a top down action rpg about undeads
Post by: Glocke on September 08, 2015, 09:38:12 am
I don't really remember which is the oldest PC I've tested it on, but I must say that my laptop is 5 years old and not that powerful. There's nothing to worry about in terms of perfomance. There isn't many sprites on the screen in one moment. There isn't any physics or complex AI.
5 years old? So the laptop might have a dual core cpu with >2 GHz per core? That's quite much for 2D gaming :) Personally, I'm focused to make my game's core (physics, graphics, basic gameplay logic) run on the very low end hardware (e.g. 2 GB Ram, 1.6 GHz Single Core, Intel OnBoard GPU ^^) .. sometimes it's pure pain, especially when using a heavy combination of non contiguous containers and lots of virtual methods (meanwhile is replaced all non contiguous containers and moved away from too much OOP). But I think the trouble is worth it, because it offers to use additional computer power for more highlevel tasks like AI.

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?
Title: Re:creation - a top down action rpg about undeads
Post by: Otherian on September 08, 2015, 07:59:38 pm
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

Have you taught the whole programming stuff to yourself?
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...
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler 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. :)
Title: Re:creation - a top down action rpg about undeads
Post by: Otherian 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)

Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler 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.
Title: Re:creation - a top down action rpg about undeads
Post by: SpeCter on September 09, 2015, 09:25:19 am
The book does have a second edition which came out recently btw.
Title: Re:creation - a top down action rpg about undeads
Post by: Glocke 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 :)
Title: Re:creation - a top down action rpg about undeads
Post by: SpeCter 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.

Title: Re:creation - a top down action rpg about undeads
Post by: dabbertorres 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.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler 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 (https://eliasdaler.wordpress.com/2015/09/08/using-lua-with-cpp-in-practice-part-2/)!
Title: Re:creation - a top down action rpg about undeads
Post by: SpeCter 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 ;)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler 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).
Title: Re:creation - a top down action rpg about undeads
Post by: Glocke 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 (https://eliasdaler.wordpress.com/2015/09/08/using-lua-with-cpp-in-practice-part-2/)!
Nice!
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler 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.
Title: Re:creation - a top down action rpg about undeads
Post by: nebula on September 10, 2015, 06:36:43 pm
I have a question.
When you release your game, in which languages will it be available?
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler 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).
Title: Re:creation - a top down action rpg about undeads
Post by: dabbertorres on September 10, 2015, 09:15:36 pm
You'll be happy to find this then (https://docs.google.com/spreadsheets/d/17f0dQawb-s_Fd7DHgmVvJoEGDMH_yoSd8EYigrb0zmM/edit#gid=310116733)! (Translations are on the Master sheet)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 10, 2015, 09:31:00 pm
You'll be happy to find this then (https://docs.google.com/spreadsheets/d/17f0dQawb-s_Fd7DHgmVvJoEGDMH_yoSd8EYigrb0zmM/edit#gid=310116733)! (Translations are on the Master sheet)
This looks pretty interesting, thanks. This would only help translate small part of the game. What about dialogues? They have to be translated by people. :)
Title: Re:creation - a top down action rpg about undeads
Post by: Jesper Juhl on September 10, 2015, 09:32:26 pm
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).
Depending on the amount of text (and your deadline) I'd probably be willing to do a Danish translation for a free copy of the game :)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 10, 2015, 09:34:22 pm
Depending on the amount of text (and your deadline) I'd probably be willing to do a Danish translation for a free copy of the game :)
Deal. ;)
I don't really know how much text there would be, but I'll contact you when all the text is written. :)
Title: Re:creation - a top down action rpg about undeads
Post by: SpeCter on September 10, 2015, 09:34:44 pm
I would gladly translate it to german if needed. Could do japanese as well, but i'll stick with my native language  ;)
Title: Re:creation - a top down action rpg about undeads
Post by: AlejandroCoria on September 10, 2015, 09:37:04 pm
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).

I would have no problems in translate to Spanish in my free time ;)
(I'm from Argentina)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 10, 2015, 09:50:10 pm
@SpeCter, @AlejandroCoria, thanks a lot! I'll start a list of potential translators and I'll message you once the game is mostly done. (This would take some time, though...)
Title: Re:creation - a top down action rpg about undeads
Post by: FRex on September 10, 2015, 10:44:19 pm
Depending on how much text there is I could maybe do a Polish version, but I'm not sure if I'll have the time because university year starts in few weeks. Also - how will it be done technically? Will there be a database of all strings in the game for each language or what? And which Lua version are you using? Also - another solution to nested tables problem littering the code with a lot of calls and checks in C++ is to just use a piece of Lua code like so:
luaL_loadstring(L, "local args = {...} package.loaded['bla.native.draw'] = args[1]");
lua_newtable(L);
//pushing methods
if(lua_pcall(L, 1, 0, 0))
{
//error handling ect.
}
It could be used to return a value from nested tables easily too, few calls, no own type checking of tables  or indexing, ect.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 10, 2015, 11:05:41 pm
Depending on how much text there is I could maybe do a Polish version, but I'm not sure if I'll have the time because university year starts in few weeks.
The translation won't be needed until the game is near release, and this may take a year or two. :)

Also - how will it be done technically? Will there be a database of all strings in the game for each language or what?
I think it would be a bunch of .csv files which you could edit in any editor you want (even in Excel :D)

And which Lua version are you using?
Lua 5.2.

Also - another solution to nested tables problem littering the code with a lot of calls and checks in C++ is to just use a piece of Lua code like so
Hmm, what problem are your referring to? And I can't quite understand what this code does...
Title: Re:creation - a top down action rpg about undeads
Post by: FRex on September 10, 2015, 11:22:47 pm
The problem of not being able to get a nested table just by calling
lua_getglobal(L, "someTable.interestingTable");
as you've written in https://eliasdaler.wordpress.com/2015/09/08/using-lua-with-cpp-in-practice-part-2/
I thought about iterating through name and checking for dots but I decided to not bother (and it'd break on names with dots in them like the module names) and instead push a piece of Lua code to stack and then call it so all type checking, ect. is done by Lua. That piece of code I've shown was to create a new library table and put it under name bla.native.draw into the package.loaded table so require can retrieve it, but you could get any nested table value out the same way:
luaL_loadstring(L, "return some.nested.table.value");
lua_pcall(L, 0, 1, 0)
{
//handle the errors, pop the error message, ect.
}
//some.nested.table.value is now on top of the stack

Quote
Lua 5.2.
Is there any special reason or feature that made you pick this over 5.1? I've used 5.2 for learning Lua because that's what was newest when I started but then went back to 5.1 so I could use LuaJIT if I wanted to and 5.3 issues made me think I made the right choice.
Title: Re:creation - a top down action rpg about undeads
Post by: dabbertorres on September 11, 2015, 05:05:01 am
I've gotten table keys and values like this (https://github.com/dabbertorres/LNA/blob/master/LuaCpp/Details/Details.hpp#L237-L268). It's how I've made an std::map<K, V> out of a Lua table (albeit, a Lua table with keys of the same type, and values of the same type).

I also ended up making syntax to get values from a table like:
bool someBool = luaState["someTable"]["anotherTable"]["yetAnotherTable"]["myBoolFinally"];
Title: Re:creation - a top down action rpg about undeads
Post by: Glocke on September 11, 2015, 10:00:41 am
I would love to have German, Spanish, French, Japanese and maybe other translations.
I could help with the German translation, because I'm German ^^ You could message me once you're ready for translation. Then we'll check whether I have enough time.
Title: Re:creation - a top down action rpg about undeads
Post by: SpeCter on September 11, 2015, 11:52:11 am
I would love to have German, Spanish, French, Japanese and maybe other translations.
I could help with the German translation, because I'm German ^^ You could message me once you're ready for translation. Then we'll check whether I have enough time.

We should work together then, so that when the time comes we won't do things twice ;)
Title: Re:creation - a top down action rpg about undeads
Post by: nebula on September 11, 2015, 01:05:31 pm
I volunteer as a tribute for german translation :'D put me on the list
Title: Re:creation - a top down action rpg about undeads
Post by: Tank on September 11, 2015, 01:29:08 pm
/me volunteers for a German translation.
Title: Re:creation - a top down action rpg about undeads
Post by: Rosme on September 11, 2015, 11:44:45 pm
<- This guy here volunteers for a French translation.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 12, 2015, 12:15:35 am
@FRex, don't really know how fast it is compared to my method. What concerns me is that you'd have to do luaL_loadstring for each table you want to get keys of which just doesn't seem right to me. :S

Quote
Lua 5.2.
Is there any special reason or feature that made you pick this over 5.1? I've used 5.2 for learning Lua because that's what was newest when I started but then went back to 5.1 so I could use LuaJIT if I wanted to and 5.3 issues made me think I made the right choice.
No, that was just the latest version of Lua when I started to do scripting. I didn't consider to use LuaJIT at that moment, so I went with 5.2. I don't think that I use lots of 5.2 features, so I think I can still use LuaJIT if this would be necessary. :)

@dabbertorres, yep, that's the best syntax to have, but implementing it with one function is impossible, but I've tried to create function which would explain the general concept as simple as possible.

To everyone who are volunteering for the translation: I've created a trello list which I would expand.
Thanks for offering your help, it means a lot :)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 16, 2015, 12:27:24 pm
Sorry for the lack of updates, been working on some awesome stuff and fixing bugs all week.
I'm working on a combat system and try to make it enjoyable and not boring. So far, the progress is great.
I'll work on the new art soon, so expect some cool screenshots and gifs.

I'm trying to focus more on making the game, not the engine for it, and it feels good. Are there any great articles about this? I want to plan better and focus on what's the most important.

And here's some random concept art:
(http://i.imgur.com/VJrChjK.png)
Title: Re:creation - a top down action rpg about undeads
Post by: Strikerklm96 on September 17, 2015, 05:57:51 am
This game looks awesome :) and as a novice programmer, I had some questions.

How do you make components interact? When a player damages another, what code and functions does that flow through?

For your lua, how does this get translated to an actual c++ instance of a GraphicsComponent?
Do you have to go through and set each value for the instance of GraphicsComponent to each value in the lua?
Like:
GraphicsComponent gc;
gc.filename = lua("GraphicsComponent.filename");
  GraphicsComponent = {
        filename = "res/images/chest.png",
        animated = true,
        defaultAnimation = "closed",
        z = 0,
        animations = {
            closed = {
                frame = {0, 0, 16, 16},
                numOfFrames = 1,
                frameTime = 0,
                looped = false
            },
            opened = {
                frame = {16, 0, 16, 16},
                numOfFrames = 1,
                frameTime = 0,
                looped = false              
            }
        }
    },


Or is there some way to get it to auto assign the values?
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 17, 2015, 08:16:18 am
Thanks!

When a player attacks, his weapon creates "damage" entity which contains DamageComponent and CollisionComponent. If CollisionSystem detects that "damage" bounding box intersected with some other entity, this entity's "damaged" Lua function is called. It may look like this:

damaged = function(this, second) -- this - entity which was damaged, second - entity which damaged it
    decreaseHealth(this, getDamageValue(second))
end

I go through each value in C++ when I create GraphicsComponent, yeah. But then I copy this GraphicsComponent in C++ without Lua script.
Title: Re:creation - a top down action rpg about undeads
Post by: Brax on September 17, 2015, 11:17:40 am
@EliasDaler I have a feeling this article might be of some use to you. :)

The art of enemy design in Zelda a link to the past (http://www.gamedev.net/page/resources/_/creative/game-design/the-art-of-enemy-design-in-zelda-a-link-to-the-past-r4147)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 17, 2015, 10:49:46 pm
Thanks a lot. It's very interesting and will be totally useful.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 18, 2015, 09:04:17 am
Another concept art of cafe
(http://i.imgur.com/D02Kwwl.png)
I'm working on art for it, so in-game screenshots will come soon. :)
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on September 18, 2015, 05:32:06 pm
I really like the scene you've drawn above. Looks to me (and this is just my take) that you have a retired pirate and one of his fellow pirates who died at sea and then they started a tavern together.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 18, 2015, 11:18:11 pm
I really like the scene you've drawn above. Looks to me (and this is just my take) that you have a retired pirate and one of his fellow pirates who died at sea and then they started a tavern together.
Thanks! That's a good interpretation, ha-ha.
I'm going to post the pixel art of them tomorrow. :D
Title: Re:creation - a top down action rpg about undeads
Post by: Jesper Juhl on September 18, 2015, 11:21:57 pm
I'm really impressed with what you are with this this game. Keep up the amazing work. It's really impressive.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 19, 2015, 04:45:22 pm
I'm really impressed with what you are with this this game. Keep up the amazing work. It's really impressive.
Thanks a lot. Very glad to hear that. :)

Okay, here's a new screenshot.
Undead cafe which I've been working on lately.
(http://i.imgur.com/PEOdJT3.png)
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on September 19, 2015, 05:07:12 pm
Looks brilliant as always. Do the characters in the cafe have backstories/sidequests?
Title: Re:creation - a top down action rpg about undeads
Post by: argh on September 19, 2015, 08:51:18 pm
This game looks amazing! (artwork, colors, layout. well everything is spot on tbh). Keep up the great work. I hope the release date will end some time soon ;)

Just wanted to cheer you on.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 19, 2015, 10:16:45 pm
@shadowmouse, thanks! Yes, all of them have backstories. I thought about making NPCs without any backstory, but I just can't do it! :D
As for the sidequests... probably. I haven't thought about it yet.

@argh, thanks! I'll try to work as hard as I can to finish the game as fast as possible without sacrificing its quality.
And feedback cheers me on for sure, so thanks again. :)

Progress update
Cute undead cat tells about its life:
(http://i.imgur.com/rrcZpty.gif)
And do you recognize the painting behind the cat?

There are some cool changes I've made lately.
First of all, I've changed the dialogue font. Compare it with the old one:
(http://i.imgur.com/DGuTNB5.png)
First of all, the new font is more readable. It also lets me fit a lot more text in the dialogue window.
The text doesn't scroll anymore. I think that separating text by meaningful chunks (1-2 sentences) keeps it more readable. That's how most games do it, anyway.
Because I have to fit as much as I can in one screen, rephrasing stuff is important. I think it's a good thing, because it keeps text short and precise (most people don't like to read long texts in games, unless it's a huge RPG with deep history).

I will also start to add line breaks myself (I was breaking text in lines automatically before). It lets me compose the text manually, so it looks and reads a lot better. If you look closer at NES/SNES games with lots of dialogue, you'll notice that most of the text fits the box very neatly.
To do this more easily, I'll create a tool which will let me edit text in it and immediately see how it will look in the game. This tool would also be useful for translators, I think. (especially for languages which have long words!).
I also added little talking animation which makes things a bit more lively. :D

I'll also start to move animation data from Lua to JSON, so the script won't take as much space as its currently does. For example, main hero's script is now 504 lines. 354 of them is devoted to animation descriptions (location on the sprite sheet, frame time, etc.). And there's no need to keep info like that in Lua files, because this info doesn't use any Lua capabilities. So, I would move each animation description into JSON file and then just write something like this in the script:
GraphicsComponent = {
    ... -- some stuff
    animations = "anim/hero.json"
}
This animation info would be loaded in C++ later.

Oh, and one more thing. I finally came up with the name of the main character! I'll tell you later with some other cool stuff. ;)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 20, 2015, 01:44:19 pm
I've moved animation descriptions to JSON.
This removed 1047 lines from Lua scripts which is cool, as scripts are now more compact and easier to edit.

I also made a dialogue tool. It took me just half an hour to make!
(http://i.imgur.com/l8ZmDX6.gif)
Yes, line breaks can be easily inserted automatically. But this tool lets me compose the text in such way, that there's no situations like this:

Code: [Select]
Some text, some text, some text
some_very_long_word_which_doesn't_fit_in_previous_line, even more text,
a giant space is left on the first line. Meh, not cool!

This also lets me see how much text I can still fit in this box. I don't want to break one long sentence into several boxes, because this may be not very readable.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 21, 2015, 06:18:38 pm
Here's something another... I've decided to write music for the cafe. Hope you enjoy. :D
https://soundcloud.com/elias-daler/cafe-demo
Title: Re:creation - a top down action rpg about undeads
Post by: nebula on September 22, 2015, 07:50:11 pm
Sounds nice, but where do you want to loop it? :D
Title: Re:creation - a top down action rpg about undeads
Post by: Jesper Juhl on September 22, 2015, 08:02:40 pm
This game is super impressive (and inspirational). When I consider how much I struggle with graphics and sound for my own game (the code I can manage) I almost can't believe you're doing this alone - fscking well done!
My hat comes off for you sir.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 24, 2015, 08:23:56 am
@nebula, thanks! I want to loop it from the measure when the bass starts to play. This is not the beginning of the song, so I would have to figure out a way to loop songs from the specified time.

@Jesper Juhl, thanks a lot. Very glad that it inspires you, this fact inspires me! :D

Btw, I've decided not to use Zelda's perspective anymore. I'll try to remake cafe in FF/Seiken Dentesu's perspectives and Mother 3 perspective. Will post results later. :)
Title: Re:creation - a top down action rpg about undeads
Post by: Mortal on September 24, 2015, 09:53:20 am
i just did quick scan for your older posts and i found that you are making graphic arts and coding but in last posts you're also, making music composing. that indeed impressive. to be honest with you, i can't do that no way, it needs super talent guy like you to accomplish that, ain't me, i'm just average guy who's barely can coding in c++ mostly copy and paste from others. ;D

me too My hat comes off for you sir.

it seems this game is well written and best to learn from. i have question are you going to make this game open source?
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 24, 2015, 10:24:29 pm
i just did quick scan for your older posts and i found that you are making graphic arts and coding but in last posts you're also, making music composing. that indeed impressive. to be honest with you, i can't do that no way, it needs super talent guy like you to accomplish that, ain't me, i'm just average guy who's barely can coding in c++ mostly copy and paste from others. ;D

me too My hat comes off for you sir.
Thanks a lot!

Everyone is average (or worse! :D) at one point.
Start with some smaller games (Pong, Tetris, etc.) and read some books on C++. I highly recommend "C++ Primer" by Stanley B. Lippman. Continue working hard and you'll sure become awesome! :D

it seems this game is well written and best to learn from. i have question are you going to make this game open source?
Not sure about all the game being well written, but there are some good parts, at least some working ideas.
I ocassionally post about them in dev log, on my blog or in my tutorials, so you'll understand a lot about my engine if you read this stuff.
There's a possibility that I'll make my game (or at least some part of it, like main components) open source. But to do that, I have to release the game first. I'll see how good the code is when it happens. :)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 26, 2015, 02:14:17 pm
Okay, here's the biggest change in the art in a long time. I've changed pespective to axonometric 3/4.
(http://i.imgur.com/6hqLHuZ.png)
Just compare it with the old one:
(http://i.imgur.com/BsoAP9z.png)
GIF:
(http://i.imgur.com/TAfsl29.gif)

Drawing in this perspective is a lot easier, because all lines are straight. It's also a lot less confusing and more readable!
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on September 26, 2015, 02:55:33 pm
Are you changing only the inside of buildings, or everything? I'm kind of biased towards the former mode because Zelda games, but I can see why you prefer the new version over the older one.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 27, 2015, 12:56:45 pm
Are you changing only the inside of buildings, or everything?
If you take a look at these screenshots, you'll see that perspective there is already axonometric 3/4. Zelda uses the same perspective outside.

(http://i.imgur.com/EJzHdlj.png)
(http://i.imgur.com/LNGqqXe.png)

I'm kind of biased towards the former mode because Zelda games, but I can see why you prefer the new version over the older one.
I can understand why Zelda perspective may look more appealing. But I've thought about this and figured out that it gives me no advantage at all. It's actually harder to pull off because other stuff should follow this pespective. Now sprites are a lot of easier to make. Compare these two sprites, for example:
(http://i.imgur.com/iMo1XtP.png)
The right one is a lot easier to draw and looks cleaner, which is cool about axonometric perspective too :)
Title: Re:creation - a top down action rpg about undeads
Post by: Glocke on September 27, 2015, 06:21:56 pm
Great job - awesome drawing skills ;)

Btw: Some pages ago, I read that you want to update all systems at once without calling each system individually. As I remember you had not base class for your systems, so a common collection like std::vector<std::unique_ptr<BaseSystem>> systems isn't possible.

Have you solved the problem yet without introducing a base class?
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 27, 2015, 11:24:24 pm
Great job - awesome drawing skills ;)
Thanks!

Btw: Some pages ago, I read that you want to update all systems at once without calling each system individually. As I remember you had not base class for your systems, so a common collection like std::vector<std::unique_ptr<BaseSystem>> systems isn't possible.

Have you solved the problem yet without introducing a base class?
Right now I have base class IEntitySystem and template class
template <typename ComponentType>
class EntitySystem {
    ...
    std::vector<ComponentType*> components;
}

So I can store systems like this:
std::vector<std::unique_ptr<IEntitySystem>>
Works quite well! (No casts needed, because IEntitySystem has such virtual methods as update and process)
Title: Re:creation - a top down action rpg about undeads
Post by: Glocke on September 28, 2015, 08:08:17 am
Works quite well! (No casts needed, because IEntitySystem has such virtual methods as update and process)

Ah cool! :) I just found another solution without a base class - but with some heavy template meta-programming using C++11 parameter packs.
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on September 28, 2015, 06:56:27 pm
I prefer the newer perspective and the artwork is - unbelievably - still improving!
Title: Re:creation - a top down action rpg about undeads
Post by: Mörkö on September 29, 2015, 07:39:39 am
The new style looks much better.

Seeing all four walls of a room doesn't make any sense when the objects in the room are shown only from one side.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 29, 2015, 03:29:06 pm
Ah cool! :) I just found another solution without a base class - but with some heavy template meta-programming using C++11 parameter packs.
Neat. How can you access a particular system in your engine?

I prefer the newer perspective and the artwork is - unbelievably - still improving!
Thanks a lot!

The new style looks much better.

Seeing all four walls of a room doesn't make any sense when the objects in the room are shown only from one side.
Thanks. I agree, though some games used weird perspectives pretty good, I'm not able to pull it off, so using a more convenient one is better.
Title: Re:creation - a top down action rpg about undeads
Post by: Nexus on September 29, 2015, 10:21:09 pm
I think the problem with the previous perspective was still what I mentioned earlier (http://en.sfml-dev.org/forums/index.php?topic=18062.msg134432#msg134432): mixing perspective and parallel projection.

Games with an actual top view (not a front-top angle) such as GTA2 are usually rendered with perspective, even if it may be faked implementation-wise. There are games that mix both successfully (e.g. Binding Of Isaac), but it works because the game focuses much more on action/enemies than on scenery and art.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on September 30, 2015, 12:26:35 am
So, do you like the new perspective? :D
Title: Re:creation - a top down action rpg about undeads
Post by: Glocke on September 30, 2015, 08:36:53 am
Ah cool! :) I just found another solution without a base class - but with some heavy template meta-programming using C++11 parameter packs.
Neat. How can you access a particular system in your engine?

In a nutshell:
int main() {
        SystemA a;
        SystemB b;
        SystemC c;
        SystemD d;
       
        EntityUpdater<SystemA, SystemD, SystemB, SystemC> updater{a, d, b, c};
        updater.update(sf::milliseconds(20));
        updater.update(sf::milliseconds(19));
        updater.update(sf::milliseconds(23));
        updater.update(sf::milliseconds(30));
        updater.update(sf::milliseconds(12));
        updater.update(sf::milliseconds(20));
       
        std::cout << "Total time for System A: " << updater.getTotal<SystemA>().asMilliseconds() << "ms\n";
        std::cout << "Total time for System B: " << updater.getTotal<SystemB>().asMilliseconds() << "ms\n";
        std::cout << "Total time for System C: " << updater.getTotal<SystemC>().asMilliseconds() << "ms\n";
        std::cout << "Total time for System D: " << updater.getTotal<SystemD>().asMilliseconds() << "ms\n";
}

But providing something like
template <typename... Args>
struct EntityUpdater
        : MultiUpdater<Args...> {
       
        EntityUpdater(Args& ...args)
                : MultiUpdater<Args...>{std::forward<Args&>(args)...} {
        }
       
        // should also be possible
        template <typename T>
        T& getSystem() {
                return SingleUpdater<T>::system;
        }
};

In more detail:
(click to show/hide)
(Source linked)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on October 02, 2015, 07:47:06 am
Glocke, that's a cool implementation. But yeah, looks like it may cause increased compilation time. Especially if you have lots of systems. And doesn't this approach creates a high compilation dependency between systems? By changing one system, you may cause lots of unnecessary recompilation.

Base class approach is working good, because most of the time you don't really care about what components this system works with. You just call update() and process() and you're done.
But, in case I need to get a particular system, I can do it by dynamic_cast. :)

Progress update
Can't really show much at the moment. Working on the cool fog system which I hope to show off soon. It's not just overlay sprites, clouds can actually be of any height and interact with objects they collide with!
I'm also prototyping some stuff. I've understood that this is absolutely neccessary.
This is something which I need to be used to. Drawing raw, unpolished sprites, making levels without lots of details, etc.
If I make a level with some detail (even not a lot of it), changing stuff becomes harder. So, raw prototyping helps here. Just draw some boxes, throw them on the map and change them to get a good level. And then I can start with details. But it's actually pretty hard, because I want the game to look good all the time, but I have to overcome this thing. Does anyone feel that about their games? :D
Title: Re:creation - a top down action rpg about undeads
Post by: Glocke on October 02, 2015, 01:19:51 pm
Glocke, that's a cool implementation.

Thanks :)
And doesn't this approach creates a high compilation dependency between systems? By changing one system, you may cause lots of unnecessary recompilation.

Yes it does. But I'd recomment to use such an approach at the very high end of the module stack - e.g. right before the actual game's mainloop (e.g. at the game state if you're using something like a state machine to switch between different states like menus).

But, yes: The approach using a common interface (which virtually provides update etc.) is better for decoupling, because the Headerfile (where you declare the systems vector) only depends on the interface declaration and the cpp-File includes everything else. So everything that depends on the header (which provides the systems vector) doesn't need to be recompiled when a system is added (only the corresponding cpp-File which depends on the systems is needed).

About your dynamic casts: Personally, I could think of something like
class ECS {
    private:
        std::vector<std::unique_ptr<BaseSystem>> systems;

    public:
        // create system
        template <typename T, typename ...Args>
        std::size_t create(Args&& ...args) {
            // emplace system and return index
        }
       
        // query existing system
        template <typename T>
        T& operator[](std::size_t index) {
            return *systems[index].get();
        }
        // + const overload
};
plus some is_base_of etc.
But at the moment I use
// session.hpp
struct Session {
    MovementManager& movement;
    CollisionManager& collision;
    // ...

    // + ctor that initializes the references
};

// ecs.hpp
struct ECS {
    MovementSystem movement;
    CollisionSystem collision;
    // ...

    Session session;
    std::vector<Updateable*> updateables;

    // + ctor that initializes all systems, the session and the updateables
};
FooManager is the pure FooComponent container, FooSystem is based on FooManager and has update logic etc. (which is implemented for the Updateable interface). So I can pass that Session reference where ever I those component managers (e.g. to a factory that creates complete objects). So the factory depends on the Component definition (+ their manager definition which is very simple) but not on the actual system.

Well this isn't perfect either^^

About your progress update: Can you tell us more about your fog system? Personally, I'm using a simple lightingsystem in my game, which produces dynamic shadows. What's the idea of your (upcomming) fog system yet? :)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on October 04, 2015, 10:24:37 am
About your dynamic casts: Personally, I could think of something like
*code*
Yep, that's how I currently do it. But this code won't work:

template <typename T>
T& operator[](std::size_t index) {
    return *systems[index].get();
}

Because you can't convert from BaseSystem to DerivedSystem
This is what I do:

template <typename T>
T& operator[](std::size_t index) {
    return *(std::dynamic_pointer_cast<T>(systems[index].get())); // systems are shared_ptr, can't do this with unique_ptr
}

But at the moment I use
It's okay when you have a small number of systems, but as it increases, this stuff becomes more difficult to work with.

About your progress update: Can you tell us more about your fog system? Personally, I'm using a simple lightingsystem in my game, which produces dynamic shadows. What's the idea of your (upcomming) fog system yet? :)
Something like this:
(http://i.imgur.com/CuN6YuP.png)
The height of the cloud can vary and the cloud can move, so I have to draw it differently depending on the object which are in it. I'll explain how I do it a bit later. :)
Title: Re:creation - a top down action rpg about undeads
Post by: Glocke on October 04, 2015, 11:19:10 am
Something like this:
(http://i.imgur.com/CuN6YuP.png)
The height of the cloud can vary and the cloud can move, so I have to draw it differently depending on the object which are in it. I'll explain how I do it a bit later. :)
Looks very interesting. I'm curious about your explanation!
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on October 06, 2015, 01:33:42 pm
Okay, here's how the fog looks in the game
(http://i.imgur.com/3VYHeU2.gif)

Notice, that it's not just an overlay. It actually has some height and draws depending which objects are in it. Just a neat simple effect...

This wasn't easy to make, though. Here's how it works:
(http://i.imgur.com/FbNfLlU.png)
Suppose we have one object. First, we draw the part of the fog which is behind it. Then we draw the object itself. After that, we draw the rest of the fog sprite in front of the object.
It all depends on the line which divedes the front and the back.It's easy to get it by substracting fog height (in pixels) from lowest Y coordinate of the object.
So, I split one big sprite in smaller ones depending on objects around.

Stuff becomes a lot harder if there are several objects in fog. I won't explain how to deal with it, as it would take too much time, but stuff works mostly the same.
And by the way, the most interesting thing about it is that the fog sprites don't move. Only textures move on sprites. This is done to make tiling of fog easier. I don't have to create additional sprites to do this, sprites just follow the camera if it moves.

There are other stuff I can do with this system. Like simulating water (some stupid undead forgot to turn off the taps...)
(http://i.imgur.com/nW4m3cY.png)

Or deep snow...
(http://i.imgur.com/BwJY76t.png)
You get the idea. It's always cool to reuse stuff like that!
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on October 06, 2015, 05:25:33 pm
May I suggest that if you are going to do water effects or snow effects then use a texture. Before I read the whole post, the second and third images just looked like a sort of weird version of fog of different intensities. Either giving it a texture across the whole  thing, or by the edges would make it clearer what the effect is.
Title: Re:creation - a top down action rpg about undeads
Post by: select_this on October 06, 2015, 06:09:03 pm
I think it was more of a demonstration of the versatility of his solution rather than "this is how I want it to look", but I do agree that it does look rather odd to have flat colours - especially the snow one, due to the lack of translucency :)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on October 06, 2015, 08:30:57 pm
I think it was more of a demonstration of the versatility of his solution rather than "this is how I want it to look", but I do agree that it does look rather odd to have flat colours - especially the snow one, due to the lack of translucency :)
Yeah, that's just to show off that it's possible to use the solution in different ways . Of course, I'll add texture if I decide to use in in some level. Snow would have some footprints on it, some snowdrifts, etc.
Title: Re:creation - a top down action rpg about undeads
Post by: Nerevar on October 06, 2015, 08:38:13 pm
What size of sprites(objects,tiles,gui) you use in your game?
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on October 06, 2015, 09:54:02 pm
What size of sprites(objects,tiles,gui) you use in your game?
Most of the gifs and screenshots I make are upscaled 2x. So, you can take any screenshot/gif and check it out for yourself. The original resolution is 256x240.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on October 09, 2015, 09:00:56 am
Fixed one big bug where hero's sprite was shaking during camera scrolling. Turns out, I was setting the updated camera view too late (somewhere in the rendering phase, he-he). This took me like 3-4 hours to find! I'm not a clever man, heh.

As for 256x240 resolution. I've chosen this resolution because of SNES (but actually SNES is 256x224!).
So, I'm thinking about changing resolution to either 256x244 or 320x240 (4:3!).
320x240 would actually be cool because it would give me more horizontal space.

16:9 ratio for resolution would be cool, but I think that this would make my game look weird and too much horizontal space is not needed anyway (it's better for platformers).
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on October 12, 2015, 04:53:58 pm
Your fog (/water/snow) effect looks pretty cool!

I noticed that they're all at the same height (from the ground) though. Is it possible in your system to adjust this height as required or is it hard-coded at that height?
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on October 12, 2015, 06:38:27 pm
Your fog (/water/snow) effect looks pretty cool!

I noticed that they're all at the same height (from the ground) though. Is it possible in your system to adjust this height as required or is it hard-coded at that height?
Thanks!
It's possible to adjust the height, but it's not currently possible to adjust height for individual clouds because the code becomes very complicated. But it's possible that I'll create "layers" of fog at different heights which may make the effect even cooler! :D
Title: Re:creation - a top down action rpg about undeads
Post by: Hapax on October 12, 2015, 06:41:46 pm
It's possible to adjust the height, but it's not currently possible to adjust height for individual clouds because the code becomes very complicated. But it's possible that I'll create "layers" of fog at different heights which may make the effect even cooler! :D
Sounds cool  :)

Can the height be dynamically altered, like a water level rising/falling, for example?  ;)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on October 12, 2015, 07:38:51 pm
Can the height be dynamically altered, like a water level rising/falling, for example?  ;)
Yeah, the height is just a variable which can be easily changed. :)
Title: Re:creation - a top down action rpg about undeads
Post by: Mario on October 13, 2015, 11:14:54 am
Not sure, but from your explanation the fog drawing sounds more complicated, especially if there are multiple things around close by.

Could think of two alternative approaches:

Or even easier when using a shader:

Of course the latter gets more complicated with multiple layers.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on October 14, 2015, 06:46:29 am
Mario, thanks for your suggestions. At first I thought I'd say "the first approach is cool, but I want it to be like this:

std::vector<sf::Sprite*> renderList;
... // form it from all entities on the screen
applyFog(renderList);
... // do other stuff
for(auto sPtr : renderList) {
    ... // render
}
"

But then I 've realized that this is possible to do with the first method, I just need to divide sprites in parts and then put sprite parts under the first layer of fog in the renderList, then add fog sprite of the first level, then add all sprite parts under the second layer of fog, etc.
So, I'll need to create sf::Sprite for parts of all entities in the fog, but I think it's okay and won't be a problem!

I can't really understand the second approach, though. Can you explain it more, please?
Title: Re:creation - a top down action rpg about undeads
Post by: Glocke on October 14, 2015, 08:28:37 am
Or even easier when using a shader:
  • Determine depth in the fog.
  • Mix textures depending on the depth.
I can't really understand the second approach, though. Can you explain it more, please?
Maybe:
(*) And let the shader manipulate all pixels that should be affected by the fog. So if your sprite has a height of 64px and the fog should have a height of 24px, the shader will leave all pixels with height 0-39 as they are, but change the pixels with height 40-63 to be "fogged". I could imagine of using a gradient here, too!

At least that's what I understood :D
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on October 14, 2015, 08:59:54 pm
Glocke, yep shaders might do the trick. But I've never worked with shaders before, so this may be quite a challenge for me... Which I'll try to beat a bit later. :D

Right now I'm working on refactoring and making the game more playable. There were some game breaking bugs which I was okay with. Not anymore. As I work toward playable build, I have to reduce the number of bugs. Hopefully, this won't take long as the game is mostly (sometimes surprisingly) stable.
Title: Re:creation - a top down action rpg about undeads
Post by: argh on October 14, 2015, 09:33:31 pm
Right now I'm working on refactoring and making the game more playable. There were some game breaking bugs which I was okay with. Not anymore. As I work toward playable build, I have to reduce the number of bugs. Hopefully, this won't take long as the game is mostly (sometimes surprisingly) stable.

Can't wait  8)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on October 14, 2015, 11:57:29 pm
Can't wait  8)
I can't really promise a lot. If I'm able to finish it this year, this is going to be a miracle, ha-ha.
There's just lots of content I have to make. I want to make a good first impression, so I want a polished and awesome demo.
Hobby game dev is a long process.  :-[
(Any tips on speeding it up everyone? :D)
Title: Re:creation - a top down action rpg about undeads
Post by: shadowmouse on October 15, 2015, 08:16:09 am
What sped up the development of my current project the most, was moving to using bitbucket and source tree. Once I got it I immediately stopped putting off doing big things in case they broke it, because I would be working on a different branch and could always switch back again, but it also seemed to increase my coding speed once I was confident that whatever I did, it wouldn't be irreversible.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on October 15, 2015, 10:24:53 am
What sped up the development of my current project the most, was moving to using bitbucket and source tree. Once I got it I immediately stopped putting off doing big things in case they broke it, because I would be working on a different branch and could always switch back again, but it also seemed to increase my coding speed once I was confident that whatever I did, it wouldn't be irreversible.
Currently using it! Can't really get into branching yet, because I can't work on the one independent part of the code. Most of the code I write affects other stuff, so I can't be sure that if I return there'll be no collisions. But this is just for now, because I work on the engine and fix lots of stuff. Separating systems by using events will help a lot too. :D
And when most of my job will be done by writing scripts... that's where real fun begins and stuff will go pretty fast! :D
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on October 15, 2015, 11:51:14 pm
Here's a summary of what I've made during the last five months.
https://eliasdaler.wordpress.com/2015/10/15/recreation-dev-log-june-october-2015-theres-a-lot-of-stuff-made/
It's so good to look back and see how much of the stuff changed and improved.
Title: Re:creation - a top down action rpg about undeads
Post by: Glocke on October 16, 2015, 09:02:54 am
Glocke, yep shaders might do the trick. But I've never worked with shaders before, so this may be quite a challenge for me... Which I'll try to beat a bit later. :D

Don't hesitate to work with shaders :) Once you're in, there are lots of possibilities. As an example: When I started working on my game's lighting implementation, I had never worked with shaders before. But the result is quite great!
(example image inside spoiler, because it's offtopic somehow ^^)
(click to show/hide)
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on October 16, 2015, 09:14:36 am
Don't hesitate to work with shaders :) Once you're in, there are lots of possibilities. As an example: When I started working on my game's lighting implementation, I had never worked with shaders before. But the result is quite great!
(example image inside spoiler, because it's offtopic somehow ^^)
(click to show/hide)
Okay, I'll try something out. Do you know any great tutorials on GLSL? :)
Title: Re:creation - a top down action rpg about undeads
Post by: Glocke on October 18, 2015, 09:44:16 am
Okay, I'll try something out. Do you know any great tutorials on GLSL? :)
Sorry, I don't :D

But here are my shaders for rendering a sprite with some brightness and saturation (I use it for blinking animations)
sprite_shader.loadFromMemory(
        "uniform float brightness, min_saturation, max_saturation;" \
        "uniform sampler2D texture;" \
        "void main() {" \
        "       vec4 pixel = gl_Color * texture2D(texture, gl_TexCoord[0].xy);" \
        "       pixel = vec4(clamp(pixel.rgb, min_saturation, max_saturation), pixel.a);" \
        "       gl_FragColor = vec4(pixel.rgb * brightness, pixel.a);" \
        "}",
        sf::Shader::Fragment
);
and for rendering a lighttexture (which is a major part of my lighting implementation).
light_shader.loadFromMemory(
        "uniform vec2 center;" \
        "uniform float radius;" \
        "uniform float intensity;" \
        "void main() {" \
        "       float dist = distance(gl_TexCoord[0].xy, center);" \
        "       float color = exp(-9.0*dist/radius);" \
        "       gl_FragColor = vec4(gl_Color.xyz * color, 1.0);" \
        "}",
        sf::Shader::Fragment
);
Setting up the sprite_shader before rendering looks like this:
sprite_shader.setParameter("brightness", brightness);
sprite_shader.setParameter("min_saturation", min_saturation);
sprite_shader.setParameter("max_saturation", max_saturation);
sprite_shader.setParameter("texture", sf::Shader::CurrentTexture);
Prerendering a light texture is shown here:
sf::RenderTexture buffer;
buffer.create(size, size);

// prepare shadeable object
sf::VertexArray array{sf::Quads, 4u};
array[0].position = {0.f, 0.f};
array[1].position = {size, 0.f};
array[2].position = {size, size};
array[3].position = {0.f, size};
for (std::size_t i = 0u; i < 4u; ++i) {
        array[i].texCoords = array[i].position;
        array[i].color = sf::Color::White;
}

// render lightmap
buffer.clear(sf::Color::Black);
light_shader.setParameter("radius", radius);
light_shader.setParameter("center", {size / 2.f, size / 2.f});
buffer.draw(array, &light_shader);
buffer.display();
Later the resulting texture is applied to the scene using a suitable blend mode. The lighting texture is attached (so you can see the result).

Maybe those shaders can help to when experimenting.
Title: Re:creation - a top down action rpg about undeads
Post by: Elias Daler on October 24, 2015, 07:34:30 am
Glocke, thanks for your code. :)
I think I'll need shaders to create cool effect when the player turns into a ghost. Still not sure how it will look like.

Progress update
So, I've been refactoring and improving the code this week. This actually feels very good, because I'm fixing a lot of bugs and improving the readability and structure a lot. I'll tell more about stuff I've been doing a bit later.

So, I have a question about one aspect of the code.

For a lot of time I could get components from entities with this function:
template <typename T>
T* Entity::get() {
    ...
    if(...) { // component found
        return componentPtr;
    }
   return nullptr; // component not found
}

And I could check if the component exists like this:
auto gc = entity->get<GraphicsComponent>();
if(gc) { // do stuff
     ...;
}

This is needed for two reasons:

1) Systems check if entities have components which they are interested in

2) C++ functions which can be called from Lua check this to send error messages if you call something like setAnimation(e, "anim") for entity which has no GraphicsComponent.

But what if I return the references instead?
template <typename T>
T& Entity::get() {
    ...
    if(...) { // component found
        return component;
    }

   ??? // component not found
}
 

The question is: what do I do in the situations where entities don't have the component? I think I can do it like this:
template <typename T>
T& Entity::get() {
    assert(...); // check if component is found
    ...
    return component;
}

And I'll have to check if entity has a particular component if I'm not sure if the components exist
if(e->hasComponent<GraphicsComponent>() {
    auto& gc = e->get<GraphicsComponent>();
} else {
    ... // do something else
}
 

So, I think this is better than getting nullptr errors where I don't check if component exists and it doesn't.
GraphicsComponent* gc = e->get<GraphicsComponent>(); // nullptr
gc->doSomething(); // crash!
vs
GraphicsComponent& gc = e->get<GraphicsComponent>(); // assert!
gc.doSomething() // component totally exists, because if assert aborted the program, we won't be there

Is this a good way to do things? Is there a better way to do it? Maybe returning the pointer to component is fine?
Title: Re:creation - a top down action rpg about undeads
Post by: Glocke on October 24, 2015, 11:06:56 am
Is this a good way to do things? Is there a better way to do it? Maybe returning the pointer to component is fine?
Personally, I'm using a pure get without extras! My getter returns a reference (or const reference if suitable), and I use a has()-Operation to query existence. Its great for readability: Prefering references over pointers (where pointers have to be non-null) is always good. So I always branche !has() to return early (e.g. no damage calculation if no health component) or do something alternative (e.g. writing to a log that the component is missing but shouldn't be ^^). Personally, I also use lots(!) of assertions, which help readability, "understandability" and "refactorability", as well as "debugability" ...
So the separation of has and get makes sense for my coding, because I'm asserting stuff anyway. But the separation can also be used without asking for the actual component, e.g. to check for logical paradox.. maybe an object has either a FooComponent or a BarComponent (not both, not none) ... this can be tested without asking for the actual components - if required.

So my code looks similar, like this:
assert(movesys.has(actor_id)); // ignored in production code
auto& movedat = movesys.get(actor_id); // safe in dev code
++movedat.pos.x; // etc.
or
if (!animationsys.has(actor_id)) { // also evaluated in production
    log << "Object << " << actor_id << " cannot be animated\n";
    return;
}
auto& anidata = animationsys.get(actor_id); // always safe
// do whatever

My getters have some assertions, too - to avoid memory violation. But they do not check anything in production code.. just deliver the component as fast as possible. If the code needs to change using existence, I use has additionally before querying a component.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on October 24, 2015, 11:34:07 am
Glocke, awesome, thanks for explanation. :D
I was using A LOT of pointers before and I think I need to refactor this a bit because sometimes references are much nicer, yeah. As for assertions... I've been using them from time to time, but I was using console output for errors mostly.  I think I need to use them more to make my game more stable and to prevent some stupid bugs in the future. :D
Title: Re:creation - a top down action adventure about undeads
Post by: Glocke on October 26, 2015, 11:56:00 am
for assertions... I've been using them from time to time, but I was using console output for errors mostly. I think I need to use them more to make my game more stable and to prevent some stupid bugs in the future. :D

Personally, I prefer "testable" assertions (which to not abort while unit testing, but throw a specific exception that can be expected and caught) to guarantee (during unit testing) that specific conditions do not happen.

For error logging, I wrote a minimal wrapper using some operator<< and an assign() operation, which adds a logging target. So I can create a "Logger"-instance debug which can be used like
std::ofstream file{"debug.log"};
Logger debug;
debug.assign(file);
debug.assign(std::cout);
// ...
debug << "Position is " << myVector << "\n";
(with additional overloads for e.g. sf::Vector<> etc.) and write this to a specific log file and stdout. Both are some kind of basic output streams, so each call to debug's operator<< calls each assigned ostream's <<.

(My previous approach is part of my SfmlExt Lib, the new approach will be added as I have enough time to do it.)
Title: Re:creation - a top down action adventure about undeads
Post by: Tank on October 28, 2015, 09:29:38 pm
I was facing the get/has/etc "problem" before as well. Two options:

1) Like Glocke said, split get() up into get() and has(), where get() contains an assertion (reason: calling get() without making sure that the object exists via has() is a programming error, so report to developer only).
2) Rename get() into find(). Find operations, by definition, can either return a hit or nothing. The return type would be a pointer in this case, and I think it's perfectly legit.

Personally I use find() wherever I can, because it's less error-prone and avoids code duplication (both get() and has() will query the same thing).

Btw, I wrote some lines about that topic on my blog (http://www.optank.org/2013/10/11/game-development-design-4-errors/).
Title: Re:creation - a top down action adventure about undeads
Post by: Nexus on October 28, 2015, 10:10:35 pm
So my code looks similar, like this:
assert(movesys.has(actor_id)); // ignored in production code
auto& movedat = movesys.get(actor_id); // safe in dev code
Why not embed the assertion into get()? Makes code safer and more readable on call site.

You mention that you do it sometimes later, why not always? Getting something non-existing is always a mistake, as Tank pointed out.

1) Like Glocke said, split get() up into get() and has(), where get() contains an assertion (reason: calling get() without making sure that the object exists via has() is a programming error, so report to developer only).
Yes, exactly.

However, has() is an explicit case differentiation which may often be solved more elegantly using different design. If you end up having a lot of code such as:
if (e.has(thisComponent))
   doThis();
if (e.has(otherComponent))
   doSomethingElse();
...
you should think about restructuring the systems, so that code paths are selected depending on the available components a priori and implicitly.
Title: Re:creation - a top down action adventure about undeads
Post by: Glocke on October 29, 2015, 08:17:38 am
Why not embed the assertion into get()? Makes code safer and more readable on call site.
I placed an assert into both: get() and call site. This is because I faced problems while unit testing. My assertion macro expands to throwing a special exception in case of building the unit tests. Unfortunately I didn't get the configurations for boost test right (I'm not quite sure whether they even exist) to produce a call stack when an untested exception was thrown. So I get something like `AssertionFailed` thrown in component.hpp at line XY (that's the file which defines an abstract component system), which doesn't help my to find the right spot where I accessed an invalid object. When I move that assertion into the actual function (which is directly called by the corresponding unit test, so I don't need a callstack here), I'm able to figure out where my precondition has failed.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on October 29, 2015, 03:55:30 pm
Thanks for bringing up some awesome points, guys. I especially agree on using find() vs get() with Tank. Tank's article is also very awesome. :D
I didn't know about _ASSERTE. This works much better than assert from assert.h. Not only because it doesn't execute functions in release build, but because it actually lets you see the call stack (with assert the call stack is just some random stuff). So, I guess I'll be using _ASSERTE in the future. :D

Progress update
I'm almost finished with refactoring. The structure of the engine is much better. I've also done some stuff like fixed-time step, better collision testing (spatial partitioning with grids) and some other stuff. I plan to write a blog post about the stuff I've done this Saturday or Sunday.

I also plan to finish demo prototype by the end of November. There will be some finished stuff and there'll be some placeholder art/NPCs/dialogue, etc.
The best case scenario is me finishing the demo by the end of this year, testing/polishing it for a month and then releasing somewhere by the end of January or somewhere near my birthday, ha-ha (which is on the 2nd of February).

And by the way, Re:creation is now 2 years old. Please, don't use this as a way to tell how much I have to work to finish the game. Now that I have a set of good tools and better experience with art, I'll be able to work much faster. Most of the work I've done during those two years was about creating the engine from almost a scratch. And I'm glad that I did, because now I know lots of stuff about game dev and have an awesome system which I'm quite proud of.
I'm almost done with the engine, there are some minor things I've yet to add, but they'll be implemented quite fast. Most of the game I have in mind can be implemented with the tools I already have. This makes me very happy.
So, the new era of Re:creation development will begin soon. Thank you for supporting me so far, I hope you'll get some cool stuff from my future work. :D

(http://i.imgur.com/Lc7zy11.png)
Title: Re:creation - a top down action adventure about undeads
Post by: SeriousITGuy on October 30, 2015, 11:03:04 am
Congrats on keeping up the work for two years, can't wait to get my hands a copy of your game.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on October 31, 2015, 10:52:35 pm
Congrats on keeping up the work for two years, can't wait to get my hands a copy of your game.
Thanks

Okay, here's what I've been doing today:
Lua enums
As you may know, Lua doesn't have enums. But sometimes I need to pass C++ enum value into Lua function and do something based on it.

Suppose I have this enum in C++

enum class Direction {
    Up,
    Down,
    Left,
    Right
};

Previously I converted enum values to strings (using std::map<Direction, std::string>) and then used it like this in Lua:

if(direction == "Up") then
    ... -- do something
end

This was alright for a while, but now I've realized that I can do something a lot better!
Here's what I can do now:

if(direction == Direction.Up) then
    ... -- do something
end

Direction is a const global Lua table which can be used similarly to C++ enum. And what's cool is that it has the same values as corresponding C++ enum! So I can do something like this and this will still work:

enum class SomeEnum {
     SomeValue1 = 1,
     SomeValue2 = 8,
     ... // etc
};

I'll tell the implementation details in some blog post later, there's too much to write about. :)

Event Manager
Let's talk about events.
Previously I had something callbacks like this:

void SomeClass::onHpChange(Event* e) {
    auto event = virtual_cast<HpEvent*>();
    int hp = event->hp;
    ...
}

So, basically I had a base Event class and lots of events which used it as a base class.
The only thing different about them were arguments.

Why virtual_cast? That's because implementing something like this:

void SomeClass::onHpChange(HpEvent* event) {
    int hp = event->hp;
    ...
}

Is much harder, because functions with different argument types have different types, so they can't be stored in the same array, so you have to use lots of template magic to make this work.
Another problem is that Lua/C++ event communication gets harder, because you have to register all those event classes in Lua or write function which create tables based on the event's data.
I also had pretty bad separation between Lua and C++ callbacks, so I created CppEventManager and LuaEventManager. They had lots of common stuff, so I created a base EventManager template class (I had to store different types of callbacks and listener id's). Stuff was very hard to manage.

So, what did I come up with? First of all, I created EventArg class which can hold some common types (int, float, bool, more about it later). Event has a std::map<std::string, EventArgs> args. (key is a name of the argument)

So, I can create events like this now:
Event e(EventType::HpChangedEvent);
e.setData("hp", 10);
eventManager.queueEvent(e);

and callbacks look like this:

void SomeClass::onHpChange(const Event& e) {
     int hp = e.getData<int>("hp");
     ...
}

EventManager can now easily hold both C++ and Lua callbacks, so communication between Lua and C++ is easy. Lua callback can look like this:

function callback(event)
    print("HP:" .. event.data.hp)
end

This works, because events can easily be converted to Lua tables with same data.

I have two things I want to discuss though...

1) EventType enum
This is a big enum of all types of events which is used to differ one type from another. Is this okay to use a enum like this or is there a better way? Creating new classes is not an option as I've shown above.
What makes me worry is that compilation times may become slow, because EventManager.h includes EventType.h, so each time I change EventType enum, EventManager.h is recompiled which may cause lots of additional recompilation, which sucks.

2) EventArg
So, what is EventArg? This is a class with union which can hold int, float or bool.
This is enough for most purposes (you may think that std::string is needed, but it isn't, because you most engines don't use std::string's at all and have string integer ids instead.)
But sometimes this is not enough. Sometimes it's good for event to hold sf::Vector2f or sf::FloatRect.
This will probably work with unrestricted unions, but they're not currently supported in VS2013, so I can't use them. (They're supported in VS2015, anyone tried it?)

So, this is how things work now. What do you think about it?
(When I get some time, I'll write more about stuff I've improved in my code in a big blog post :D)
Title: Re:creation - a top down action adventure about undeads
Post by: JLM on November 11, 2015, 10:51:40 pm
I have a question for you. How do you make objects like Arrows spawn?

Let's say I've got a EntityManager class which contains all of the Entities (Entities are ints).
And Systems (Singletons) which contain all Components (map<Enity id, Component>...).

So how do I allow a Component like PlayerInputController to add new Entity to EntityManager?
I can't just #include EntityManager to System becouse EnityManager #includes all The systems already.

I was wondering how you solved that problem.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on November 12, 2015, 02:30:28 pm
Well, here's how it works in my game.
1) Each item has ItemComponent with a reference to Lua script function called use
2) When the player or AI uses the item, this function is called.

It looks like this:
function use(this, owner) -- this - a pointer to item entity, owner - a pointer to owner entity
    local arrow = createEntity("arrow")
    setPosition(arrow, getPosition(owner))
end

createEntity is a global C++ function which can be called from Lua and it looks like this:
Entity* createEntity(const std::string& name) {
    auto entity = entityManager.create(name);
    return entity;
}

If you don't use scripts, you can use events and send event like "EntityCreateEvent" with a name of entity which needs to be created to the entity manager. (But implementing events is a bit harder, yeah)
Another way is to store a pointer to EntityManager in your system (this is not very good, because of coupling, but this works). You can prevent cyclic dependencies by using forward declarations.

Progress Update coming soon!
I've remade lots of script and engine stuff and this is very cool and will improve my perfomance a lot. More details today or tomorrow!
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on November 22, 2015, 09:48:58 pm
Progress update
Sorry for a huge delay with a progress update, I've been very busy, mostly finishing the refactoring stuff and making new things!. And now I can say that for the most part it's complete.
Here's how much stuff I've changed last month!
(http://i.imgur.com/LtVfLgI.png)
Yep. That's a lot. This includes new stuff I've made this month, so maybe I wrote lots of negative code.
This was the biggest refactoring and engine improvement I've done ever. I'm very glad I did this, because now I can make stuff faster, easier and there'll be a lot less bugs in the future. Some people prefer to create workarounds for the problems they have, but if I did this, the game would be buggy, the engine would be a pain to work with and my creativity would be very limited by the stuff I coudn't implement because of the engine structure. So, I'm satisfied with most of the stuff I've remade and now I'm working on the game itself most of the time.

What about the game?
Here's a gif to get you interested. Not much have changed, but here you can see, that I've created bigger rooms for buildings, made scrolling a lot smoother etc.. The talking animation also stops when the character finishes the part he's talking.
(http://i.imgur.com/Diuvc9A.gif)

This post will give a brief overview about what I've done and I'll write a more detailed post later.

Separating drawing, input, event handling
This started when I tried to implement fixed time step. I've realized, that in my game input, drawing and other stuff wasn't separated well enough, so implementing fixed time step wasn't really possible. "SFML Game Development" book gave me some awesome ideas about this and stack of game states, so I did it mostly as described there. This also helped me get rid of lots of global variables. For example, window was a global variable, but now I can pass it in draw function as an argument from the main loop. The main loop looks like this now:
void Game::mainLoop() {
    sf::Time delta = mainClock.restart();
    timeSinceLastUpdate += delta;
    while (timeSinceLastUpdate > TimePerFrame) {
        timeSinceLastUpdate -= TimePerFrame;
        processEvents();
        update(TimePerFrame);
    }
    draw(window);
}
This is as simple as it can get and it feels great. :D
Using stack of GameStates helped me fix some bugs and improve code readability a lot.

EventManager
I've talked about this one before, but let's look at it again. Now I can send events like this:
Event event("HpChangedEvent");
event.setData("hp", healthComponent->getHp());
eventManager.queueEvent(event);

Subscribing to events looks like this:
eventManager.addListener(this, "HpChangedEvent", &GUIPlayingState::onHpChanged);
In this example, GUIPlayingState wants to know when player's hp changed, but other entities can send this event too, so GUIPlayingState can subscribe to the player entity only:
eventManager.addSubjectToListener(this, "HpChangedEvent", playerEntity);

Now, when the HpChangedEvent is triggered, onHpChanged callback is called by EventManager. It looks like this:
void GUIPlayingState::onHpChanged(const Event& event) {
    playerHp = event.getData<int>("hp");
    ... // update GUI!
}
I can also send events from Lua scripts!
event = {}
event.hp = entity:getHp()
event.type = "HpChangedEvent"
queueEvent(event)
Event Lua table is converted to C++ event and then is queued in EventManager. The most cool part is that no matter what sends the event, Lua or C++, both Lua and C++ listeners' callbacks will be called! When the Lua callback is called, I can do stuff like this:
someLuaCallback = function(event)
    print("Hp changed to " .. event.data.hp)
end
I previously used EventType enum for event types, but I now use string hash ids, so I don't have to recompile a lot of stuff when I add a new event. But this raises another question: what if I mistype something? Like this:
Event event("HpChangeEvent"); // should be HpChangedEvent
No problem, I will check the string hash and if it wasn't registered before (all event types are registered during EventManager initialization) nice little assert will tell me about this (crashing my game which is good, because I'd have to fix the error immediately!). (I would love to have some static_assert for checking this, but is this even possible?)

Event class is not a base class for all event types and it's great. It looks like this:
class Event {
    ...
    std::map<std::string, EventArg> args;
}

What is EventArg? It's a cool class which has an unrestricted union which may contain everything that I need for events: bool, int, float, string, etc. I can easily cast it to the needed type like this:
auto someInt = eventArg.cast<int>();

args map is easily converted to Lua table and vice versa, which is what makes using events easy with Lua. I'm very satisfied with the event system now.

C++11/14 stuff
C++11 makes your code much better. Back when I started making Re:creation, some C++11 features were not known to me or the Visual Studio version I was using didn't support these features. Now I've moved to VS2015 and now most of the cool stuff is available to me. Let's talk about the stuff which is available for most people first:

* Pointers
Mostly I was using shared_ptrs everywhere, but then I've realized that I was thinking about smart pointers wrong. Using raw pointers is okay as long as they are non-owning! So, it's better to pass a raw pointer to a function which does something with this pointer, than to pass unique/shared_ptr. So, I do it like this:
void someFunc(SomeClass* ptr) {...}
...
std::unique_ptr<SomeClass> ptr;
...
someFunc(ptr.get());

And using unique_ptr is better than using shared_ptr most of the time. And it's best to not use pointers at all, so I tried to reduce the number of pointers to minimum and use unique_ptr where it's needed.
There were some problems with forward declaration, though. This will produce an error:
// A.h
...
class B;
class A {
     ...
     std::unique_ptr<B> ptr;
};
Why? That's because the compiler creates default destructor in the A.h and B is not available yet, so the compiler tells you that it can't know how to delete B!
Here's an easy way to fix this:
// A.h
...
class B;
class A {
public:
     ~A();
private:
     ...
     std::unique_ptr<B> ptr;
};

// A.cpp
#include "B.h"
A::~A() = default;
...
Good! But this creates another problem when you need move ctor/operator=.
Defining a constructor will prevent move ctor/operator from generation, so you have to declare them for yourself. You can use =default for them, but VS2013 can't do that (but VS2015 can!)

* auto
There's no need to explain how cool auto is. It helped me refactor stuff a lot, because I was using it a lot before, so I didn't have to manually replace a lot of code.

* for-ranged loop
Instead of writing stuff like this:
for(auto it = someStuff.begin(); it != som
eStuff.end(); ++it) {
    auto& something = *it;
    ...
}
I can now write this:
for(auto& something : someStuff) {
    ...
}
Saves a lot of typing and this is easier to write. Now I wish that stuff like this was possible (it will be possible in C++17, most likely!):
for({someKey, someValue} : someMap) { ... }

* STL algoritms + lambdas
I didn't use algorithms much before, because writing functions and then passing them to another function wasn't fast. Lambdas make it a lot better. Suppose you have to find something which matches some condition. You can do it like this:
auto foundIt = someVector.end();
for(auto it = someVector.begin(); it != someVector.end(); ++it) {
     auto& elem = *it;
     if(.../*condition*/) {
          foundIt = it;
     }
}

Or like this:
auto it = std::find_if(someVector.begin(), someVector.end(), [](const SomeClass& elem) { return ...; /*condition*/ });
This is especially awesome when you need to erase something. Previously I had to do it like this:
auto it = someVector.begin();
while(it != someVector.end()) {
     if(... /*condition*/) {
         it = someVector.erase(it);
    } else {
        ++it;
    }
}
 
You can't just do it in for loop, because erasing something will invalidate some iterators.
But now I can do it like this!
std::erase(std::remove_if(someVector.begin(), someVector.end(),
     [](const SomeClass& elem) { return ...; /*condition*/}), someVector.end());
Much better.

One more thing, when you stuff with maps or vectors which store objects with long class names, lambdas can be pretty painful to write, because you have to do stuff like this:
[](const std::pair<KeyClass, ValueClass>& elem) { ... }
Generic lambdas (supported in VS2015 now!) make it a lot easier:
[](const auto& elem) { ...}
Awesome. If you can't use generic lambdas, the best thing I can come up with is this:
[](const decltype(someMap)::value_type& elem) { ... }
Not pretty, but works.
// end of C++11/14 stuff

Const correctness
Not too much to write about this, but I've improved const correctness a lot and this helped me fix a bunch of subtle bugs and will probably save me a lot in the future!

What, there's more?
Yeah, I have lots of stuff to write about (mostly about Lua). Lua enums, new cool LuaScriptManager, removing header dependencies (a.k.a. how LuaBridge caused compiler to recompile everything all the time), improving scripts and more! Stay tuned.

I would love to hear your thought about the stuff I've done and the stuff which you do to improve the quality of your code.
Title: Re:creation - a top down action adventure about undeads
Post by: Ungod on November 26, 2015, 10:20:01 pm
I'm following your project for some time now and i finally manged to register here. Your game and engine were a nice source of inspiration for me.

I really like your modding philosophy and your lua-scripting and editor tools related to that. Until now, I just hardcoded stuff, but I tried scripting in the past a few times. (I can remember that I tried lua for an afternoon, but I had some problems with the setup)

I think you have to consider carefully when using scripts, because they can really slow down the game if used for too basic procedures. Where do you use them? Just everytime you want to implement gameplay behavior, thats unique to certain object and will not occur regular in the game?
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on November 26, 2015, 10:35:18 pm
Ungod, thanks a lot! Glad you find my articles/dev logs useful! :)

Yes, you have to use scripts for stuff that isn't computationally expensive and doesn't happen very often. For example, collision checking and resolution should be done in C++. But reaction to collision may be scripted, because collisions don't happen all the time and you're pretty safe. There are two things that should take most of the time if you're doing stuff right: collision, AI and rendering. Rendering and collision is done in C++. Some of the AI should be done in C++ (finding the shortest path, A*, etc.) and some can be scripted (going from one AI state to another, deciding what to do next, etc.). I don't optimize my script usage for now and I didn't notice any perfomance problems with Lua.

Progress update
Today I've tried to see how the prison/dungeon would look like if drawn in the new perspective. And the results are pretty cool. I'll show them when I implement them in the game! (It's mostly a sketch now)

And today's Pixel Dailies (https://twitter.com/Pixel_Dailies) theme is Bard, so I've drawn Undead Bard who is a cool character which you see from time to time on screenshots :)
(http://i.imgur.com/wrjbCbE.png)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on November 28, 2015, 11:49:10 am
I created pretty cool shadow system
(http://i.imgur.com/g7rRMWm.png)

Previously shadows were drawn by hand, but I realized that this is pretty boring to do, so I created a simple shadow system. Here's how it works:

(http://i.imgur.com/ZiNro6P.png)
First, I apply a simple fragment shader to the object's silhouette.
Here it is:
uniform sampler2D texture;

void main()
{
    float alpha = texture2D(texture, gl_TexCoord[0].xy).a;
    if(alpha < 0.1) {
        discard;
    }
    vec4 color = vec4(0.098, 0.098, 0.098, 0.5);
    gl_FragColor = color;      
}
 
So, I just set all non-transparent pixels to one color.
(http://i.imgur.com/GegiKPJ.png)
Then I skew the silhouette using sf::VertexArray (this is done by simply moving two top verticles (marked as 0 and 1)  like this:
(https://i.imgur.com/WPhqio0.png)

and then I draw the original sprite on top of the shadow. That's it! I still don't know how much I have to skew each shadow to get the best looking shadows (anyone has ideas?). Maybe there are ways to make this even cooler? (I don't want to make anything complex, there won't be "true" lightning system in my game, no directed lights, etc.)

Another aspect of shadows is interaction with other objects and I'll write about it when I implement it (basically it's per-pixel collision test with shadow and object's collision rect)
Title: Re:creation - a top down action adventure about undeads
Post by: shadowmouse on November 28, 2015, 12:22:46 pm
How about making a day and night system and having the shadows gradually move from left to right? I think you'll have to rotate the top edge a bit to stop it looking weird though, but I might be wrong as I've never tried it myself.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on November 28, 2015, 12:28:02 pm
How about making a day and night system and having the shadows gradually move from left to right? I think you'll have to rotate the top edge a bit to stop it looking weird though, but I might be wrong as I've never tried it myself.
Yeah, I thought about that, changing a pallete a bit by using different shaders would also work pretty good with this (changing brightness + hue). I think that I may make day/night system where day and night wouldn't change gradually, but during some events (you go inside the dungeon, it's day outside, you go out - night already!) :D
Title: Re:creation - a top down action adventure about undeads
Post by: lezebulon on November 28, 2015, 02:06:34 pm
Hi!
from experience, when you do shadows this way you really cannot skew them that much without it looking really bad
the reason is simply that the shadow should be the projection of the outline of the 3D object, and with a 2D sprite you only know the outline of the object when you see it from the camera point of view.

This can work fine in any direction as long as the original 3D object has a circulat symmetry (like a pine tree), where the outline from all angles is the same. But basically if you want the shadow to be drawn on the upper-right of the object, the shape of the shadow should be the outline of the object seen from the lower-left... there is no way to tell what it should be just based on the sprite since it's just a view of the object from the top
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on November 28, 2015, 09:19:30 pm
Hi! That's a valid concern, but I'll try not to skew them too much. Most of the shadow is overlapped by the object itself, shadows are low-res/not to big, so I don't think that this will be too obvious if you don't try to think about it. Even if I drew shadows myself, I wouldn't be able to imagine how the other side of the object would look! But if some objects (especially bigger once) have really bad shadows, I can still draw them by hand to make them look better.

So, I'm okay with not perfect shadows :)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on November 29, 2015, 08:54:57 am
Okay, it's time to write another part about the refactoring I've done. It's also contains the hardest part of the refactoring!
Here's some small stuff I've done:

1. Lua enums. I've written about those already (http://en.sfml-dev.org/forums/index.php?topic=18062.msg139016#msg139016). They work pretty good
2. LuaEntityHandle. Read more about this technique here (https://eliasdaler.wordpress.com/2013/11/30/lua_and_cpp_pt3/).
This thing allows me to write stuff like this:
entity:setAnimation("walk")
instead of
setAnimation(this, talk)
A minor change, but the one I like very much, because it makes scripts easier to read
3. Lua/C++ events. Written about it here (http://en.sfml-dev.org/forums/index.php?topic=18062.msg139773#msg139773).
4. And now for the hardest part. I didn't really think too much about header dependencies because I try to not include stuff in headers, use forward declaration as possible, try to decouple classes, etc. But changes in some classes caused lots of recompile for no reason. You now, like file changing A.h caused B.cpp which didn't include A.h in any way to recompile. I've searched for hours for the root of the problem. I've created a big graph of includes in my code but found no reason for this thing. And here comes the worst part: when I created new functions and registered them in LuaBridge, this caused almost full recompilation of the whole project (which took 4-5 minutes!). This was not acceptable. This would limit me a lot, because I wouldn't want to add C++ functions which can be called for Lua or change some classes which caused a lot.

And then I found it. It was LuaBridge.h. I created a quick project to test things out. So, suppose you have two classes A and B which are not related in any way. You register A class in A.cpp and do some stuff with LuaBridge in B.cpp. So, A.cpp and B.cpp have LuaBridge.h included in them. And now suppose you make some changes in class A and compile. B.cpp compiles too! What? This is what LuaBridge does. I think that compiler generates some weird template code again which causes LuaBridge.h to recompile causing ALL files which include LuaBridge.h to recompile.

As you may imagine, lots of files in my project included LuaBridge.h. This is what caused the problem! And I've found the solution. It was to make LuaScriptManager which included LuaBridge.h in LuaScriptManager.cpp but not in LuaScriptManager.h, so if you change some stuff and LuaBridge.h needs to recompile, only LuaScriptManager.cpp is recompiles, but all the files which use LuaScriptManager.h are not recompiled!
But making good interface for LuaScriptManager was a big challenge. There were two problems:

Problem A. I needed to make some templated functions which used LuaRef in them (like T getData<T>). This meant that I needed to include LuaBridge.h in LuaScriptManager.h which would cause the same problems again!

Here's how I solved it:
You can declare a template function in .h but define it in C++ if you do template specialization. But this proved to be bad, because a lot of the code had mostly common stuff in it and I didn't want to just copy-paste stuff. And then I've found out about one of the coolest template features ever. It's called explicit template instantiation. So, all you have to do is to define the template function in .cpp and then put explicit instantiations in .cpp for all the types you want this function to use with. This limits you to only those types, but I was okay with that, because getData was used with only a number of classes like int, float, bool, etc.
So, here's how the code looks:
// LuaScriptManager.h
class LuaScriptManager {
    ...
    template <typename T>
    T getData<T>(...);
    ...
};

// LuaScriptManager.cpp
...
template <typename T>
T LuaScriptManager::getData<T>(...) {
    // template code
}

// explicit instantiations
template bool LuaScriptManager<bool> getData(...);
template int LuaScriptManager<int> getData(...);
... // etc.
So, this causes compiler to generate all this functions in .cpp file, so you don't have to have template function definition in your .h file which enables you to not put code into headers.

Problem B. I needed to find some wrapper around LuaRef which could act like LuaRef, but didn't require files where it's used to include LuaBridge.h. This one was easy, I just created class like this:
namespace luabridge {
    class LuaRef;
} // forward declaration

class LuaRefWrapper {
    template <class T>
    T cast() const;
    ...
    std::unique_ptr<luabridge::LuaRef> refPtr;
};
This also allowed me to get rid of some explicit template instantiations in LuaScriptManager which made code a lot better. I can just use LuaRefWrapper.h in LuaScriptManager.h without including LuaBridge.h! So, I got rid of the dependency, but I also got a few good things out of LuaScriptManager too, of course.

1) Hiding stuff/error checking inside the scripts
Suppose I have entity definition that looks like this:
someEntity = {
    ...,
    GraphicsComponent = {
        filename = "res/images/someEntity.png",
        ...
    }
}
Suppose I want to get someEntity.CollisionComponent.collide. Here's what I had to do previously:
auto entityTable = luabridge::getGlobal(L, "someEntity");
auto componentTable = entityTable["GraphicsComponent"];
auto filenameRef = componentTable["filename"];
std::string filename;
if(filenameRef.isString()) {
    filename = filenameRef.cast<std::string>();
} else {
    filename = "res/images/error.png";
}
There are lots of things that can go wrong. What if one of the tables is not found? Should add checks for this too?
Here's what I can do now:
auto componentTable = scriptManager.getTable("someEntity.GraphicsComponent");
auto filename = scriptManager.getData<std::string>("filename", "res/images/error.png", componentTable);
Much better! If one of the tables is not found, the program doesn't crash and LuaScriptManager tells me about the error. If the value is of the wrong type, the script manager tells me about this too. If there are some errors, getData returns the default value which I provided as the second argument.

2) Overwrite
One functionality I've implemented a long ago was entity "inheritance". Suppose I have one entity with lots of components. And now I decide to create almost the same entity, but with another sprite. Here's how I can do that:
base_entity = {
    ...
}

derived_entity = {
    template_init = function(this)
        this:copyEntity("base_entity") // copies everything from base_entity
    end,
    GraphicsComponent = {
        filename = "res/images/newSprite.png"
    }
}
The difference between default loading and this type of loading is that I don't care if the value is not found in derived entity. If this is a case, I just don't change the value. If the value is found, I replace it with a new one. And here's what I had to do previously:
auto entityTable = luabridge::getGlobal(L, "someEntity");
auto componentTable = entityTable["GraphicsComponent"];
auto filenameRef = componentTable["filename"];
if(!filenameRef.isNil()) {
    filename = filenameRef.cast<std::string>();
}
Notice how it's almost the same as the previous example. Can I implement it better with new scriptManager? Sure
auto componentTable = scriptManager.getTable("someEntity.GraphicsComponent");
auto filenameRef = scriptManager.getRef("filename", componentTable);
if(filenameRef.isNil()) {
    filename = filenameRef.cast<std::string>();
}
This almost looks like LuaBridge code above! So I came up with a better solution, now I can do stuff like this:
scriptManager.getData(filename, "res/images/error.png", "filename", componentTable, isOverwrite);
Here's what's going on. Fist of all, notice that I don't have to specify template argument because of the type deduction which happens because I pass the first argument.
If isOverwrite == false, this works as getData<std::string> that I showed above. If isOverwrite == true, then I rewrite the value only if it's found. But I don't write about errors that some tables or values are not wrong, because some values may be missing in derived entities and that's fine.
So, this one line works for two cases: loading value expecting to find it and trying to overwrite value only if the value is found.

So, all this stuff lead me to great simplification of script loading code, allowed me not to worry about the errors in scripts and reduced a lot of header dependencies. This also allows me to replace LuaBridge with some other library in the future only by changing LuaScriptManager and not bothering about other code which is very good.

I'm very glad I did this epic refactoring/engine improvement. Now I'm a lot more confident in the engine and I'm already making some progress about the game. :)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on November 30, 2015, 10:31:39 pm
Today I've integrated new shadow system in the game (previously I used it in a test project). Here's how it looks!
(http://i.imgur.com/DOlQtfI.gif)
Notice, that I don't draw shadows when I turn on the fog.

There's a lot of stuff to improve, of course. Here's one of such improvements:
(http://i.imgur.com/Uzc5ft4.png)
The shadow on the left doesn't look as it should because the dirt/grass and tombstone were one sprite, so shadow system used all that sprite to create a shadow. But if I separate them and tell the system to generate a shadow only from the tombstone, it all becomes much better! (The shadow must be smaller though, but it's easy to change!)

Here's another screenshot for fun. There are still lots of things I have to make better (like don't skew shadows very much in some objects and there's other stuff) but I'm very satisfied with the result. The game looks more alive now!
(http://i.imgur.com/3RqbSBc.png)
Title: Re:creation - a top down action adventure about undeads
Post by: Hapax on November 30, 2015, 11:39:58 pm
This is looking better and better every time. Good work!

Notice, that I don't draw shadows when I turn on the fog.
The absence of the 'dynamic' shadows makes the presence of the hand-animated shadows look odd (at the bottom of the lamps).
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 01, 2015, 06:10:52 am
Thanks a lot!

Oh, I completely forgot about those. They are drawn directly with the sprite itself, I guess I have to separate them  and draw shadow and torch sprites separately :D
Or I can use a shader which will remove "shadow" pixels from the texture (this is even easier, ha-ha!)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 01, 2015, 01:47:47 pm
If you love Re:creation, please vote for it, so maybe it wins Indie of The Year indiedb award!  ;D
Vote now! (http://www.indiedb.com/games/recreation)
Do it, so you can spend more time talking with this cat in the future
(http://i.imgur.com/EF18sUv.png)
Title: Re:creation - a top down action adventure about undeads
Post by: Jesper Juhl on December 01, 2015, 06:21:29 pm
Voted. You and your awesome game deserve it :-)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 01, 2015, 06:34:25 pm
Thanks a lot, Jesper!  ;D
Title: Re:creation - a top down action adventure about undeads
Post by: shadowmouse on December 01, 2015, 07:01:12 pm
Same. I think I'm possibly anticipating this more than any professionally made game at the moment.
Title: Re:creation - a top down action adventure about undeads
Post by: Mortal on December 01, 2015, 07:03:48 pm
Voted, here  ;)
Title: Re:creation - a top down action adventure about undeads
Post by: Jesper Juhl on December 01, 2015, 07:13:27 pm
I think I'm possibly anticipating this more than any professionally made game at the moment.
I know what you mean. All the cool screenshots, details about implementation, etc etc, has built up a huge amount of suspense.
I want to play this now! ;-) (for Linux, please).
Title: Re:creation - a top down action adventure about undeads
Post by: SpeCter on December 01, 2015, 08:18:20 pm
Voted from work pc and home pc ;D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 01, 2015, 11:00:54 pm
Thanks you very much, everyone! Your support means a lot to me. I'm very glad that you find the game and the dev process interesting. Sometimes I have doubts about my skills, but hearing such kind words makes me confident and motivated to work more and more. :)

Jesper Juhl, Linux demo is totally coming when Windows version will be out. Though, I haven't compiled on Linux since March... hope most of the code works and there'll be no need to fix a lot of stuff. :D

(Btw, I'm working on wall shadows, they're pretty tricky to make)
(https://pbs.twimg.com/media/CVK7kgSVAAEsfqb.jpg)
Title: Re:creation - a top down action adventure about undeads
Post by: Jesper Juhl on December 02, 2015, 04:36:54 pm
Jesper Juhl, Linux demo is totally coming when Windows version will be out. Though, I haven't compiled on Linux since March... hope most of the code works and there'll be no need to fix a lot of stuff. :D
Why don't you set up a CI system like Jenkins or BuildBot to build every commit on all of your target platforms and then run your tests?

That way you'll instantly know if you caused a target to fail to build or a test to fail and you'll also know which exact commit broke it.

And you can use both physical machines and virtual ones (or a mix) as your build slaves.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 02, 2015, 06:31:56 pm
Yeah, I really need to do it some day. Any good articles about setting it all up? :D
Title: Re:creation - a top down action adventure about undeads
Post by: Jesper Juhl on December 02, 2015, 06:50:00 pm
Not really. But I've set up both BuildBot and Jenkins a few times, both at home and at a couple of employers - just using the official docs. It's really not that hard.  Set aside a day and read up on it in the morning and set it up in the afternoon. By evening you'll have a working setup and it'll be a day well spent going forward :-)

And your second step (when you have another day to burn) should then be to get your CI system to generate installation packages every night for all your target platforms. So that every morning you'll have a fresh set of MSI's, RPM's, DEB's, etc etc, ready to deploy to your customers.
And if you don't already have the generation of such packages/installers automated; well, pull out one more day from the calender and do that. That's also a day well spent (IMHO) - you really don't want to constantly have to do that crap by hand - a computer can do it better (every night).
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 03, 2015, 08:40:16 am
Thanks for advice. I'll try something out very soon. :D

By the way, can someone give me advice about how to make this stuff better?
So, I load components from scripts like this:
void AIComponent::loadFromScript(const std::string& entityName, const LuaRefWrapper& componentTable,
    bool overwrite)
{
    scriptManager.getData(viewSize, "viewSize", componentTable, overwrite);
    scriptManager.getData(type, "type", componentTable, overwrite);
    ...
}
So, the first argument is the variable in which the value from the script is written. The second argument is the name of the value in the script, the third argument is the component table in the script and the fourth argument is the script manager mode (doesn't really matter that much, it's just a bool).

So, for example I have something like this in the script:
enemy = {
    AIComponent = {
        type = "chaser",
        ...
    }
}
So, the componentTable is enemy.AIComponent

As you can see, always passing the third and the fourth argument is getting pretty annoying. Is the some good way to make this code better? Something like this:
void AIComponent::loadFromScript(const std::string& entityName, const LuaRefWrapper& componentTable,
    bool overwrite)
{
    ... // temporally set componentTable and overwrite mode in ScriptManager
    scriptManager.getData(viewSize, "viewSize");
    scriptManager.getData(type, "type");
    ... // automatically unset this, so the next time I use scriptManager, it works as usual
}
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 03, 2015, 10:04:43 am
Why not just make a simple wrapper?

void AIComponent::loadFromScript(const std::string& entityName, const LuaRefWrapper& componentTable,
    bool overwrite)
{
    ScriptDataLoader loader(scriptManager, componentTable, overwrite);
    loader.get(viewSize, "viewSize");
    loader.get(type, "type");
}
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 03, 2015, 01:50:11 pm
Why not just make a simple wrapper?

void AIComponent::loadFromScript(const std::string& entityName, const LuaRefWrapper& componentTable,
    bool overwrite)
{
    ScriptDataLoader loader(scriptManager, componentTable, overwrite);
    loader.get(viewSize, "viewSize");
    loader.get(type, "type");
}
Yeah, that's a good idea, thanks! Would make the code so much cleaner and easier to write. :D
(Btw, I was wondering, what is the name of this pattern? It kinda looks familiar)
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 03, 2015, 02:41:33 pm
I don't know if it's a known pattern ; maybe an adapter? Anyway, to me it's just "putting redundant stuff into a common place" ;)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 03, 2015, 02:53:49 pm
I don't know if it's a known pattern ; maybe an adapter? Anyway, to me it's just "putting redundant stuff into a common place" ;)
Yeah, looks like it. I did it, btw. Looks so much better!

(http://i.imgur.com/pZlKYhE.png)

I kinda want to write a macro like this:
#define GET_SCRIPT_DATA(loader, x) loader.get(x, #x)
so I could do this:
GET_SCRIPT_DATA(loader, chargeAnimationName);
// expands to loader.get(chargeAnimationName, "chargeAnimationName");
But that may be too extreme and silly. :D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 05, 2015, 10:14:21 pm
(http://i.imgur.com/hXo02P5.png)
QtCreator + CMake + GCC 5.2.1 + Xubuntu VM. Works pretty well, as you can see. Still have to fix some stuff, but I didn't have to change much to compile/run my game on Linux which is a very good sign! :D
The biggest fails were because of differences in newline characters. "\n" vs "\r\n". Any good way to deal with them? Remove them after each getline? Any other ways? :D
Title: Re:creation - a top down action adventure about undeads
Post by: dabbertorres on December 05, 2015, 11:54:14 pm
I just always use '\n'. Everything I've used except Notepad (which no one in their right mind uses for programming) parses it just fine.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 06, 2015, 08:06:27 am
I just always use '\n'. Everything I've used except Notepad (which no one in their right mind uses for programming) parses it just fine.
So, should I change line endings to Linux-style in every editor I use? :D
Btw, strangely enough:
getline(file, line); // this line is "SCRIPTS_BEGIN" in file
if(line == "SCRIPTS_BEGIN") { // true on Windows, false on Linux!
    ...
}
So I need to remove \r\n or just \n to get the expected results. This is because I read files with windows endings on Linux. Is there a better solution to the problem?

Question to those, who use CMake with large projects: do you use glob or do you specify source files by hand? I have 135 .cpp files and lots of sub-directories, so I'm afraid that specifying them by hand would take a long, but is it worth it?
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 06, 2015, 01:36:46 pm
If you don't open files with the std::ios::binary flag, newlines should be treated correctly by the stream, independantly of the platform.

I never use glob with CMake. Since I never add 150 files at once to the project, this is not really a problem ;)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 06, 2015, 02:34:15 pm
If you don't open files with the std::ios::binary flag, newlines should be treated correctly by the stream, independantly of the platform.
The problem is that I open files (which were created in Windows) in Linux, so getline produces different results on Windows and Linux. I'd probably write a function which will just remove line endings from strings. :D

I never use glob with CMake. Since I never add 150 files at once to the project, this is not really a problem ;)
Maybe I should devote some hours to it and just do it. :D
Btw, what is the correct way to manage subfolders? I know that I must add CMakeLists to each subfolder, but what should those files contain? I see that SFML sets SRC variable, but does it actually append to SRC? Can I use this method to do this in the main CMakeLists?
add_executable(game ${SRC})
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 06, 2015, 03:07:34 pm
You don't need to create CMakeLists.txt files in every sub-folder. If they just contain source files and headers, you can reference them from the main CMakeLists.txt with their relative path.
Title: Re:creation - a top down action adventure about undeads
Post by: shadowmouse on December 06, 2015, 03:53:39 pm
Just out of interest, why do you have so many files? How much do you put in each? That might well be the reason for your compile time taking minutes unlike the usual few seconds.
Title: Re:creation - a top down action adventure about undeads
Post by: Jesper Juhl on December 06, 2015, 04:12:05 pm
Just out of interest, why do you have so many files? How much do you put in each? That might well be the reason for your compile time taking minutes unlike the usual few seconds.
I would expect to opposite.
With many individual files the amount of code that needs to be recompiled when you change something is likely to be less than if you had a few monster files that are all impacted by every little change.

My personal rule of thumb is one class per .h/.cc file.
Title: Re:creation - a top down action adventure about undeads
Post by: shadowmouse on December 06, 2015, 04:21:31 pm
That's my rule as well (except with .hpp and .cpp), I just thought that once you had split stuff up that much, the shear amount of files that would have to be compiled, especially if a header file was changed could be what's taking ages. I just remember Elias saying something about it taking at least 2 minutes to compile, which is weird because in my experience things take 15 seconds tops, usually closer to 2 seconds to compile unless you're doing a full rebuild.
Title: Re:creation - a top down action adventure about undeads
Post by: Nexus on December 06, 2015, 04:43:19 pm
With many individual files the amount of code that needs to be recompiled when you change something is likely to be less than if you had a few monster files that are all impacted by every little change.
This is definitely true, and a good reason to keep dependencies between different modules low, for example by:
However, having many files comes with the problem that often-used external code in headers (from standard and other libraries) must be included in many more files, and recompiled again and again in each of them.

The effect of this depends strongly on the compilers' capabilities to cache code that doesn't change (which is not always trivial, since single declarations or macros can change the behavior of everything that follows). Good compiler toolchains therefore offer an explicit option to precompile headers. Furthermore, with the number of files increasing, the effort for the linker increases as well, thus the linking step may take longer.
Title: Re:creation - a top down action adventure about undeads
Post by: Jesper Juhl on December 06, 2015, 04:51:55 pm
@Nexus : What you say is true of course. And one should always try to only include what one uses and no more and always use forward declarations where possible etc. On top of that I'd recommend using ccache (https://ccache.samba.org/). It can really speed up your recompiles when most files can just be taken from the cache rather than re-running the compiler.
Ohh and using a fast compiler like clang (http://clang.llvm.org/) can also help a lot.
Title: Re:creation - a top down action adventure about undeads
Post by: Jesper Juhl on December 06, 2015, 09:10:17 pm
I just remember Elias saying something about it taking at least 2 minutes to compile, which is weird because in my experience things take 15 seconds tops, usually closer to 2 seconds to compile unless you're doing a full rebuild.
That very much depends on the size and complexity of the code you are working on.
Sure, for many personal hobby projects sub-minute build times are probably the norm. But projects grow...
The code base I work on at work is ~60000 files and takes about 30min to rebuild from scratch on a modern 8core machine. With ccache it can then usually be re-built in a few minutes (0.5-3.0) if you only make small local changes..
Also, have you tried building something like Qt5 from scratch? On my (8core) laptop it takes >4hrs.
Title: Re:creation - a top down action adventure about undeads
Post by: shadowmouse on December 06, 2015, 09:20:14 pm
No I'll be honest I haven't tried stuff like that. I was merely guessing at the amount of code that goes into something like this because it's similar to an unfinished old project of mine which I used to be able to compile in 10 seconds.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 06, 2015, 10:53:24 pm
You don't need to create CMakeLists.txt files in every sub-folder. If they just contain source files and headers, you can reference them from the main CMakeLists.txt with their relative path.
Yeah, but why do most people put them in every sub-folder anyway? Even SFML does it! :D

Just out of interest, why do you have so many files? How much do you put in each? That might well be the reason for your compile time taking minutes unlike the usual few seconds.
I have so many files, because I have lots of code! ~16k lines of code in .cpp and most of the files are 100-200 lines long. Most of the time compilation is pretty fast. Compilation times are bigger when I change some base files like Entity.h or Component.h. But mostly, they're pretty okay. I forward-declare as much as possible and  ECS makes me not make large inheritance trees, so dependencies are minimal.
And btw, my laptop is not very good, so this adds to compilation time. Full recompilation takes around 4-6 minutes.

The biggest problems with compilation times were caused by LuaBridge, but I've already fixed that :)
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 06, 2015, 10:59:21 pm
Quote
Yeah, but why do most people put them in every sub-folder anyway? Even SFML does it!
There's a CMakeLists.txt file where there is a new binary to configure. There are plenty of sub-folders in SFML that don't have this file, because they exist only to organize source code (the whole headers hierarchy, or the various platform folders in System and Window, for example).
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 06, 2015, 11:03:56 pm
There's a CMakeLists.txt file where there is a new binary to configure. There are plenty of sub-folders in SFML that don't have this file, because they exist only to organize source code (the whole headers hierarchy, or the various platform folders in System and Window, for example).
Oh, okay, this makes sense. Hmm, seems like using GLOB doesn't change anything in my case (except that I need to run CMake each time I add/remove file) :D
Title: Re:creation - a top down action adventure about undeads
Post by: Nexus on December 07, 2015, 08:54:59 am
The biggest problems with compilation times were caused by LuaBridge, but I've already fixed that :)
May I ask how you did that? :)
Title: Re:creation - a top down action adventure about undeads
Post by: eXpl0it3r on December 07, 2015, 09:00:59 am


May I ask how you did that? :)
See here: http://en.sfml-dev.org/forums/index.php?topic=18062.msg139957.msg#139957
Title: Re:creation - a top down action adventure about undeads
Post by: Jabberwocky on December 09, 2015, 01:42:18 am
Voted!
Looking great, Elias.  :)

This is definitely true, and a good reason to keep dependencies between different modules low, for example by:
  • Having classes with small APIs and let each reference only a few "neighbors" that logically relate
  • Avoiding central manager- and singleton-style classes used everywhere
  • Using forward declarations or even the PImpl idiom where appropriate
  • Including only the necessary specific headers and no mass includes like <SFML/Graphics.hpp>

All good suggestions, except for the singleton-style critique.  There's nothing inherent about a singleton that makes it any better or worse than a non-singleton for dependencies.  Sure, you can design a singleton poorly, but you can design a non-singleton poorly as well.

Singleton talk is one of those "holy war" type coder conversations.  If anyone wants to debate them further (as if everything hasn't already been debated 1000x over ;)) I'd suggest we start a new thread on it.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 09, 2015, 01:04:25 pm
Thanks, Jabberwocky!

Yeah, let's not discuss singletones. :)
Here's a thing I want to discuss: Manager classes.
There are some useful managers in my game: ResourceManager, LogManager, LuaScriptManager, etc.

I store pointers to them in a global structure named engine_system.
struct EngineSystem {
     LogManager* log;
     ... // etc.
}
To write something in log, I need to do it like this:
engine_system.log->write("Something happened");
This allows me to do some cool stuff, like making FileLogManager and ConsoleLogManager and then replace simple LogManager with FileLogManager which writes to file. Or, I can create NullLog which will ignore all the messages.
This is a Service Locator pattern. So, here are the things I want to discuss

1) How do I make a better interface to this? Maybe I should do something like this?
engine_system.getLog()->write(...);
Or maybe there are better alternatives?

2) Avoiding usage of global engine_system.
Sometimes I can pass needed managers to functions, like this:
void handleInput(const InputManager& inputManager);
But sometimes there's no such possibility, because it's hard to predict which managers will be needed (especially hard with virtual functions!)
So, what are your tips on dealing with this?
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 09, 2015, 01:31:32 pm
Quote
How do I make a better interface to this?
In the end it will always be a global access to some variable. So whether it is behind a function, a parent structure, or whatever, won't make much difference. Some will say that using a getter function is more flexible, since you can change the implementation without impacting the API. In real life, I can hardly see what you would change in a function that just returns an object.

Quote
Avoiding usage of global engine_system.
It is a fact that global access to some objects is the best design sometimes. There's no need to try to avoid it at all costs, if it's the best solution for you. What's important is to avoid global lifetimes whenever possible, because this is what causes problems: construction before main() and destruction after main(). But to me, global access is fine for objects that are used everywhere, and not really tied to what a function does (it would be silly to pass a log manager argument to every function that may log something).

A design that I often use is a globally accessible Application class (*), instanciated in main(), and which takes care of construction and destruction of all other "global" objects, as well as giving access to them. This way you avoid lots of global objects scattered all over the code, and you have fine control over order of construction, dependencies between them, etc. And you only have a single true global object to deal with, in case one day you decide that this is not a good design anymore.

(*) in a Qt application it is kind of mandatory anyway, because that's already how Qt works -- and I work with Qt ;D
Title: Re:creation - a top down action adventure about undeads
Post by: Jabberwocky on December 09, 2015, 08:42:03 pm
What's important is to avoid global lifetimes whenever possible, because this is what causes problems: construction before main() and destruction after main(). But to me, global access is fine for objects that are used everywhere, and not really tied to what a function does (it would be silly to pass a log manager argument to every function that may log something)

Good approach, Laurent.
I agree, and bolded what I consider the most important part for emphasis.

Title: Re:creation - a top down action adventure about undeads
Post by: Ricky on December 10, 2015, 01:22:31 am
What Laurent Said

All of this and also I understand where you are coming from Elias. The problem is that sometimes OOP is NOT the best solution to the problem but we have been sort of indoctrinated into this OOP religion where all the problems we have we think we can solve with OOP and UML charts.

I recommend watching this http://www.twitch.tv/handmade_hero/v/28507308 (http://www.twitch.tv/handmade_hero/v/28507308) recent talk at Handmade Con 2015. Very eye opening. Being dogmatic about programming is counter productive. If what you need is a global then do it. I also use a global for logging. I'm also considering a simpler design using a global gCurrActor and gCurrScene and then just have functions that operate on them. This is to simplify the process of Lua binding.

--Edit: Here is a link to the Logger I'm using https://github.com/ricanteja/MoonySpriteBatch/blob/master/include/Log.h (https://github.com/ricanteja/MoonySpriteBatch/blob/master/include/Log.h)
Title: Re:creation - a top down action adventure about undeads
Post by: SeriousITGuy on December 10, 2015, 07:59:02 am
I also use one global data structure which holds (non-owning) pointers to all engine subsystems (which are owned by the main application class), like renderer, audio, logger (even a blackboard for simple data exchange between different game states). In my opinion it is a simple and at the same time elegant solution to this problem. So everthing I do is to pass this global object to all gamestates, and from there every state has access to all engine subsystems.
I think in the book SFML Game Development the same concept is used, and it worked perfectly.
Title: Re:creation - a top down action adventure about undeads
Post by: eXpl0it3r on December 10, 2015, 08:30:40 am
(it would be silly to pass a log manager argument to every function that may log something).
Not according to my prof. :P
We're only allowed to use std::cin/std::cout in the main file and otherwise have to pass around the streams. But it does make sense to some extend, because that way we can easily test all classes and functions.
Then again a log class maybe a slightly different topic. Point being that in general globally accessible objects create side effects which are often nearly impossible to test against. ;)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 10, 2015, 02:21:47 pm
But to me, global access is fine for objects that are used everywhere, and not really tied to what a function does (it would be silly to pass a log manager argument to every function that may log something).
Yep, agreed. Thanks for making me stop doubting this stuff :D

(*) in a Qt application it is kind of mandatory anyway, because that's already how Qt works -- and I work with Qt ;D

Didn't really think about this before, that's a good analogy :D

Ricky, I'm currently watching Handmade Con and it's one of the best stuff to happen ever, haha. Lots of cool stories from awesome guys! :D

SeriousITGuy, yeah I mostly use this approach too (try to avoid using the global engine_system as possible), but sometimes the object is not really connected to game states and still needs to log stuff, that's where global engine_system is useful.

eXpl0it3r, yeah, sometimes it makes sense to pass a stream, but only when you know that this function will write some stuff most of the time. Passing it "just in case" may be poor design in some cases, IMHO.

After all, I think that some managers are almost like free functions which perform stuff without changing lots of stuff. They have their own members sometimes, but they don't change that much, so this is not a big deal. If I had some global stuff which was used everywhere and could change in some places, that would be another problem! :D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 12, 2015, 12:06:25 pm
I'm starting to write a small animation tool for my game in Qt, so I don't have to modify JSON by hand. Why don't I just use JSON editor? That's because I'll add animation preview window soon.

I would like to ask: what's the current status on Qt + SFML? Do they work together? Are there many problems? :D

I would like to have a widget which would render stuff in SFML and I'll use Qt for GUI (possibly I'll create GUI for level editor using Qt if it all works all right, this would save me so much time!)

Progress update
Got some basic stuff working
(http://i.imgur.com/Ks5H7Qt.png)
The coolest thing about it is that it's much more readable than JSON because I can display better variable names. Here's how this animation looks in JSON:

{
    "directions" : null,
    "frame" :
    [
        0,
        64,
        32,
        32
    ],
    "frameTime" : 100,
    "isLooped" : false,
    "name" : "die",
    "numOfFrames" : 13,
    "offset" :
    [
        2,
        -2
    ]
},
 

I think I'll move most of the entity stuff (data) in JSON and use Lua for functions for the rest, so I may create Entity Creation Tool which will work the same way as Animation Tool and if I integrate it with my engine, I'll be able to see how entity would look like as I create it. Isn't it awesome? :D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 13, 2015, 09:00:50 am
(http://i.imgur.com/hz42v6W.png)
It's happening! This is Qt with SFML drawing! :D
Animations are not yet implemented, but as you can see Qt and SFML work very well together! Integrating them was very easy, here's what I did. Feel free to give me some tips on how to make stuff better and tell me your experience with Qt + SFML :D

SFMLWidget.h
#ifndef SFMLWIDGET
#define SFMLWIDGET

#include <QWidget>
#include <SFML/Graphics/RenderWindow.hpp>

class SFMLWidget : public QWidget
{
public:
    SFMLWidget(QWidget* parent = nullptr);

    void processEvents();
    void processInput(int dt);
    void update (int dt);
    void draw();
private:
    QPaintEngine *paintEngine() const;
    void enterEvent(QEvent *) override;
    void paintEvent(QPaintEvent*) override;

    sf::RenderWindow window;
    sf::View view;
};

#endif // SFMLWIDGET
 

SFMLWidget.cpp

#include "sfmlwidget.h"
#include <SFML/Window/Event.hpp>

SFMLWidget::SFMLWidget(QWidget *parent) :
    QWidget(parent),
    view(sf::FloatRect(0.f, 0.f, 128.f, 120.f))
{
    //Setup some states to allow direct rendering into the widget.
    setAttribute(Qt::WA_PaintOnScreen);
    setAttribute(Qt::WA_OpaquePaintEvent);
    setAttribute(Qt::WA_NoSystemBackground);
    setAttribute(Qt::WA_PaintUnclipped);

    //Set strong focus to enable keyboard events to be received.
    setFocusPolicy(Qt::StrongFocus);

    //Under X11, we need to flush the commands sent to the server to ensure that
    //SFML will get an updated view of the windows
#ifdef Q_WS_X11
    XFlush(QX11Info::display());
#endif

    window.create((HWND)winId()); //Create the SFML window with the widget handle
    window.setView(view);
}

QPaintEngine* SFMLWidget::paintEngine() const
{
    //We make the paintEvent function return a null paint engine. This functions works together with
    //the WA_PaintOnScreen flag to tell Qt that we're not using any of its built-in paint engines.
    return nullptr;
}

void SFMLWidget::enterEvent(QEvent *)
{
    setFocus();
}

void SFMLWidget::paintEvent(QPaintEvent *event)
{
    draw();
}

void SFMLWidget::processEvents()
{
    sf::Event event;
    while(window.pollEvent(event)) {
        ... // process events
    }
}

void SFMLWidget::processInput(int dt)
{
    ... // process input
}

void SFMLWidget::update(int dt)
{
    ... // update stuff
}

void SFMLWidget::draw()
{
    window.clear();
    ... // draw
    window.display();
}

And then you can use SFMLWidget as QWidget without any problems!
And now I need to figure out how to do game loop inside this stuff and I'll try to use it with my engine if this works out well :D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 13, 2015, 10:42:17 am
I'm writing a lot today :D
Managed to get a basic loop working.
(http://i.imgur.com/5SjFPaR.gif)

Code:

#include "mainwindow.h"
#include "sfmlwidget.h"

#include <QApplication>
#include <QTime>

int main(int argv, char *args[])
{
    QApplication app(argv, args);
    MainWindow window;
    window.show();

    SFMLWidget* sfmlWidget = window.getSFMLWidget();

    int timeSinceLastUpdate = 0;
    int TimePerFrame = 16;

    QTime mainClock = QTime::currentTime();

    while(window.isVisible()) {
        app.processEvents();

        int delta = mainClock.restart(); // just like in SFML, lol
        timeSinceLastUpdate += delta;

        while (timeSinceLastUpdate > TimePerFrame) {
            timeSinceLastUpdate -= TimePerFrame;
            sfmlWidget->processEvents();
            sfmlWidget->update(TimePerFrame);
        }
        sfmlWidget->draw();

        // add small sleep time, so we don't get delta == 0
        QTime dieTime= QTime::currentTime().addMSecs(1);
        while (QTime::currentTime() < dieTime) { } // wait until time passes
    }

    app.exit();

    return 0;
}

So, fixed-delta, pretty cool. But I have to add small sleep period (1 ms), or else delta will be 0 most of the time (Qt's timer is not very precise). Is it the best way to deal with this problem?
(And I need to figure out how to process SFML events for keyboard input, and then most of the work is done! :D)

Update: SFML events work well, I can easily get sf::Event::MouseEntered/Left to capture input
sf::Keyboard::isPressed works too! :D
Title: Re:creation - a top down action adventure about undeads
Post by: eXpl0it3r on December 13, 2015, 08:28:59 pm
Oh nice! :)

I've often thought about playing around with SFML and Qt, but never got around to it. Also nice to see that events are working, some threads about SFML and Qt had issues with event processing.

What exactly do you need the Qt timer for? C++11 introduces <chrono> which also has some highprecision timer (iirc).
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 13, 2015, 08:49:32 pm
Or sf::Clock, or QElapsedTimer. But please don't use QTime as a timer :P

And simply use sf::sleep or QThread::msleep if you want to pause the execution.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 13, 2015, 09:36:25 pm
Oh nice! :)

I've often thought about playing around with SFML and Qt, but never got around to it. Also nice to see that events are working, some threads about SFML and Qt had issues with event processing.
Yeah, this was a pleasant surprise for me, much easier than I expected.
Well, I didn't test all events, but MouseEntered/MouseLeft work well, and that's pretty much all I need for now. :D

What exactly do you need the Qt timer for? C++11 introduces <chrono> which also has some highprecision timer (iirc).
No need for it, yeah. I just saw people doing stuff with Qt timer and now I realize that I can just use sf::Clock, ha-ha :D
(Hmm, I wonder what's better: <chrono> or sf::Timer?)

Or sf::Clock, or QElapsedTimer. But please don't use QTime as a timer :P

And simply use sf::sleep or QThread::msleep if you want to pause the execution.
Okay, thanks :D
So, should I use sleep to wait for some time if the delta was too low to not waste lots of resources, updating events all the time?

Starting to think about how I should map components to JSON objects, this will be very interesting to solve...
Basically I want to change some value in JSON object and automatically change corresponding value in the object without tons of if/else stuff.
I also wonder how to decouple editor from game. I guess I should have some game.dll and Qt application will call some functions from it... I've never done stuff like this before, this will be something new :D

Title: Re:creation - a top down action adventure about undeads
Post by: Nexus on December 13, 2015, 10:29:05 pm
(Hmm, I wonder what's better: <chrono> or sf::Timer?)
In general, you should prefer the standard library where possible. However, in this particular case your code will be more portable with sf::Clock, because some standard library implementations (e.g. those of Visual Studio) were known to not use high-precision timers in Chrono until a few years ago.

Starting to think about how I should map components to JSON objects, this will be very interesting to solve...
Basically I want to change some value in JSON object and automatically change corresponding value in the object without tons of if/else stuff.
You should work with a C++ data structure that represents the JSON tree layout (which is very simple: arrays and objects=maps). I'm pretty sure good JSON libraries already come with that.

I also wonder how to decouple editor from game. I guess I should have some game.dll and Qt application will call some functions from it... I've never done stuff like this before, this will be something new :D
I wouldn't stick to one dynamic library format (DLL) unless you actually need it. There are various options for inter-process communication, see here (http://www.boost.org/doc/libs/1_59_0/doc/html/interprocess.html#interprocess.intro) for a list of common ones. Network sockets are also a possibility.

But are game and editor actually running in parallel, in two applications, and they need to know each other?
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 13, 2015, 10:52:41 pm
In general, you should prefer the standard library where possible. However, in this particular case your code will be more portable with sf::Clock, because some standard library implementations (e.g. those of Visual Studio) were known to not use high-precision timers in Chrono until a few years ago.
Alright, thanks. Less differences between game and level editor code, yay! :D

You should work with a C++ data structure that represents the JSON tree layout (which is very simple: arrays and objects=maps). I'm pretty sure good JSON libraries already come with that.
I use jsoncpp which has that, but I want to do this.
Suppose I have a class like this in C++
class Animation {
     int frameTime;
     int frameCount;
     ...
};
which looks like this in JSON:
{
     "frameTime" : 100,
     "frameCount" : 10
}
I output Json table (Json::Value in C++) to Qt table which then maps every field to Json::Value object, so when I change table value, corresponding Json::Value changes. But I also need to update corresponding C++ value. So I have to map Json::Value object to pointer to corresponding value, so when Json::Value changes, the variable value changes automatically. I already have some ideas how to implement this, but maybe there are easy ways to do this stuff.

I wouldn't stick to one dynamic library format (DLL) unless you actually need it. There are various options for inter-process communication, see here (http://www.boost.org/doc/libs/1_59_0/doc/html/interprocess.html#interprocess.intro) for a list of common ones. Network sockets are also a possibility.

But are game and editor actually running in parallel, in two applications, and they need to know each other?
Thanks, I'll check this out.
I want to have an instance of game running in Qt application. I can use code directly from my game project and then call functions from it, but I feel like this is a bad idea.
So, I need some other way to link editor and game engine code.
They, of course, need to communicate somehow. Suppose I click on some object. Level editor calls some function from game engine like this:
Entity* findEntity(sf::Vector& mousePos);
and now I get a pointer to entity and level editor can do pretty much everything with it, so if I decide to delete it, it does calls function from Game:
removeEntity(selectedEntity);
This would be trivial if I just #included some stuff from main code base, but I feel like game engine and level editor need to be separate somehow. (Hell, some devs write their editors in C# while the game engine is in C++, you can't do #include's in C# for code in C++, so you can't call it directly)
Title: Re:creation - a top down action adventure about undeads
Post by: Nexus on December 13, 2015, 11:25:33 pm
I already have some ideas how to implement this, but maybe there are easy ways to do this stuff.
MVC is a common pattern. Your C++ Json::Value class would then be the model, and the Qt table (or even the JSON file) the view. Changes in one will notify and update the other. Have a look at the Qt documentation to see how it provides such functionality.

I can use code directly from my game project and then call functions from it, but I feel like this is a bad idea.
So, I need some other way to link editor and game engine code.
If we're only talking about code, and not actual concurrent processes at runtime, why don't you simply outsource the shared code into a library?

This would be trivial if I just #included some stuff from main code base, but I feel like game engine and level editor need to be separate somehow.
Don't make your life overly complicated because you feel something. You know, keeping things simple is a skill.
A library is the straightforward approach here.

(Hell, some devs write their editors in C# while the game engine is in C++, you can't do #include's in C# for code in C++, so you can't call it directly)
There are well-established techniques for ports between languages (e.g. P/Invoke in this case). But you're dealing with a different problem ;)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 14, 2015, 07:01:07 am
MVC is a common pattern. Your C++ Json::Value class would then be the model, and the Qt table (or even the JSON file) the view. Changes in one will notify and update the other. Have a look at the Qt documentation to see how it provides such functionality.
I've already implemented a part of that. So, when the Qt table value changes, value in JSON changes automatically. But now I need to go further, I need to change C++ variable which corresponds to the changed JSON value, which is a harder problem, I think. :)

A library is the straightforward approach here.
Yeah, it seems like it.
I just have  no idea how they work because I never before had a need to do such code re-use. But I'll figure it out. (Btw, any good resources I can read about making libraries? Or is it so simple that I can't do wrong? :D)

There are well-established techniques for ports between languages (e.g. P/Invoke in this case). But you're dealing with a different problem ;)
Yep :D
Title: Re:creation - a top down action adventure about undeads
Post by: Jesper Juhl on December 14, 2015, 07:04:31 am
A library is the straightforward approach here.
Yeah, it seems like it.
I just have  no idea how they work because I never before had a need to do such code re-use. But I'll figure it out. (Btw, any good resources I can read about making libraries? Or is it so simple that I can't do wrong? :D)
This might be of use : http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 14, 2015, 07:45:31 am
If you only need the JSON <--> C++ mapping in the level editor, then you can use the Qt meta-object system, which allows class introspection.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 14, 2015, 07:59:03 am
This might be of use : http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
Thanks!

If you only need the JSON <--> C++ mapping in the level editor, then you can use the Qt meta-object system, which allows class introspection.
I may be wrong, but doesn't it require me to inherit from QObject? I can't do this, because I don't want to change the existing classes from my game. Or maybe I can create some wrapper class which will inherit from QObject and use Qt's introspection? Something like:
class AnimationWrapper : public QObject {
    Q_OBJECT
   
public:
    AnimationWrapper(Animation& animation) :
        frameCount(animation.frameCount),
        frameTime(animation.frameTime),
        ...
    {}
   
private:
    int& frameCount;
    int& frameTime;
    ... // etc.
   
};
and then later...
Q_PROPERTY(int& frameCount READ frameCount)
so when the JSON value changes I can do something like this:
animWraper.setProperty(changedValueName, newValue); // both are taken from Json::Value which just changed

Btw, animations are working now :D
(http://i.imgur.com/ufJxIIu.gif)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 14, 2015, 04:26:37 pm
(http://i.imgur.com/apwae3f.gif)
Okay, got some basic introspection working. Here's how the wrapper looks.

class AnimationWrapper : public QObject {
    Q_OBJECT
    Q_PROPERTY(bool looped READ isLooped WRITE setLooped)
    Q_PROPERTY(int frameCount READ getFrameCount WRITE setFrameCount)
    Q_PROPERTY(int frameTime READ getFrameTime WRITE setFrameTime)

public:
    AnimationWrapper(Animation* anim) :
        anim(anim)
    { }

    // is looped
    bool isLooped() const {
        return anim->isLooped();
    }

    void setLooped(bool b) const {
        anim->setLooped(b);
    }

    // frame count
    int getFrameCount() const {
        return anim->getFrameCount();
    }

    void setFrameCount(int fc) {
        anim->setFrameCount(fc);
    }

    // frame time
    int getFrameTime() const {
        return anim->getFrameTime().asMilliseconds();
    }

    void setFrameTime(int frameTime) {
        anim->setFrameTime(sf::milliseconds(frameTime));
    }
private:
    Animation* anim;
};
That's not the coolest thing, yeah, but now I can do this:
animationWrapper->setProperty("frameCount", 10); // same as calling animation->setFrameCount(10);
So, when some value changes, I find corresponding animation wrapper, and then I can change animation parameters using this wrapper.

Update: but then I realized that this system kinda sucks and I shoudn't really use QObject, because some introspection will be useful when loading components in the game from Json in the future...
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 14, 2015, 05:47:27 pm
Don't you already have a Lua binding of all your classes and objects? Can't you use it for introspection?
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 14, 2015, 06:00:34 pm
Don't you already have a Lua binding of all your classes and objects? Can't you use it for introspection?
I have one way binding like this:
void SomeComponent::loadFromScript()
{
     someVar = scriptManager.getData<SomeVarClass>(entityName + ".someVar");
     ...
}
So it's one way only. I can't set variables by name. I could change the value in Lua table and call loadFromScript again... but that's just silly.
And I think about moving most data stuff to JSON in near future.

Right now I think about implementing meta stuff like this:
void SomeComponent::SomeComponent()
{
     meta_register<SomeVarClass>("someVar", this, getSomeVar, setSomeVar); // getSomeVar/setSomeVar are get/set functions
     ...
}
and then I'll be able to do this:
someComponent->setProperty("someVar", newValue);
and this:
auto value = someComponent->getProperty("someVar");
So, it's basically like QObject meta stuff works, but without moc_....cpp and macros.

I can use it for
1) Loading from JSON (no need to write it by hand)
2) Saving to JSON
3) Displaying/changing component variables with Qt
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 15, 2015, 08:19:24 am
Okay, so I got some basic meta-property system working which lets me do this:
class Animation : public MetaObject
{
public:
    Animation()
    {
        meta_register("name", name);
        meta_register("isLooped", isLooped);
        meta_register("frameCount", frameCount);
    }
private:
    std::string name;
    bool isLooped;
    int frameCount;
};

int main()
{
    Animation a;
    a.setProperty("name", std::string("walk"));
    a.setProperty("isLooped", true);
    a.setProperty("frameCount", 100);

    std::cout << "Name = "  << a.getProperty<std::string>("name") << std::endl;
    std::cout << "isLooped = "  << a.getProperty<bool>("isLooped") << std::endl;
    std::cout << "frameCount = " << a.getProperty<int>("frameCount") << std::endl;
}
Pretty neat! This will allow me to serialize to JSON /deserialize from JSON without any effort. One more thing I need to add is support for get/set member functions, but that's pretty easy to do, I just wanted to keep the code which I show brief.

Here's the source code:
http://pastebin.com/54ATGH9X
There's almost no error checking to keep the example brief.
Any suggestions to improve this are welcome! Maybe there's a better way do to it than to use dynamic_cast :P
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 15, 2015, 08:58:19 am
The "problem" here is that each instance of the class will register and store the (same) meta-properties, but properties should be attached to the class, not to its instances. Moreover, I think inheritance is too strong: almost every instance of your engine will be a meta-object, whereas they should have one (shared by all instances).

So I would rather do something along the lines of:

MetaObject meta("Animation");
meta.addProperty("name", &Animation::name); // or get/set functions
...
xxx.registerMetaObject<Animation>(meta);

auto meta = xxx.findMetaObject(a);
meta.setProperty(a, ...);
meta.getProperty(a, ...);

That's just for the idea. You can add a lot of syntactic sugar on top of that, and you can also find a smarter way of managing registration and ownership of meta-objects.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 15, 2015, 09:27:06 am
I agree with all your points, Laurent. Version 2.0 coming soon! :D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 15, 2015, 09:43:38 am
Okay, it was a bit harder to implement, but it's so much cooler!
http://pastebin.com/SgAr78X3

it works like this:
class Animation
{
public:
    static void registerClass(MetaObject<Animation>& metaA)
    {
        metaA.addProperty("name", &Animation::name);
        metaA.addProperty("isLooped", &Animation::isLooped);
        metaA.addProperty("frameCount", &Animation::frameCount);
    }
   
private:
    std::string name;
    bool isLooped;
    int frameCount;
    FloatRect frame;
};

int main()
{
    MetaObject<Animation> metaA;
    Animation::registerClass(metaA);

    Animation a;
    metaA.setProperty(a, "name", std::string("walk"));
    metaA.setProperty(a, "isLooped", false);
    metaA.setProperty(a, "frameCount", 10);

    std::cout << "Name = " << metaA.getProperty<std::string>(a, "name") << std::endl;
    std::cout << "isLooped = " << metaA.getProperty<bool>(a, "isLooped") << std::endl;
    std::cout << "frameCount = " << metaA.getProperty<int>(a, "frameCount") << std::endl;
}
Of course, I'll need to have some MetaManager which will allow me to get Meta<Class> objects like this:
auto& meta = metaManager.get<Animation>();
I'll implement it soon.
Is it better now, Laurent? :D

P.S. a small improvement:
template <typename Class>
MetaObject::MetaObject()
{
     Class::registerClass(*this);
}

So now creating MetaObject<Animation> will automatically call Animation::registerClass
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 15, 2015, 09:50:42 am
Yes, much better, but let's see once you've completed the implementation ;)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 15, 2015, 09:53:59 am
Yes, much better, but let's see once you've completed the implementation ;)
Nice. :)
I guess I'll just make std::unordered_map<std::type_index, std::unique_ptr<IMetaObject>> metaObjects and then I'll use dynamic_cast just as I did with properties. But yeah, I'll post the source code once this is implemented :D

... or maybe I can should just store static MetaObject<SomeClass> meta inside SomeClass? No need for MetaManager then. And then I'll just do this:
Animation::meta.setProperty(a, ...);

Update: ...and done
Animation a;
auto& metaA = Animation::meta;
metaA.setProperty(a, "name", std::string("walk"));
metaA.setProperty(a, "isLooped", false);
metaA.setProperty(a, "frameCount", 10);

std::cout << "Name = " << metaA.getProperty<std::string>(a, "name") << std::endl;
std::cout << "isLooped = " << metaA.getProperty<bool>(a, "isLooped") << std::endl;
std::cout << "frameCount = " << metaA.getProperty<int>(a, "frameCount") << std::endl;

And now I'll add JSON serialization/deserialization. :D
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 15, 2015, 10:23:51 am
I don't like this approach because:
- it is intrusive
- you can't control the lifetime of meta-objects, they all live in the global scope
- there's still a lof of static types involved

... however, it's good because you kept it simple and it really sticks to your needs. So I'd say leave it as it is, unless you think that one of the points above may be a problem in the future.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 15, 2015, 10:34:16 am
Alright. :)
I think that meta-objects don't need to have their lifetime, because information about the class is compile-time (if only we had better constexpr, I'd like to generate all this stuff at compile time, hehe). So it's fine unless I would want to add/remove meta objects in runtime, but I don't see why I would need that. (or if one meta-object would depend on the other, but I think this will be pretty bad).
Global scope is not a problem too, because &SomeClass::SomeVar is global too (though it can be private, but SomeClass::meta can too) ;)

So yeah, I'll see if there are some problems with this approach.
I just don't want to search for meta-object in the map every time I need to access meta-info which is almost here, if you have SomeClass instance. :D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 16, 2015, 10:45:51 pm
Okay, I'm almost done with this meta-system. I decided to go with the static approach (it's even more static that I originally thought to make!)
Animation class:
class Animation
{
public:
    // main stuff here
    int getFrameCount() const;
    void setFrameCount(const int& fc);
    // meta
    static void registerClass();
private:
    std::string name;
    bool isLooped;
    int frameCount;
    FloatRect frame;
};
As you can see, no static MetaObject involved.

First of all, let's look at what I can do now:
Let's look at the code:
// need to call this before using Meta<Animation>
Meta<Animation>::init();

// let's create a simple animation
Animation a;

// and set some properties using meta stuff
Meta<Animation>::setProperty(a, "name", std::string("walk"));
Meta<Animation>::setProperty(a, "isLooped", false);
Meta<Animation>::setProperty(a, "frameCount", 10);
Meta<Animation>::setProperty(a, "frame", FloatRect(10, 20, 32, 32));

// let's serialize it to JSON!
Json::Value root = Meta<Animation>::serialize(a);

// now we can save it to file, but we'll input it to console
std::cout << "Animation a in JSON:" << std::endl;
std::cout << root << std::endl;

Animation b;
Meta<Animation>::deserialize(b, root); // get info from JSON

std::cout << "____________________" << std::endl;
std::cout << "Let's look at Animation b now:" << std::endl;
std::cout << "Name = " << Meta<Animation>::getProperty<std::string>(b, "name") << std::endl;
std::cout << "isLooped = " << Meta<Animation>::getProperty<bool>(b, "isLooped") << std::endl;
std::cout << "frameCount = " << Meta<Animation>::getProperty<int>(b, "frameCount") << std::endl;
std::cout << "frame = " << Meta<Animation>::getProperty<FloatRect>(b, "frame") << std::endl;

Output:
(http://i.imgur.com/n5fgMew.png)

Cool!
So, Meta<Animation> (it's Meta now instead of MetaObject) stores a static map of properties. I thought that classes won't need to have different meta presentations, so now I can just use Meta<Animation> to do all the stuff!

Let's look how I can add properties:
void Animation::registerClass()
{
    Meta<Animation>::addProperty("name", &Animation::name);
    Meta<Animation>::addProperty("isLooped", &Animation::isLooped);
    Meta<Animation>::addProperty("frameCount", &Animation::frameCount,
        &Animation::getFrameCount, &Animation::setFrameCount);
    Meta<Animation>::addProperty("frame", &Animation::frame, &serializeRect, &deserializeRect);
}
So, I can set custom getters and setters which will be called each time getProperty or setProperty are called for the property who set them.
I can also add serialization/deserialization which allow me to convert from Json::Value to T and from T to Json::Value.
I don't need these functions for int, float, bool, etc., because I can just do this (jsoncpp provides this functions):
int i = intValue.asInt();
bool b = boolValue.asBool();
... // etc
But I can't convert from T to Json::Value if T is custom class.
So I can provide functions like this which allow me to do serialization/deserialization for custom classes:
Json::Value serializeRect(const FloatRect& rect)
{
    Json::Value v;
    v[0] = rect.x;
    v[1] = rect.y;
    v[2] = rect.w;
    v[3] = rect.h;
    return v;
}

void deserializeRect(FloatRect& rect, const Json::Value& value)
{
    rect.x = value[0].asFloat();
    rect.y = value[1].asFloat();
    rect.w = value[2].asFloat();
    rect.h = value[3].asFloat();
}

So, this allows me to do some great stuff, for example I can save and load components from JSON files without writing additional code for serialization/deserializaition! I can also use all this info about objects to display their properties on the screen while the game is running. How cool is that?

Ask me any questions if you're interested in knowing some other details. I won't post code until it becomes better, it has grown a lot in size, so I have to make a lot of work documenting and cleaning up stuff.
Title: Re:creation - a top down action adventure about undeads
Post by: Jabberwocky on December 17, 2015, 12:02:34 am
No doubt, decent tools can make or break a game, especially content heavy games like an RPG or action adventure.  I've enjoyed watching you hammer out your approach with the editor, Elias.  And the JSON <-> C++ serialization.

One thought - you may also want to be thinking about saving and loading functionality while you're at it.  Like, the "save game" and "load game" buttons.  It's very much the same kind of serialization/deserialization type of problem.  I'm personally a big fan of having a human-readable save file format (like XML or JSON), as this can help immensely during development and debugging.  As opposed to a binary format.

So, maybe you can use the C++ <-> JSON serialization for saving and loading the game, just like you do in your editor for authoring animations and other game content.
Title: Re:creation - a top down action adventure about undeads
Post by: dabbertorres on December 17, 2015, 04:29:30 am
^

Can even take it a step further and make a "game save editor" of sorts. That can help with debugging as well. Set the game to be at a certain level of completion or whatnot, and make sure the game loads and starts/runs fine, etc.

(Though, depending on game format, may be as simple as a bunch of checkboxes!)
Title: Re:creation - a top down action adventure about undeads
Post by: dwarfman78 on December 17, 2015, 07:05:26 am
your test is invalid because you print a's properties instead of b's.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 17, 2015, 07:43:21 am
Jabberwocky, dabbertorres, I'll think about it. There's just so many stuff I don't have to save to the save file, for example, component's default values which are stored in entity definition files. I only have to save stuff which is unique for entity: it's position, current state, HP, inventory, etc.
But, there's sometimes no need to save  HP or current position which most games don't do and they're fine. So, as for now, I'll be writing game saving/loading code by hand by thinking carefully about what I have to save and what I don't.

dwarfman78, ha-ha, right, I've changed the code.
I just checked b's values in debugger and thought:"Alright, this works, output is expected, let's post! :D"
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 17, 2015, 08:35:01 am
Just two comments about your implementation:

- Why do you need to pass the direct pointer to member when you also pass the getter and setter functions, when you register the property?

- Why do you pass the serialization functions explicitely when you register a property? You should rather use a single known function (like jsonSerialize / jsonDeserialize) for which you add overloads when you need to handle new types. The compiler will then choose the right overload for you. This is similar to what standard streams do with operators << and >>.

And if you're tired of writing all this stuff, you can add a wrapper that makes it a little funnier to write:
auto meta = getMeta(a); // returns a MetaWrapper<T>, which stores the T instance and invokes Meta<T>:: functions
meta.set("frameCount", 10);
auto count = meta.get<int>("frameCount");

And... this is also mostly for fun, but if you want to make the whole system safer, and disallow calling Meta<T>::addProperty from anywhere, you can do something like this:
void Animation::registerClass(MetaBuilder<Animation>& builder)
{
    builder.add("name", &Animation::name);
    builder.add("isLooped", &Animation::isLooped);
    ...
}

By restricting construction of MetaBuilder<T> and access to Meta<T>::addProperty, you can make sure by design that:
- Meta<T> can only be populated in T::registerClass, so the whole initialization of meta stuff is kept under control
- the rest of the code only has access to Meta<T>::get/set
- ... and if you use the MetaWrapper, you don't even need a visible Meta<T> class anymore, you can keep everything hidden and only expose construction with MetaBuilder and access with MetaWrapper.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 17, 2015, 01:14:14 pm
Thanks, Laurent, there are fantastic suggestions! I've implemented everything that you've proposed.
Once I finish cleaning everything up, I'll create a github repository, so maybe someone will help improve it even further :D

Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 17, 2015, 02:54:21 pm
I've tried out more complex classes and here are the results.
Animation class stays the same, let's add GraphicsComponent class:
class GraphicsComponent {
public:
    GraphicsComponent();

    Json::Value serializeAnimations() const;
    void deserializeAnimations(const Json::Value& root);

    static void registerClass(MetaBuilder<GraphicsComponent>& builder);
private:
    std::string filename;
    std::map<std::string, Animation> animations;
    Animation specialAnimation;
};

Here's how register function looks:
void GraphicsComponent::registerClass(MetaBuilder<GraphicsComponent>& builder)
{
    builder.add("filename", &GraphicsComponent::filename);

    builder.add<decltype(animations)>("animations");

    auto& animationsProperty = builder.get<decltype(animations)>("animations");
    animationsProperty.setMemberSerializer(&GraphicsComponent::serializeAnimations);
    animationsProperty.setMemberDeserializer(&GraphicsComponent::deserializeAnimations);

    builder.add("specialAnimation", &GraphicsComponent::specialAnimation);
}

Here's how JSON file for this class looks (all I have to do to get this is call Meta<GraphicsComponent>::serialize) :
{
        "animations" :
        [
                {
                        "frame" : [ 0, 32, 32, 32 ],
                        "frameCount" : 30,
                        "isLooped" : true,
                        "name" : "idle"
                },
        ...
        ],
        "filename" : "res/hero.png",
        "specialAnimation" :
        {
                "frame" : [ 0, 64, 32, 32 ],
                "frameCount" : 20,
                "isLooped" : false,
                "name" : "megaAttack"
        }
}

Serializing/deserializing map of animations is tricky, because it's array in JSON and we want to use animation names as map keys in C++. So, let's add functions which will be called each time Meta<GraphicsComponent> tries to serialize/deserialize animations map:
Json::Value GraphicsComponent::serializeAnimations() const
{
    Json::Value animationsArray;
    for (const auto& animationPair : animations) {
        auto& animation = animationPair.second;
        animationsArray.append(Meta<Animation>::serialize(animation));
    }
    return animationsArray;
}

void GraphicsComponent::deserializeAnimations(const Json::Value& root)
{
    for (int i = 0; i < root.size(); ++i) {
        Animation a;
        Meta<Animation>::deserialize(a, root[i]);
        animations[a.getName()] = a;
    }
}

Great! What about Animation specialAnimation? If no functions are provided, Meta<T>::serialize / Meta<T>::deserialize get called. If the meta class was not explicitly created for the T (using T::registerClass function) , it will have no properties, so the first function will return Json::nullValue and the second function will return T().

As for MetaWrapper object, here's how useful it is:
auto metaGc = Meta<GraphicsComponent>::getMeta(gc);
metaGc.set("filename", std::string("res/test.png"));
int frameCount = metaGc.get<int>("frameCount");
The code is much cleaner and easier to read!

Oh, and as Laurent suggested, doing this is possible:
builder.add<int>("frameCount");
auto& frameCountProperty = builder.get<int>("frameCount");
frameCountProperty.setGetter(&Animation::getFrameCount);
frameCountProperty.setSetter(&Animation::setFrameCount);
As you can see, there's no need to provide &Animation::frameCount for this property. What happens if I don't provide setter and try to call set for this property? (Or try to get some property without getter?) Assertion tell me about it ("Forgot to add setter/getter!"), and everything is alright :D (if I don't use assertions, C++ silently writes to nullptr and the stack gets corrupted!)

And now I'm getting back to work on Animation tool... which will later become Entity Creation Tool!
But I'll have to rewrite a lot of stuff to store all component data in JSON instead, so this will take a while. I'll try not to stop working on the game and will draw art and think about levels/mechanics in parallel.
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 17, 2015, 06:21:30 pm
Quote
auto metaGc = Meta<GraphicsComponent>::getMeta(gc);
The purpose of using a function was mainly to benefit from type deduction, so that you never have to write any template parameter. Just make getMeta a free function, and you can remove the "Meta<GraphicsComponent>::" part.

Quote
Oh, and as Laurent suggested, doing this is possible
I don't remember suggesting that ;D
What I previously said is that:
- there were useless arguments in your calls (pointer to member in addition to getter/setter)
- using an overload of a single function for serialize/deserialize would be better than explicitly passing the functions when you register the property
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 17, 2015, 08:29:23 pm
The purpose of using a function was mainly to benefit from type deduction, so that you never have to write any template parameter. Just make getMeta a free function, and you can remove the "Meta<GraphicsComponent>::" part.
Ohhh, yeah, I'll make that :D

Quote
Oh, and as Laurent suggested, doing this is possible
I don't remember suggesting that ;D
What I previously said is that:
- there were useless arguments in your calls (pointer to member in addition to getter/setter)
Well, as I've shown you can either pass just pointer to member ot getter + setter. How is this useless? You either access the member directly or use getter + setter to do this.

- using an overload of a single function for serialize/deserialize would be better than explicitly passing the functions when you register the property
Can you please explain more? I have no idea how to do this. :D

And... I've encountered the first huge problem.
What I need is to have Property::serialize function which does this:
1) Calls serializer member function if it exists
2) If it doesn't exist:
     a) Returns Json::Value(T&) for these types: bool, string, float, int.
     b) Tries to call Meta<T>::serialize for other types
This is easily done with template specializations...
3) If everything else fails, returns empty Json::Value() (null value)

Here's the problem: suppose I try to serialize size_t. Template specialization for size_t doesn't exist, so Meta<size_t>::serialize gets called. But this will fail to sompile, because size_t doesn't have registerClass function which is required for all types which use Meta<T>.
Even if I call it only with "good" types, this introduces another problem: circular dependencies. Meta<T>::serialize calls Property::serialize for each property of T, some of which may call Meta<U>::serialize, etc.
This introduces circular header dependencies and other headaches... So, I feel like I'm doing this wrong. Any suggestions? :D
I feel there's much easier solution...
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 17, 2015, 09:00:43 pm
Quote
Well, as I've shown you can either pass just pointer to member ot getter + setter.
I was referring to this:
Meta<Animation>::addProperty("frameCount", &Animation::frameCount,
        &Animation::getFrameCount, &Animation::setFrameCount);
If you have a getter and a setter you obviously don't need direct access to the member ;)

Quote
You either access the member directly or use getter + setter to do this.
If now it's one or the other, it's fine.

By the way, what do you gain by allowing to set the meta-property's properties (;D) after constructing it, rather than passing all you need directly to the add function?

Quote
Can you please explain more? I have no idea how to do this.
Sure.
Json::Value json::serialize(int x) {...}
void json::deserialize(const Json::Value& root, int& x) {...}

Json::Value json::serialize(std::string s) {...}
void json::deserialize(const Json::Value& root, std::string& s) {...}

Json::Value json::serialize(sf::FloatRect rect) {...}
void json::deserialize(const Json::Value& root, sf::FloatRect& rect) {...}

Json::Value json::serialize(sf::IntRect rect) {...}
void json::deserialize(const Json::Value& root, sf::IntRect& rect) {...}

...

auto value = json::serialize(v);

If an overload exists for the type of v, the compiler will automatically choose it. If it doesn't, the compiler will complain. The point is, the serialization code remains generic, it only has to call json::serialize and the compiler does the rest, as long as a compatible overload exists.

Quote
And... I've encountered the first huge problem.
What I explained may solve it as well. If not, I'll try to come up with a proper solution later ;)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 17, 2015, 10:48:25 pm
I was referring to this:
Meta<Animation>::addProperty("frameCount", &Animation::frameCount,
        &Animation::getFrameCount, &Animation::setFrameCount);
If you have a getter and a setter you obviously don't need direct access to the member ;)
Look at the code I've posted previously:
builder.add<int>("frameCount");
auto& frameCountProperty = builder.get<int>("frameCount");
frameCountProperty.setGetter(&Animation::getFrameCount);
frameCountProperty.setSetter(&Animation::setFrameCount);
Just pointers to get/set functions, no direct access! :D

By the way, what do you gain by allowing to set the meta-property's properties (;D) after constructing it, rather than passing all you need directly to the add function?
That's because I was tired of having lots of constructor overloads
1) No pointers passed
2) Just pointer to member
3) Getter + Setter
4) Getter + Setter + Serializer/Deserializer
5) Pointer to member + Serializer / Deserializer
Setting particular functions makes the code easier to read and write, imo. But maybe I should come back to having 3 (or 4?) overloads, I don't know :D

Sure.
Json::Value json::serialize(int x) {...}
void json::deserialize(const Json::Value& root, int& x) {...}

Json::Value json::serialize(std::string s) {...}
void json::deserialize(const Json::Value& root, std::string& s) {...}

Json::Value json::serialize(sf::FloatRect rect) {...}
void json::deserialize(const Json::Value& root, sf::FloatRect& rect) {...}

Json::Value json::serialize(sf::IntRect rect) {...}
void json::deserialize(const Json::Value& root, sf::IntRect& rect) {...}

...

auto value = json::serialize(v);
Yeah, this is something I previously did, though I tried to make the function generic and failed! :D
You see, I just wanted to have function like this:
template <typename T>
Json::Value cast(const T& obj) {
     return Meta<T>::serialize(obj);
}
and having a bunch of template specializations for other specializations. But this introduces cyclic dependency between Meta -> Property -> cast -> Meta which I couldn't resolve. Once again, the cyclic dependency is caused by these things I have to do:
Meta<T>::serialize calls Property<U>::serialize for some property with type U, which then either calls template specialization (for simple types) or Meta<U>::serialize and so on. And I can't even forward declare all this stuff :D

This is what made it possible to simply create JSON in the GraphicsAnimation class. Meta<GraphicsAnimation> iterated over all the properties, it did this:
1) Called template specialization for std::string
2) Called serialization function for std::map<...> which I've provided
3) Called template function Json::cast<Animation> which then called Meta<Animation>::serialize

This worked in MSVC, but GCC fails to compile this code because of the cycle. So, this is my problem now. :D
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 17, 2015, 11:06:20 pm
Would you mind sharing your code for Meta and Property, so that I can have a look?
Title: Re:creation - a top down action adventure about undeads
Post by: Jabberwocky on December 17, 2015, 11:12:58 pm
If an overload exists for the type of v, the compiler will automatically choose it. If it doesn't, the compiler will complain. The point is, the serialization code remains generic, it only has to call json::serialize and the compiler does the rest, as long as a compatible overload exists.

This is pretty close to how I've implemented XML serialization in my game.

You've given a lot of fantastic advice in this thread Laurent, and it's cool seeing the SFML devs so involved in these devlog threads.

Jabberwocky, dabbertorres, I'll think about it. There's just so many stuff I don't have to save to the save file, for example, component's default values which are stored in entity definition files. I only have to save stuff which is unique for entity: it's position, current state, HP, inventory, etc.
But, there's sometimes no need to save  HP or current position which most games don't do and they're fine. So, as for now, I'll be writing game saving/loading code by hand by thinking carefully about what I have to save and what I don't.

Absolutely.  You don't save the same data to a savegame file as you would to an entity definition file.  It should only be "dynamic state" stuff, like position and inventory, as you mention.

What I am saying is that in both cases (editing, saving) you need to serialize and deserialize data to a file.  And that it's useful to be able to open and read your savegame files (in a non-binary format).  So JSON may be an ideal format for both.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 17, 2015, 11:23:26 pm
Would you mind sharing your code for Meta and Property, so that I can have a look?
Sure, here:
https://bitbucket.org/edaler/meta-stuff/src
Check out include/JsonCast.h. It includes Meta.h which causes the problem according to GCC. It compiles with MSVC, huh. Also, Property.inl and Meta.inl have some very important code
And yeah, I'm sorry that some code may be bad, this is very WIP, so I still have some stuff to improve. ;D

You've given a lot of fantastic advice in this thread Laurent, and it's cool seeing the SFML devs so involved in these devlog threads.
Ha-ha, yeah, I'm very glad that so many awesome people read my dev logs and help me make the game! :D

Absolutely.  You don't save the same data to a savegame file as you would to an entity definition file.  It should only be "dynamic state" stuff, like position and inventory, as you mention.

What I am saying is that in both cases (editing, saving) you need to serialize and deserialize data to a file.  And that it's useful to be able to open and read your savegame files (in a non-binary format).  So JSON may be an ideal format for both.
Yup, it's quite good, working with it was a pleasure. Easy to read, easy to make, easy to parse. :D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 18, 2015, 10:07:48 pm
Okay, aside from the circular dependencies problems, I think about easier ways to solve the problem.
So, I think it would be good to make Json::toValue(T& obj) return null value for ALL non-standard types. What about the classes which can be serialized? Well, I think that it would be good for classes to provide serialization function to all members with non-standard types which have to be serialized. So, the Meta<T>::serialize will work like this:
1) Call toValue(T& obj) for all properties which have simple types (int, bool, string, etc.)
2) Ignore other properties and just call T::serialize

So, for GraphicsComponent this function will look like this:
void GraphicsComponent::serialize(Json::Value& root)
{
    root["specialAnimation"] = Meta<Animation>::serialize(specialAnimation);
    ... // serialize other stuff
}
So, it would just "append" all non-standard properties to existing Json::Value and the problem is solved.
The stuff I wanted to make previously is much more compilcated and isn't necessary as you can see (though it has some downsides, but they are okay!)

Update: so, I've made the changes, cast<T> function in Json::cast may seem silly, but this is one of the ways to be sure not change properties with non-default types. If I just returned T() for all non-standard classes, there's no way I could tell that this is T() for non-default value or some standard-type property is really T() (0, 0.0f, "", etc.)
Title: Re:creation - a top down action adventure about undeads
Post by: FRex on December 21, 2015, 05:35:26 am
This thread kept popping up non stop last week in recent posts so I looked through the screens and I noticed in one of the gif screens you use a small console/prompt in your game to enter Lua code.
I don't know how much code you enter by hand into game itself vs. code in files but I decided to shameless promote myself a little anyway. :P
I happen to have a Lua SFML console/terminal lib for 5.1 and 5.2 (I'd not mind adding 5.3 if that's what you're using now, but it came after you started and there is little benefit in upgrading 5.1 to 5.2 to 5.3 for gamedev purposes so I'm guessing it's not).
It's a Slavic product too. ;D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 25, 2015, 08:53:50 am
I don't know how much code you enter by hand into game itself vs. code in files
Not much, it's mostly for testing purposes. The code is not saved, this console just calls some C++ functions if I need to call them.

I happen to have a Lua SFML console/terminal lib for 5.1 and 5.2 (I'd not mind adding 5.3 if that's what you're using now, but it came after you started and there is little benefit in upgrading 5.1 to 5.2 to 5.3 for gamedev purposes so I'm guessing it's not).
How does it work? Does it integrate into C++ program and then calls Lua/SFML bindings?

Progress update
I've passed lots of exams in my university, so the week was very busy and I didn't have any time to work on the game! But I'll be mostly free for the next month, so I'll work on the game a lot.
I'll write a big blog post about the stuff I've done this year later. :)
Title: Re:creation - a top down action adventure about undeads
Post by: FRex on December 25, 2015, 10:48:21 am
Quote
How does it work? Does it integrate into C++ program and then calls Lua/SFML bindings?
It's a Lua console so it's like the 'lua' command line program except in your game.
You type Lua code into it and it'll evaluate it for you (plus extras like completion, history, etc.).
Anything you exposed to Lua is available, you're basically doing luaL_dostring at runtime in a super fancy way.

It's a C++ lib which depends only on Lua, C++98 and SFML and is meant to be easy to use:
1. You create the view, input and model class and give input the model ptr (and set font and history if you don't want to use default ones from default paths) and give L pointer to the model.
2. You call  input.handleEvent(eve) to filter your events through the console in your pollEvent loop.
3. You call view.geoRebuild(&model) and then draw the view (it's SFML drawable) when you want to render it.

There is an example here of minimal program that has just a console in it, with default everything: https://github.com/FRex/LuaConsole/blob/master/examples/main.cpp
It shouldn't take more than 30 minutes to get into an app and I tried to make it well configurable and so on but with sane defaults.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 25, 2015, 10:00:21 pm
Heh, this is basically what I do with my console. Everything I write after "lua" is passed to luaL_dostring.
But I have other functions as well. Like if I write "open res/levels/someLevel.txt", it opens level, if I write "info 45", it prints info about entity with id=45, etc.
Title: Re:creation - a top down action adventure about undeads
Post by: FRex on December 25, 2015, 11:50:54 pm
I do just Lua code, so everything I want to use there must be exposed to Lua for my apps, but then I get history, completion, incomplete chunks, colors, ect. and I like working with Lua so it's worth it to me. I was thinking about a simplified bash-like input without braces and commas or about adding moonscript or typedscript input (or even some user provided input handler via callback instead of making all go through Lua) but didn't try to do any of that yet.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 27, 2015, 04:27:41 pm
I do just Lua code, so everything I want to use there must be exposed to Lua for my apps, but then I get history, completion, incomplete chunks, colors, ect. and I like working with Lua so it's worth it to me. I was thinking about a simplified bash-like input without braces and commas or about adding moonscript or typedscript input (or even some user provided input handler via callback instead of making all go through Lua) but didn't try to do any of that yet.
That's pretty cool. I'll check out your project. :D

Progress update
Okay, I'm almost done with Animation Tool. Here's how it looks now:
(http://i.imgur.com/0iPWhEs.gif)
This gif actually uses Meta system I've been working on for so long. Previous gifs just used JSON and reloaded animation when something changed. This one changes C++ value, so when I change "frameTime", corresponding C++ variable changes!

Stuff I've also added:
Stuff I need to add:
Later I'll use this project to make entity editor. It will work by the same principle. What's cool is that most of the members in component classes are of these types: bool, int, float, size_t, std::string, sf::Vector2i, sf::Vector2f, sf::IntRect, sf::FloatRect which are supported by my meta system very well.

One current problem I have which someone may help me solve is this. Suppose I want to do this:
std::cout << meta.get("someProperty");
This isn't going to work, because I need to do this:
std::cout << meta.get<int>("someProperty");  // if someProperty is int
Why do I need to specify the type? I need this type to convert from IProperty<Class> to Property<T, Class> inside get function!  (where T is type of property, Class is class to which this property belongs)

Property<T, Class>  has T Property<T, Class>::get() function which returns value of the property, but IProperty can't have it as virtual, because it's a base class which I use to store all properties in one map.
When I store Property<T, Class> as IProperty<Class> pointer I lose type of the property. I've solved this by storing type_index of T inside IProperty, so I can later get it to identify which type Property has.

So I can do this:
if(meta.getPropertyType("someProperty") == typeid(int)) {
    std::cout << meta.get<int>("someProperty");
} else if(meta.getPropertyType("someProperty") == typeid(double)) {
    std::cout << meta.get<double>("someProperty");
} ...
but those if/else things are pretty awful to write! (but they work, he-he)
Are there any other solutions?
What I want to do is do is call template function by getting the type out of type_index. Any way to do it without if/else?
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 27, 2015, 07:17:11 pm
virtual std::ostream& IProperty::print(std::ostream& stream) = 0;

Again, you can then add some syntactic suger on top of that to make it look funnier.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 27, 2015, 09:21:34 pm
virtual std::ostream& IProperty::print(std::ostream& stream) = 0;

Again, you can then add some syntactic suger on top of that to make it look funnier.
At first I wanted to say "I've oversimplified the problem, in MY case I can't use virtual functions!" but then I thought "oh wait... what if...?" and turns out I can use them! :D
So, I've just replaced lots of awful code with one line(!) which looks like this:
meta.setData(name, value); // where value is QVariant.
This call IProperty<Class>::setData which calls Property<T, Class>::setData and there I have something like this:
T v;
castFromQVariant<T>(v, value);
set(obj, v);
Virtual function saves the day!
(http://i.imgur.com/wRbTMXi.png)

P.S. and I just want to show this gif. I've realized how many cool animations I have drawn and it made me happy :D
(http://i.imgur.com/UPw7S6i.gif)
Title: Re:creation - a top down action adventure about undeads
Post by: Nexus on December 27, 2015, 09:45:09 pm
Nice! And this looks like a really versatile tool to tweak the animations :)

The presence of explicit case differentiations based on any kind of type identifier (dynamic_cast, typeid, a type enum, ...) is usually a strong indicator of bad abstraction. Very often, a form of polymorphism can help in these cases. See also my reply here (http://en.sfml-dev.org/forums/index.php?topic=7023.msg69437#msg69437).
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 27, 2015, 10:23:53 pm
Nice! And this looks like a really versatile tool to tweak the animations :)
Thanks! And it'll be a lot more versatile once I move all entity data to JSON and then I'll be able to do same stuff with most entity parameters.

The presence of explicit case differentiations based on any kind of type identifier (dynamic_cast, typeid, a type enum, ...) is usually a strong indicator of bad abstraction. Very often, a form of polymorphism can help in these cases. See also my reply here (http://en.sfml-dev.org/forums/index.php?topic=7023.msg69437#msg69437).
Wow, this looks really interesting, I'll think about it. The only place I have dynamic_cast now is get/set functions for properties. So, if I call this:
auto value = meta.get<int>("someIntProperty");
IProperty<Class> is cast to Property<T, Class> inside the get function, so I can call
T Property<T, Class>::get()
{
    ...
}

this function cannot be virtual, because of different return types for each property type.
But maybe I can do some trickery with templates and virtual functions which will allow me to get needed type from IProperty*... :D
Title: Re:creation - a top down action adventure about undeads
Post by: Nexus on December 27, 2015, 11:01:56 pm
Do you need dynamic_cast for error checking? Otherwise, you can as well downcast with static_cast.

Or even better, combine the advantages of both. I've written a downcast function template (http://www.bromeon.ch/libraries/aurora/v1.0/doc/_downcast_8hpp.html) that checks the type in Debug mode, but is fast in Release mode. It's a drop-in replacement for static_cast:
Base& base = ...;
auto& derived = aurora::downcast<Derived&>(base);
auto* derived = aurora::downcast<Derived*>(&base);

By the way, the Aurora library is header-only and very lightweight, so it can be used very easily within any project (without configuration, building or linking).
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 28, 2015, 09:35:34 am
Oh... if you use QVariant then it's a totally different thing. It does all the crappy things for you (type abstraction, checking, conversion, JSON serialization, ...). But I thought that you wanted to stay away from Qt specific stuff for this part of the code.

So now, may I ask why you still need this IProperty class with typed derived classes?
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 28, 2015, 09:40:11 am
Do you need dynamic_cast for error checking? Otherwise, you can as well downcast with static_cast.
Yeah, I think that dynamic_cast is not really necessary, but I think that assert which checks that cast succeeded will be nice. Are there any speed diferences between static_cast and dynamic_cast?

Or even better, combine the advantages of both. I've written a downcast function template (http://www.bromeon.ch/libraries/aurora/v1.0/doc/_downcast_8hpp.html) that checks the type in Debug mode, but is fast in Release mode. It's a drop-in replacement for static_cast:
Base& base = ...;
auto& derived = aurora::downcast<Derived&>(base);
auto* derived = aurora::downcast<Derived*>(&base);
Good idea.

By the way, the Aurora library is header-only and very lightweight, so it can be used very easily within any project (without configuration, building or linking).
I think I'll implement my template stuff first (this is so useful to learn template trickery!) and then I'll try to use your library to gain some perfomance, because I think that your code may be better :D
Title: Re:creation - a top down action adventure about undeads
Post by: Nexus on December 28, 2015, 11:04:03 am
Yeah, I think that dynamic_cast is not really necessary, but I think that assert which checks that cast succeeded will be nice. Are there any speed diferences between static_cast and dynamic_cast?
Yes, of course. As implied by the name, static_cast is resolved at compile time (the compiler computes the new start address of the class, which is more or less an addition at runtime), while dynamic_cast is a runtime operation that looks up the RTTI of the involved classes and checks their inheritance relation. But in any case, performance should not be the decisive factor here.

You can only use static_cast when you're sure about the conversion, and it's more limited (regarding cross-casts or casts through virtual inheritance). But the use of dynamic_cast should be questioned; often, a design with virtual functions can replace it.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 28, 2015, 11:51:06 am
Yeah, I think that dynamic_cast is not really necessary, but I think that assert which checks that cast succeeded will be nice. Are there any speed diferences between static_cast and dynamic_cast?
Yes, of course. As implied by the name, static_cast is resolved at compile time (the compiler computes the new start address of the class, which is more or less an addition at runtime), while dynamic_cast is a runtime operation that looks up the RTTI of the involved classes and checks their inheritance relation. But in any case, performance should not be the decisive factor here.
Good to know, thanks.

You can only use static_cast when you're sure about the conversion, and it's more limited (regarding cross-casts or casts through virtual inheritance).
After some thinking, I think that I need to do dynamic_cast, because I can't be sure about some stuff. Like if I have some property Property<T, Class> which is stored as IProperty<Class>* and then if I call
int i = meta.get<int>("someProperty")
I assume that T is int, so this needs an assert.

But the use of dynamic_cast should be questioned; often, a design with virtual functions can replace it.
Yeah, I'll try to think about improving my design, but right now it works pretty okay :D

And here's another screenshot of the animation tool. Almost done!
(http://i.imgur.com/zil8Lsk.png)
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 28, 2015, 02:40:25 pm
I posted while you were replying to Nexus, so you may have missed it:

Quote
Oh... if you use QVariant then it's a totally different thing. It does all the crappy things for you (type abstraction, checking, conversion, JSON serialization, ...). But I thought that you wanted to stay away from Qt specific stuff for this part of the code.

So now, may I ask why you still need this IProperty class with typed derived classes?
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 28, 2015, 05:34:53 pm
I posted while you were replying to Nexus, so you may have missed it:

Quote
Oh... if you use QVariant then it's a totally different thing. It does all the crappy things for you (type abstraction, checking, conversion, JSON serialization, ...). But I thought that you wanted to stay away from Qt specific stuff for this part of the code.

So now, may I ask why you still need this IProperty class with typed derived classes?
Yeah, I've missed it, sorry. :D
So, I need to cast from QVariant to T and back to be able to edit/display properties with QTreeView. It passes QVariant to setData in my model (which is inherited from QAbstractItemModel) and then I need to cast it to the correct type and set it to property. But... I think that the QVariant passed by QTreeView can be converted to QString and then to std::string, so I can basically make this get/set functions which convert std::string to needed value. (instead of making virtual functions which operate on QVariant)
So, when I type "56" it's treated as int, when I type "32, 32" it's treated as sf::Vector2i, etc.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 29, 2015, 10:54:31 pm
So, implementing toString and getValueFromString methods totally solved the problem with having QVariant near animation classes. QTreeView uses QString for data manipulation, so when you input something, you get QVariant which contains QString with stuff you just wrote. This is converted to std::string and passed to virtual function in IProperty<Class> which then calls function in Property<T, Class> which then converts from std::string to T.

One interesting problem to solve was checking the input data. That's because if you do this:
auto i = std::stoi("bla-bla");
you get an exception. So, I created a quick function which checks if the string contains data which can be converted to following types: bool, int, float, string (he-he), etc.
And if you input wrong stuff, you get a nice error message instead of program crash. :)
(http://i.imgur.com/TTxb2Zb.png)

I've also worked on the game itself (finally!). I connected meta stuff to main project and quickly thrown away old JSON loading code in favor of meta-deserialization! It worked pretty well. I'm now very glad that I did all that stuff instead of sticking to the easiest solution.
Now only animations use JSON but I'll start to convert most of the component data from Lua to JSON. What's interesting is that I can do it gradually (converting component data to JSON one by one), so I won't stop working on other stuff in meanwhile!

I've also came up with a bunch of cool ideas which will be easy to implement (mostly dialogues and cutscenes) and I won't spoil anything. Oh, and I'll soon start working on cutscene system, so expect some silly test cutscenes soon.

And by the way, I have question about reusing your own code in your projects. How do you do it?
Often I feel that I need to use LogManager, ResourceManager or Meta stuff in other quick/test projects and I end up just copying the code from main project so I don't break some stuff in it accidentally (by changing code shared among different projects). This approach is obviously not the right way to do stuff... So, what's your approach? Where do you store your code which you reuse in different projects? Do you just include them in all your projects or do you make shared libs?
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 30, 2015, 09:40:08 am
Quote
So, I created a quick function which checks if the string contains data which can be converted to following types: bool, int, float, string (he-he), etc.
I still don't get why you're writing all that stuff when QVariant can already do it.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 30, 2015, 03:08:31 pm
Quote
So, I created a quick function which checks if the string contains data which can be converted to following types: bool, int, float, string (he-he), etc.
I still don't get why you're writing all that stuff when QVariant can already do it.
That's because I have to handle types like sf::Int/FloatRect, sf::Vector2i/f, etc. (they're not stored inside QVariant! Only strings like "54, 20, 32, 32" are stored, so I need to manually convert them.)
 
And I also want to make meta stuff independent from Qt. If I use QVariant inside the Property class, I can't use this code inside my game which doesn't use Qt.
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on December 30, 2015, 06:03:33 pm
Good points ;)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 30, 2015, 10:06:48 pm
Nothing special, just repaired Lua callbacks and I think that this area looks neat with fog in it. :D (Though there are lots of tiles I' have to draw!)
(http://i.imgur.com/9o5dRqb.gif)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 31, 2015, 03:51:16 pm
I've written a big blog post about the stuff I've done this year. Lots of gifs, pictures and info. If you've followed this thread, you may have already seen this stuff, but it's always too look back and remember how much the game improved. :D
Read it here (https://eliasdaler.wordpress.com/2015/12/31/recreation-2015/)
(http://i.imgur.com/3eR8O5K.png)
Thanks again, everyone. And Happy New Year!
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on January 03, 2016, 10:29:50 pm
My short holiday rest is almost finished, I'll soon be resuming the development. ;D
I want to hear what you think of the progress I've made this year. (check the post above)
Title: Re:creation - a top down action adventure about undeads
Post by: Hapax on January 03, 2016, 11:44:24 pm
I had a look through it and it's as I remember it: impressive!  :D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on January 04, 2016, 09:17:15 am
I had a look through it and it's as I remember it: impressive!  :D
Thank you! :D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on January 05, 2016, 09:23:22 am
I'm back working on the game! Right now I'm working on moving entity data to JSON from Lua, but I've done it in such way that it can be loaded from Lua and JSON at the same time, so I won't need to provide Meta stuff for each component and the game will still work, so I'll work on the other stuff in parallel.
I'll also try to measure how faster the loading from JSON would be (I hope it would be faster, ha-ha!)
JSON will look like this:
(https://i.imgur.com/opYtN6l.png)

And a strange thing happened. I randomly visited daily discussion thread on /r/gamedev and came upon this post (https://np.reddit.com/r/gamedev/comments/3zdy6p/its_the_rgamedev_daily_random_discussion_thread/cyldjg8).
My first reaction was this:"Huh, someone posted a screenshot of my game...? Cool. Oh wait..."

Compare for yourselves.
(https://i.imgur.com/TEoUKae.png)
Right top corner part is my game with some color adjusted.

Generally I'm okay with people copying stuff from other people, but it should be subtle and you should add something to the original. I'm taking huge inspiration from Zelda, yeah, but it's not that obvious.
What will I do? Nothing. I've already called out the person on twitter and reddit and they said that they'll redo the graphics (while saying it's just a "coincidence").
Title: Re:creation - a top down action adventure about undeads
Post by: Hapax on January 05, 2016, 02:26:21 pm
It's possible that it really is a co-incidence. Creative people that have never seen each others' work come up with the same thing all the time.

Still, I don't buy it.

It's a shame they didn't post their character design  ;D

However, their version doesn't stick to the pixelation very well. The flowers, for example, are obviously scaled down from wherever they stole them from  ::)

On top of everything, though, the best part is that his Reddit account has been deleted.
Title: Re:creation - a top down action adventure about undeads
Post by: SpeCter on January 05, 2016, 02:51:28 pm
For me there is too much similarity to call that coincidence. Everything except for the lamps looks almost identical.

Quote
Actually, the project is inspired by A Link to the Past and Dark Souls. Thus the Zelda vibe combined with the darker and gloomier atmosphere.
Sure... I was really hoping to see one of "his" main gameplay mechanics. Let's make an elaborated guess: Taking over dead enemies/npcs to get their abilities?

Well, like hapax said his account is deleted, so we most probably won't see anything from him anytime soon.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on January 05, 2016, 11:10:41 pm
He-he, thanks for support, guys. :D

Okay, soon I'll start working on cutscenes. Imagine the following cutscene

We see a person sleeping and then old warrior goes near the bed and tells him to wake up. He gets up and asks:"What happened"?
This cutscene will look something like this in the Lua script:
sleepCutscene = function()
    local warrior = getEntityByTag("OLD_WARRIOR")
    local sleepyDude = getEntityByTag("SLEEPY_DUDE")
   
    cutscene = {
        init = function()
            sleepyDude:setAnimation("sleeping")
        end,
        {
            type = "WalkTo",
            f = function()
                warrior:setDestination(getEntityPosition("POINT_NEAR_BED"))
            end
        },
        {
            type = "Dialogue",
            f = function()
                warrior:sayTalk("WAKE_UP")
            end
        },
        {
            type = "Animation",
            f = function()
                sleepyDude:setAnimation("getting_up_from_bed")
            end
        },
        {
            type = "Dialogue",
            f = function()
                sleepyDude:sayTalk("WHAT_HAPPENED")
            end
        }
        ... // etc.
    }
   
    return cutscene
end

So, when cutscene is launched, init function is called, but then things get a bit difficult.
I can't just call functions one after another, because sometimes next action must wait until the current action is finished. So, there are two things each type of actions needs to have: functions which is called in the beginning and functions which will test if the current action is finished

Let's look at the actions and their finish conditions. (These will be hardcoded in C++, because they are very common)
1) "WalkTo" - wait until npc reaches destination
2) "Dialogue" - wait until the player reads all the lines of dialogue and presses *ACTION_BUTTON*
3) "Animation" - wait until the animation is finished
Etc.

There are a lot of other common actions which I'll add as I need them. I can also add a function which will be called repeatedly for the current action, so I can specify finishing conditions in scripts.

Any thoughts? Maybe I can do this better? :D
Title: Re:creation - a top down action adventure about undeads
Post by: dabbertorres on January 06, 2016, 03:28:16 am
Some sort of event/trigger system is the most reusable method I've seen for something like this.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on January 06, 2016, 07:22:32 am
Some sort of event/trigger system is the most reusable method I've seen for something like this.
Yeah, previously I've used event/trigger system to do cutscenes, but then I've realized that I have to do too much stuff and want to keep everything in one place. I had to subscribe to events, create lots of callback function, create lots of triggers on the map, etc.

But maybe I can do it automatically? So, when I'll write this:
{
            type = "Animation",
            f = function()
                sleepyDude:setAnimation("getting_up_from_bed")
            end
}
This action will subscribe to AnimationFinishedEvent
And when I do this:
{
    type = "WalkTo",
    f = function()
         warrior:setDestination(getEntityPosition("POINT_NEAR_BED"))
    end
}

I'll subscribe to the CollisionEvent between warrior and POINT_NEAR_BED. Notice that the POINT_NEAR_BED acts like a trigger in this case. I can't just hardcode variables, so I have to use trigger's position as a destination. (because then I'll forget to change them when the bed is moved, for example).

Previously all that trigger stuff was very confusing, because it was all over the place and you coudn't read cutscene from start to finish. So, it would be like this:

cutscene_near_bed_trigger = {
    TriggerComponent = {
        onTrigger = function(first, second)
            if(isCutscene("cutscene1")) then
                if(second:getName() == "old_warrior) then
                    ... -- do next stuff
                end
            end
        end,
        ...
    },
    ...
}

Keep in mind that this will be in a separate file, so you'd have to look at several files to see what's going on. Pure mess! So, I kinda like what I came up with.
Title: Re:creation - a top down action adventure about undeads
Post by: Mario on January 06, 2016, 10:46:42 pm
While this sounds like a good idea, you're somehow duplicating code/data.

In your example, your action type already is "Animation". Why would you have to call "setAnimation()" in addition?

Instead, this could be 100% data driven without code:

{
    type = 'Animation',
    target = 'sleepyDude',
    animation = 'getting_up_from_bed'
}

Or how about multiple actors doing the same?

{
    type = 'Animation',
    target = {'leftGuard', 'rightGuard'},
    animation = 'salute'
}

For more complex stuff:
{
    type = 'Serial', -- alternative 'Parallel'
    actions = {
        {
            type = 'Animation',
            target = 'leftGuard',
            animation = 'salute'
        },
        {
            type = 'Animation',
            target = 'rightGuard',
            animation = 'salute'
        },
    }
}

A "Serial" or "Parallel" action would only return/continue once all children have been completed.

Of course there could still be an action "script" or "complex", that would call actual code.

But also keep content creators in mind who might not be programmers. They might have a far easier time to toy around with data in a tree that's displayed in a treeview control or something similar (think of the trigger editors for Blizzard's RTS games, like StarCraft  (2)).
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on January 06, 2016, 11:24:47 pm
Yeah, I was just giving a simpler examples of functions which can be called. But sometimes you won't have enough of predefined actions. So custom functions for them will be useful.

I like your ideas, thanks! Animation actions can be also used like this:
{
    type = 'Animation',
    target = 'sleepyDude',
    animation = 'getting_up_from_bed',
    waitUntilAnimationFinish = true
}
So the next action can immediately begin after the animation is set or wait until the animation finishes depending on waitUntilAnimationFinish value.

Here's an example of a cutscene I've already done. This is very simple, and of course I could create "Print" action or something, but I'll just show the general principle.
local cutscene =  {
    {
        f = function()
            print("Hello")
        end
    },
    {
        type = CutsceneActionType.Delay,
        finishTime = 1000
    },
    {
        f = function()
            print("World")
        end
    },
}

This cutscene prints "Hello", then waits for one second and then prints "World".
I have Cutscene class which has vector of pointers to CutsceneAction
I inherit from CutsceneAction to create DelayCutsceneAction which works the same as other actions which follow this principle at the moment:
    1) Call currentAction's function
    2) If currentAction->isFinished() then we can move on to another action
    3) Else we update the currentAction, just passing delta time to its execute function

At this point it's easy to came up with idea how to implement DelayCutsceneAction, so I won't post its code here.

I think this explanation may be a bit too short for such complex topic and I think I'll write an article about it once I have more experience with it (once I create complex cutscenes some things will change for sure)

But also keep content creators in mind who might not be programmers. They might have a far easier time to toy around with data in a tree that's displayed in a treeview control or something similar (think of the trigger editors for Blizzard's RTS games, like StarCraft  (2)).

Good idea, maybe I'll make a GUI for cutscene editing at some point and then it will be easier to implement! :D
(And I also need to check out how cutscene creation works in Starcraft)
Title: Re:creation - a top down action adventure about undeads
Post by: ZackTheHuman on January 07, 2016, 07:17:55 pm
One thing that may be interesting to use for implementing cutscenes would be Behavior Trees. I just recently wrote a simple behavior tree implementation to control entity behavior, but the basic set of behavior tree components (Sequence, Selector, Repeat, etc.) could easily be used to do the kind of thing you're describing.

As to whether it's easier for content authors to write cutscenes using behavior trees is another story, but you could possibly carry over some of the ideas behind behavior trees and use them in your own way.

There are a few good articles about them on Gamasutra:

http://www.gamasutra.com/blogs/ChrisSimpson/20140717/221339/Behavior_trees_for_AI_How_they_work.php
http://gamasutra.com/blogs/BenWeber/20120308/165151/ABL_versus_Behavior_Trees.php

Another thing that could be interesting since you're using Lua would be to use coroutines to implement those "keep doing this until some condition is met" kind of things. Coroutines are an awesome feature of Lua, but you would have to wrap them up to make them nicer to use for content authors/modders.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on January 07, 2016, 09:57:20 pm
ZackTheHuman, thanks, I'll check the articles. Can't really talk about what I think about behavious trees for cutscenes at the moment, because I'm not experienced with them. :D


I wrote an article about global vs local variables in scripts. It only took me two years to realize the stuff I've been doing wrong ;D
https://eliasdaler.wordpress.com/2016/01/07/using-lua-with-c-in-practice-part4/
Title: Re:creation - a top down action adventure about undeads
Post by: FRex on January 07, 2016, 11:13:58 pm
There is a function in 5.1 called setfenv that you can use to set the global environment of a function so all global variables go into that table instead of going into the real global one. Here's an example:
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

int main(void)
{
    lua_State * L = luaL_newstate();
    lua_newtable(L);
    luaL_loadfile(L, "vars.lua");
    lua_pushvalue(L, -2);
    lua_setfenv(L, -2);
    lua_pcall(L, 0, 0, 0);

    lua_getfield(L, -1, "a");
    printf("a = %f\n", lua_tonumber(L, -1));
    lua_pop(L, 1);

    lua_getfield(L, -1, "a");
    printf("b = %f\n", lua_tonumber(L, -1));
    lua_pop(L, 1);

    lua_getfield(L, -1, "c");
    printf("c = %s\n", lua_tostring(L, -1));
    lua_pop(L, 1);

    lua_close(L);
    return 0;
}
a = 10
b = 20
c = "sto"
In 5.2 this function was removed and environment is upvalue _ENV or something like that instead.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on January 08, 2016, 07:45:11 am
That's good to know, thanks. But how is this better than using local tables?
Title: Re:creation - a top down action adventure about undeads
Post by: FRex on January 08, 2016, 02:26:35 pm
It's not better or worse, just a bit different and on about same level of complexity to do. I personally like it because it allows not having a table in the file and just writing 'variable = value' lines like in an .ini file or something. To me it's more intuitive without the local table. But there's nothing wrong with local tables.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on January 09, 2016, 08:27:16 am
I think it's a bit worse: you have to manage lifetime of stuff you load to this table. Yes, scoping problem is solved, but you have to keep track of variables you still need to have and ones you don't. If you load too many script files, your lua_State may become pretty big.

If you use local tables which are assigned to LuaRef, once the reference count for the table is 0, it's gone forever.
So, you can do something like this:
void loadData() {
    ... // load stuff
    auto ref = luabridge::LuaRef::fromStack(L, -1);
    ... // get data
    lua_settop(L, 0); // clean stack
} // ref is removed, so when you call garbage collector, local table will be removed
So, you can control Lua variables lifetimes just as you do with C++ unique/shared_ptr which is very good.

As for simplicity... You can do this:
local settings = {
a = 10,
b = 20,
c = "sto",
}

return settings
Not much different from .ini and easy to read and modify.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on January 10, 2016, 11:03:50 pm
I was making pickable items and remaking item menus and I decided to make something a bit silly
(http://i.imgur.com/d2nMzh1.gif)

Right now I'm working on a cutscene system and it's working pretty well. Here's an example of a simple cutscene. Nothing special, but I'm very glad to see the characters come into life. Now I need to draw some animations :D
(http://i.imgur.com/DNOfv8m.gif)

local cutscene =  {
    {
        type = ActionType.Dialogue,
        entityTag = "MASTER",
        talkTag = "GREETINGS"
    },
    {
        type = ActionType.GoTo,
        entityTag = "MASTER",
        destinationEntityTag = "BUTTON_BRIDGE_MASTER"
    },
    {
        type = ActionType.Event,
        eventType = EventType.TriggerEnteredEvent,
        subjectTag = "TRIGGER_CROSSED_BRIDGE"
    },
    {
        type = ActionType.GoTo,
        entityTag = "MASTER",
        destinationEntityTag = "TRIGGER_GO_TO_HOUSE"
    },
    {
        type = ActionType.Dialogue,
        entityTag = "MASTER",
        talkTag = "COME_IN"
    }
}
It's easy to read and modify which is great. I especially like "Event" action which waits until the particular event is triggered (in this example it's when the player walks across the bridge and collides with invisible trigger)
I'll continue to work on cutscenes (which are more like a scriptable events which will happen in-game and are very important!) and finally draw some new art.  :D
Title: Re:creation - a top down action adventure about undeads
Post by: Ironbell on January 14, 2016, 10:47:44 pm
That's pretty awesome and inspiring stuff you're developing here. I didn't manage yet to read this entire thread, but I'm impressed by what I've seen (I also took a glimpse into your dev blog :P).

I'm also developing a game at the moment but at the time when I thought it would be a good idea to have an Entity Component System, 30k lines of code were written and it was just.. nah. So I'm still using the straight forward, ugly, OO approach but I'll be sure to come back and look at your tutorials when starting my next game.

I also know what it feels to be a student that's developing a game and using nearly every free minute for it. And doing art AND code. Fortunately, I'm not a solo dev, I have a fellow student who's helping me with design decisions and sometimes even a bit programming and art  ;D. This is also what helps me staying motivated, having someone to talk and share, which is important when the project takes a long time (say, more than a year) to finish. So it's even more amazing that you are able to develop it entirely on your own.

I'll certainly be following your future progress and I'm quite excited about what it will be like to play when it's finished (supposed it will be finished at some time? You'll never know.)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on January 15, 2016, 11:12:38 pm
Thank you! I'm very glad that my progress inspires you!

It's hard to "get" ECS the first time you do it. It took me two or three times to get the design I've felt quite good (still, I think it's not the most efficient, but at least it works well :D)

And that's pretty cool to have something you work with. For me, my gf's support helps a lot (I talk a lot about the game with her). I also have a lot of stuff going on there, on reddit and on twitter, so people's feedback helps a lot too! :D

The game is surely being finished. Maybe it seems like I'm taking forever to make progress, but that's just because I didn't draw much art in the last months. It'll get faster, I promise :)
Title: Re:creation - a top down action adventure about undeads
Post by: SpeCter on January 16, 2016, 10:14:53 am
Well you did much groundwork and I think that your devspeed might skyrocket now :D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on January 18, 2016, 08:44:07 am
Well you did much groundwork and I think that your devspeed might skyrocket now :D
Yeah, it really seems so.

For example, I was able to do lots of stuff with Cutscene system I've made recently. It's more like "scripted sequence of events", not just for cutscenes. It would take me so long to make the same without it (I previously made short cutscenes with triggers all around the map and different callbacks between entities which was pretty painful).
I'll make cool cutscene soon and I'll be able to show it's full strength. :)

I've spend lots of time drawing stuff in axonometric perspective and giving more volume to stuff.
(http://i.imgur.com/wwyQfao.png)
Here's an old screenshot for comparison:
(http://i.imgur.com/9sOqc3Y.png)

You may notice that I made a lot of changes in Master's sprite. One big change was making it more 3d by using colors better (I'm still not very good at this, but at least the sprite doesn't look as flat as it did before!)
(http://i.imgur.com/IzCnOC7.png)

I don't have much time to work on the game now, because of the exams but they'll soon be over and I'll spend lots of time making the game. :)
Title: Re:creation - a top down action adventure about undeads
Post by: dwarfman78 on January 18, 2016, 09:19:47 am
Hi,

the hat's shadow is on a different side on the thumbnail !!!!  :'(

I prefer the old style bed, it goes better with the style of an old hermit master.

keep up with the good work !
Title: Re:creation - a top down action adventure about undeads
Post by: Ungod on January 19, 2016, 09:26:22 am
The new style looks much better and seems to be easier to draw too. There is actually a big improvement from old to new.

How do you did the shadow of the closet on the northern wall? They seem to fall out of the regular procedure.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on January 19, 2016, 04:36:42 pm
Hi,
the hat's shadow is on a different side on the thumbnail !!!!  :'(
I prefer the old style bed, it goes better with the style of an old hermit master.
keep up with the good work !
Yeah, I'll fix it :)
Old style bed fits better, but I how new one looks. Maybe I'll make another bed for Master and use this somewhere else.
And thanks, I will :D

The new style looks much better and seems to be easier to draw too. There is actually a big improvement from old to new.

How do you did the shadow of the closet on the northern wall? They seem to fall out of the regular procedure.
Thanks! Yeah, it's a lot easier to draw in this perspective. :)

This and other shadows which don't look like other shadows are drawn manually, since they look the best if I do this instead of relying on algorithm which only works for objects which cast their shadow on a flat surface.
Title: Re:creation - a top down action adventure about undeads
Post by: Hapax on January 19, 2016, 04:43:22 pm
I prefer the new projection but that's just a personal preference  :)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on January 20, 2016, 02:29:26 pm
I prefer the new projection but that's just a personal preference  :)
Thanks. :D

Today I've figured out a way to make multi-branch scripted sequences which will allow me to change stuff based on player's actions/dialogue responses in easy way. Details will come once I implement it and make a cutscene for you to enjoy. :)
Title: Re:creation - a top down action adventure about undeads
Post by: icecat on January 22, 2016, 10:00:20 pm
hey i tried to improve your straw hat guy:

(http://i.imgur.com/F7DwV7i.png?1)
- his hat seems less of a hat and more of a spike (http://i.imgur.com/yUbhAmz.png)
- the sword on his back doesn't really add much to his character so i just removed it
- notice the feet? thats because in most asian cultures its mandatory to take off your shoes when indoors so i took that into consideration

(http://i.imgur.com/Pw9sFlm.png)
- those 2 fire pillars should have shadows
- if this character still needs a sword, you could just make it walk towards the sword on the wall prehaps
- the dialogue says "show no empathy" but i think "show no mercy" would make more sense

anyway i attached my variation of the hat guy with this post. feel free to use it as you wish.
(might need to login to see attachments)
Title: Re:creation - a top down action adventure about undeads
Post by: Hapax on January 23, 2016, 01:18:17 am
hey i tried to improve your chinese hat guy
Unfortunately, your version looks like it is looking upwards, weirdly towards the high camera!

his hat seems less of a hat and more of a spike (http://i.imgur.com/yUbhAmz.png)
It seems to be correctly "pointed". However, it maybe should be wider and less high. For example:
(https://farm4.staticflickr.com/3036/2955093140_8a6a7a8bf4_z.jpg?zz=1)
(maybe not this big!)

the dialogue says "show no empathy" but i think "show no mercy" would make more sense
Technically, neither makes sense since the words relate to actual people but mercy does make more sense than empathy so I agree with you here.
Title: Re:creation - a top down action adventure about undeads
Post by: icecat on January 23, 2016, 06:42:21 am
Unfortunately, your version looks like it is looking upwards, weirdly towards the high camera!

It seems to be correctly "pointed". However, it maybe should be wider and less high.

(http://i.imgur.com/g2PiaRC.png?1)
- attempted to fix the camera angle
- added a slight cut on the hat to make it more interesting
- used the exact same colors for outline and mustashe that Elias used
- trimmed the arms to make him appear less intimidating and static
- hat got slightly bigger

(http://i.imgur.com/5a5BQEA.png)

attached the 2nd attempt of straw hat guy. feel free to use as you wish.
(login for attachments)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on January 23, 2016, 10:54:53 am
Thanks for feedback, guys.
I agree with Hapax, that icecat's version had wrong angle, but the last one is better. I'll take some notes into consideration when I try to improve the sprite again, but I won't do it exactly as you did, icecat. That's because I don't think that your interpretation fits my art style very well and the character looks a bit different from what I imagine him to be.

Meanwhile I've been redrawing stuff in Undead Cafe.
Here's how it looks now:
(http://i.imgur.com/n3eUCxD.png)
Old screenshot for comparison:
(http://i.imgur.com/6hqLHuZ.png)

It feels great to redraw characters with more shading and better use of colors. Stuff looks more polished and professional. And it has more depth.  ;D
(http://i.imgur.com/KU1Rd35.png)

My exams are almost over (The last one is on 25th). After that I'll rest a little and begin to work on a simple multi-branch cutscene which I'll show to you. (Multi-branch system already works well, I just need to make some art and animations for the cutscene)
Title: Re:creation - a top down action adventure about undeads
Post by: Hapax on January 23, 2016, 02:25:47 pm
Icecat, your new version looks better but you made the head bigger to match the hat and it looks wrong  :P

Elias, seeing your improvement in the cafe makes me wonder why we didn't notice how short the walls were before!
How did the cat get even cuter?  >:(
Title: Re:creation - a top down action adventure about undeads
Post by: SpeCter on January 23, 2016, 06:18:38 pm
I don't know why, but the cat is cuter eventhough I think it would be even cuter with the legs stretched like before.
Right now it looks more like a person.
The old one gave a "mew mew" feeling :D
Title: Re:creation - a top down action adventure about undeads
Post by: icecat on January 23, 2016, 06:55:20 pm
Icecat, your new version looks better but you made the head bigger to match the hat and it looks wrong  :P

(http://i.imgur.com/wMZEKC3.png?2)
- smaller head
- tried to mimic Elias's style for shading
- robe got curvier from the bottom

(http://i.imgur.com/cxArLjh.png?1)

attached attempt 3. feel free to use.
(login for attachments)
Title: Re:creation - a top down action adventure about undeads
Post by: Hapax on January 23, 2016, 07:03:00 pm
I don't know why, but the cat is cuter eventhough I think it would be even cuter with the legs stretched like before.
Right now it looks more like a person.
The old one gave a "mew mew" feeling :D
It's weird but now that I've seen the two together, the older one looks like it's stood on the table!
Title: Re:creation - a top down action adventure about undeads
Post by: icecat on January 23, 2016, 07:57:03 pm
Meanwhile I've been redrawing stuff in Undead Cafe.
Here's how it looks now:
(http://i.imgur.com/n3eUCxD.png)

i have some suggestions for the cafe:

(http://i.imgur.com/NwGjJNZ.png?1)
- give this guy an animation doing something casual like cleaning glasses

(http://i.imgur.com/Ev6H3vT.png?1)
- instead of square stools maybe you should have bar stools here (picture for reference below)
(http://i.imgur.com/Bw4A8vY.jpg?1)

(http://i.imgur.com/k03i3rs.jpg?2)(http://i.imgur.com/7kzvu7O.png?1)
- instead of pillars maybe use hanging lamps/lanterns for light?

(http://i.imgur.com/JHi8Kcj.png?1)(http://orig13.deviantart.net/3e72/f/2010/100/5/5/554857f7dbf6ffb18264957cfe033f60.png)
- maybe some jars/glasses/cups on the tables

(http://i.imgur.com/iBo5kmy.jpg?2)
- local sign, could maybe say "undead cafe" on it

(http://i.imgur.com/d3CPiHb.jpg?1)
- would be funny to see some cats waitering, highly unnecessary though
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on January 23, 2016, 10:14:19 pm
Elias, seeing your improvement in the cafe makes me wonder why we didn't notice how short the walls were before!
How did the cat get even cuter?  >:(
I think you didn't notice it, because when I've made the changes in perspective, the walls stayed at the same height. So you imagined that you looked at the old angle at them. But not long ago I've realized that if I make walls higher, the angle would fit the style and perspective better. And it worked! :D
And I think the cat got cuter because of longer ears and better head shape. :D

Specter, as for his pose, just imagine that he sits like this... it makes the whole thing better ;D
(http://www.zakstudio.com/wp-content/uploads/2013/06/chaton-gris-parquet-.jpg)

icecap, not to sound rude, but while some of your suggestions are good, I think that you're giving too many suggestions instead of feedback... I can't add that much stuff based on your vision of my game.
Title: Re:creation - a top down action adventure about undeads
Post by: icecat on January 23, 2016, 11:12:56 pm
I can't add that much stuff based on your vision of my game.

understood
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on January 30, 2016, 09:31:43 am
So, I'm done with the exams and I have more time to do stuff. I'm working on scripted sequences now. I've implemented multiple choice inside dialogs and tagged actions.
(http://i.imgur.com/yB0Hw90.gif)
Here's how this looks in Lua:
local cat = getEntityByTag("CAT")

local cutscene =  {
    {
        type = ActionType.Dialogue,
        dialogue = {
            {
                entity = cat,
                text = { "meow_meow_pop_quiz", "pop_quiz" },
                choices = {
                    {
                        text = "yes",
                        f = function()
                            cutsceneGoTo("ANSWERED_YES")
                        end
                    },
                    {
                        text = "no",
                        f = function()
                            cutsceneGoTo("ANSWERED_NO")
                        end
                    }
                }
            }
        }
    },
    {
        tag = "ANSWERED_YES",
        type = ActionType.Dialogue,
        dialogue = {
            {
                entity = cat,
                text = { "incorrect" },
            }
        }
    },
    {
        tag = "ANSWERED_NO",
        type = ActionType.Dialogue,
        dialogue = {
            {
                entity = cat,
                text = { "i_thought_you_would" },
                portraitName = "sad"
            },
            {
                entity = cat,
                text = { "silly_me" },
                portraitName = "shrug"
            }
        }
    }
}

return cutscene
Pretty easy to follow, but maybe there's some stuff I can improve? :D
As you can see, some actions are tagged, and I can go to them with cutsceneGoTo function. There's a lot more I can do with this stuff and I'll make another, more complex cutscene to show it off soon!
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on January 31, 2016, 04:33:28 pm
Made a quick and easy system to draw overlays on sprites which let me minimize copy-paste between human and zombie sprite sheets. Previously I had to make human sprite sheet and then copy-paste it and redraw face, hair and hands. This was obviously a pretty silly thing to do.
But now I do things a lot better. I have separate sprite sheets for body and face + hair + hands and just draw one sprite on top of another. So, I get something like this:

(http://i.imgur.com/TdmknN0.png)

(http://i.imgur.com/zP59uzw.png)

Right now face, hair and arms are at the same positions in sprite sheet as they are in original one, so I set same textureRect for both main and overlay sprite without having to deal with different coordinates. I don't waste much space by having huge empty spaces in .png.

This will also allow me to make different faces for NPC with same bodies to make reusing art easier!

My plans for the next week is to work on the battle system, puzzles and awesome boss battle which I won't spoil for you. :D
Title: Re:creation - a top down action adventure about undeads
Post by: ZackTheHuman on January 31, 2016, 07:53:15 pm
Looks really good. Reminds me of how the sprites in Mega Man worked. I'd love to hear more about how you specify this kind of layering/compositing in your data files. I want to do something similar in the game I'm working on.

I don't waste much space by having huge empty spaces in .png.

Nitpick: this is true for the .png file on disk, but not really true once the image is in memory.
Title: Re:creation - a top down action adventure about undeads
Post by: Hapax on February 01, 2016, 12:21:12 am
"InferXX"
"Can you fill in the blanks?"
(Yes/No)
"No"
"I thought you would help."

Made me laugh although sad cat's face also made me sad.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on February 02, 2016, 08:39:04 am
Looks really good. Reminds me of how the sprites in Mega Man worked. I'd love to hear more about how you specify this kind of layering/compositing in your data files. I want to do something similar in the game I'm working on.
Right now it's pretty simple, I just have this table in Lua:
overlays = {
    default  = "res/images/enemy_human_skin.jpg",
    zombie = "res/imaged/enemey_human_zombie_skin.jpg"
}
And overlay textures are stored in std::map<std::string, sf::Texture*>. So I can easily do this:
entity->get<GraphicsComponent>()->setOverlay("zombie");
so the "zombie" texture gets set to sf::Sprite overlaySprite and it's drawn on top of main sprite.

Nitpick: this is true for the .png file on disk, but not really true once the image is in memory.
Yeah, that's true. But after all the size if not the main issue, because the sprites are really small. Not having to copy-paste stuff is what makes it cool (because if I change some stuff in "human" sprite, I could have forgotten to change it in "zombie" sprite. But that's not a problem anymore)

Made me laugh although sad cat's face also made me sad.
Ha-ha, this is now one of my favorite comments about my game of all time. I want to make the game which will be called "roller coaster of emotions". ;D

Btw, I'm currently working on the first boss which will be much cooler than I've thought before and fit "prison" theme better. I'll fully redesign him later and make a lot of changes to boss battle. I'll probably show as much as possible because I don't want to spoil anything for you. :D
This boss is very complex and has a lot of different states and reactions to the stuff you do. It would have been pretty hard to make it with script state machines, so cutscene/scripted sequence helps a lot. It becomes more and more complex and lets me do stuff I never imagined to do before. For example, now I can easily track how many times one or another action happened (for example, how many times someone said something to you), so I can make NPCs react in another way if you do something twice. That's pretty cool, but also very hard to make good. So I'm trying out different approaches and maybe I'll write an article about that later.

So, I have a question: what are some good editors in games (AAA or not, doesn't matter) which let you do cutscenes in games? It would be pretty good to see how other games do it.
Title: Re:creation - a top down action adventure about undeads
Post by: Dark2Dragon on February 02, 2016, 12:50:41 pm
Quote
Btw, I'm currently working on the first boss which will be much cooler than I've thought before and fit "prison" theme better. I'll fully redesign him later and make a lot of changes to boss battle. I'll probably show as much as possible because I don't want to spoil anything for you. :D
This boss is very complex and has a lot of different states and reactions to the stuff you do. It would have been pretty hard to make it with script state machines, so cutscene/scripted sequence helps a lot. It becomes more and more complex and lets me do stuff I never imagined to do before. For example, now I can easily track how many times one or another action happened (for example, how many times someone said something to you), so I can make NPCs react in another way if you do something twice. That's pretty cool, but also very hard to make good. So I'm trying out different approaches and maybe I'll write an article about that later.
I hope you doesn´t make it too complex - because then i think u can´t finish this game (alone).
You make it better and better, but not only the engine have to run, also the story must be implemented.
Your work and this game is really great, but it would be a shame when it never comes out.  :'(
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on February 03, 2016, 08:51:57 am
I hope you doesn´t make it too complex - because then i think u can´t finish this game (alone).
You make it better and better, but not only the engine have to run, also the story must be implemented.
Your work and this game is really great, but it would be a shame when it never comes out.  :'(
Thank you! I completely understand your concerns. I'll try not to make it all overly complex, I don't want to make simple game, but it won't be a game with 10+ hours of gameplay with tons of NPCs (I plan to have something like 6-8 hours). The engine work is almost done and it feels really great. I've spend only 2 days making a boss behaviour which would take me like a week before. This will be even faster in the future, because these two days weren't just about scripts, I had to add some stuff to script system which was missing. But as I add these features, I need to do it less and less.
I've yet to learn how to develop faster and be more pragmatic, but I think I'm getting better at that. :D

Just a quick note: I now realize even more stuff which script sequence system help me to solve and it leads to removal of lots of C++ code and less hardcoding. Feels really great. :D

I've also made CameraGoToAction which lets me scroll camera to specified entity. This works pretty funny: I create an invisible entity which camera follows just as it follows the player. Then I add AIComponent to it and set AISeekState which sets entity to go to another entity. But because the first entity is invisible, it looks like camera scrolls to the entity I specified.
This is a cool example of reusing my code without simple copy-paste. :D
Title: Re:creation - a top down action adventure about undeads
Post by: Ungod on February 03, 2016, 11:21:55 pm
How is the boss-progress going? Would like to see some gameplay. :)

Do you currently work full-time on your game?
Title: Re:creation - a top down action adventure about undeads
Post by: etiennebp on February 04, 2016, 05:25:35 am
Just wanted to say that I'm looking forward to playing this game. What you got going on is really cool and it has inspired me to build my own ECS engine. Cheers!
Title: Re:creation - a top down action adventure about undeads
Post by: Tukimitzu on February 05, 2016, 06:36:03 am
Hey, dude, nice work!

I also share your love for ECS. And it's interesting to see a implementation different from mine.
I have 2 questions about your implementation:

1) Do you have/need communication between systems?

2) How do you handle events?

Thanks!
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on February 05, 2016, 09:13:01 am
How is the boss-progress going? Would like to see some gameplay. :)

Do you currently work full-time on your game?
The boss development is doing great. I'm almost finished with it, just need to redraw everything, make some more states for the battle and make sure that the battle doesn't have bugs in it.
As for gameplay: I won't show boss battle to not spoil it. But I plan to make some new puzzles soon which I'll show (and also I'll maybe show improved battle system when I'll make it)

I don't work full-time on the game, because I have to do some other stuff (study math, read, spend time with family, etc.), but I'm getting much more time to work on the game than I normally do which is great.

Just wanted to say that I'm looking forward to playing this game. What you got going on is really cool and it has inspired me to build my own ECS engine. Cheers!
Thank you! Glad that it inspires you. This is turn inspires me. :)

Hey, dude, nice work!

I also share your love for ECS. And it's interesting to see a implementation different from mine.
I have 2 questions about your implementation:

1) Do you have/need communication between systems?

2) How do you handle events?

Thanks!
Thanks!

1) Yeah, I have some communication between them, but it's pretty minimal and is done with events. So, systems just send events to which everything (including other systems) may subscribe to and then handle as needed.

2) There's some info here: http://en.sfml-dev.org/forums/index.php?topic=18062.msg139016#msg139016
But feel free to ask more questions if you feel that this is not enough to see the whole picture. :)
Title: Re:creation - a top down action adventure about undeads
Post by: Ungod on February 05, 2016, 10:45:12 am
Its your decision, but many games chose a boss to include it in teaser-gameplay (e.g. see Dark Souls 3).

I don't want to make simple game, but it won't be a game with 10+ hours of gameplay with tons of NPCs (I plan to have something like 6-8 hours).

Just wondering about that. While 6-8 sounds enough for a 1-man-game, i would say that the time to create gameplay content (if the required tools are developed), is small in proportion to the overall dev-time. Your data-driven-philosophy should go hand in hand with that anyway.

You seem to be at a point in dev where you might want to plan the next years instead of a few month so how are your future plans? I could imagine some kind of episode-format?
Title: Re:creation - a top down action adventure about undeads
Post by: Tukimitzu on February 05, 2016, 05:30:45 pm
1) Yeah, I have some communication between them, but it's pretty minimal and is done with events. So, systems just send events to which everything (including other systems) may subscribe to and then handle as needed.

2) There's some info here: http://en.sfml-dev.org/forums/index.php?topic=18062.msg139016#msg139016
But feel free to ask more questions if you feel that this is not enough to see the whole picture. :)

I see, the communication between my systems happens through events as well. As you said, it is minimal, but don't you think it is a big deal? I sure do. Maybe it's because I'm working on a turn-based strategy game, where events are essential.

I have another question, I don't know if you talked about it already somewhere: how about GUI? Are buttons and other GUI elements Entities as well?
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on February 06, 2016, 09:15:19 am
Its your decision, but many games chose a boss to include it in teaser-gameplay (e.g. see Dark Souls 3).
Dark Souls has much more stuff than my game, so showing off one or two bosses out of 20-30 is not that big deal.  :)

Just wondering about that. While 6-8 sounds enough for a 1-man-game, i would say that the time to create gameplay content (if the required tools are developed), is small in proportion to the overall dev-time. Your data-driven-philosophy should go hand in hand with that anyway.

You seem to be at a point in dev where you might want to plan the next years instead of a few month so how are your future plans? I could imagine some kind of episode-format?
I currently focus on making a demo which will later show me what stuff I need to focus on. Feedback from people would be very useful and then I'll continue to work on the rest of the game.
The scope of the game is almost defined and I see how much stuff I want to make but it's hard to plan how much it would take me to do it. Cutscene system, for example, saved me a great bunch of time already. Who knows how much time I can save in the future by making new tools and systems.
So, my main plan is simple for now: fully playable demo with 30min-1hour of gameplay.
As for episode-format... No. The game should be fully complete and I won't make it early access before launch.

I see, the communication between my systems happens through events as well. As you said, it is minimal, but don't you think it is a big deal? I sure do. Maybe it's because I'm working on a turn-based strategy game, where events are essential.
The less communication there is between the systems, the better it is for you game, I think. You get less coupling and less dependencies between systems. They each do some stuff and don't share much information between each other.

I have another question, I don't know if you talked about it already somewhere: how about GUI? Are buttons and other GUI elements Entities as well?
GUI elements are not entities, they have their own classes (but I don't have much GUI, but your game may have classes like Button, ScrollBar, etc. Or you can use some SFML GUI libraries instead of writing your own) and right now they're had coded but I'll later store their properties in Lua.
Entities are objects in the game world. Using ECS doesn't mean that everything should be an entity. :)
Title: Re:creation - a top down action adventure about undeads
Post by: SpeCter on February 06, 2016, 03:22:36 pm
Quote
Thank you! Glad that it inspires you. This is turn inspires me. :)
Seeing encouraging posts about your game fills you with Determination.

Sorry could not resist :D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on February 10, 2016, 09:19:47 am
Quote
Thank you! Glad that it inspires you. This is turn inspires me. :)
Seeing encouraging posts about your game fills you with Determination.

Sorry could not resist :D
Ha-ha, that's right! :D

Okay, some progress update.
I'm determined to finish the demo's prototype by the end of the month or a bit later. I won't post much screenshots, because it will be a raw prototype which means shitty graphics, shitty dialogue and some bugs. But this just gets stuff moving faster which I've realized when I made pretty cool boss battle in just 3 days.
How long will I polish what I do? I have no idea.  8)

Scripted action sequence (previously cutscene system) goes pretty well and I'm adding new stuff I can do with it.
Sorry for broken tiles/stuff, this is just a test level!
(http://i.imgur.com/jsaCz3U.gif)

It's not even a sequence anymore, as I can go from any action to another depending on some conditions. So, it's more like a state machine now.

For example, I made a script named house_enter.lua which scripts door behaviour and stuff when you enter the house.
Here it is: http://pastebin.com/GMcqUQwE

First of all, it has a function named makeCutscene which returns array of actions which are then later used to make a C++ vector of Actions which are then executed mostly in C++, but they also call to Lua functions (for example, f function defined in lots of actions in the script)
It could have been just a vector of references to Lua functions, but some tasks are pretty complex, so I've made some shortcuts for myself which are coded in C++.

I can pass table named args to cutscene, which is used to get different parameters.
For example, when I call door's interact function, it looks like this:
interact = function(this) -- "this" is a LuaEntityHandle of door entity
    playCutscene("house_enter",  { door = this, key = "GOLDEN_KEY" } )
end
So I can later get stuff which I need like this:
local door = args.door
Some actions have tags, so I can go to them by calling goTo function.
Actions which have nextTag property are calling goTo(nextTag) after they're finished. "EXIT_REQUEST_TAG" is a special tag which just stops cutscene from playing.
When I go to the "ENTER" action, following actions don't have tags, so they're executed one after another.

(I'm also thinking about how to do State machines in Lua better and I'll write some stuff about it later when I test some things. I'll also most likely use Behavior Trees for AI, because they're awesome, though this will be the first time I implement them and I'll try to make them data-driven, of course.)

So, that's how it works. What do you think about this system? Any stuff I can improve? :D
Title: Re:creation - a top down action adventure about undeads
Post by: Jabberwocky on February 10, 2016, 01:39:00 pm
I won't comment on the lua scripting system, I've not much experience with it since I don't use one myself.  But the game looks to be coming along really nicely, Elias!  Agreed, setting some milestones for yourself (the demo) is a great idea.  Sometimes we programmers like to disappear down rabbit holes for a long time without such milestones.  ;)
Title: Re:creation - a top down action adventure about undeads
Post by: Mörkö on February 10, 2016, 02:54:47 pm
Hi.

As I understand you are using an entity component system in your engine right? Could you please summarize how it works, just the broad strokes, most important aspects, etc. What I'm mostly interested in is, for example, does the components have logic or just data? Is there a container `entity` object or are they just connected by ID? How is message passing done? Things like that.

I'm interested in this because I'm currently considering trying ecs for an engine I'm planning, so I'm gathering data on successful implementations of the concept. I could read the whole thread instead of asking but it's very long and thus difficult to get a good overview ^^ thanks.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on February 11, 2016, 05:29:31 am
I won't comment on the lua scripting system, I've not much experience with it since I don't use one myself.  But the game looks to be coming along really nicely, Elias!  Agreed, setting some milestones for yourself (the demo) is a great idea.  Sometimes we programmers like to disappear down rabbit holes for a long time without such milestones.  ;)
But how does the script itself look? I think it looks pretty readable even if you have almost no experience with Lua :D
And thanks for support :)

Hi.

As I understand you are using an entity component system in your engine right? Could you please summarize how it works, just the broad strokes, most important aspects, etc. What I'm mostly interested in is, for example, does the components have logic or just data? Is there a container `entity` object or are they just connected by ID? How is message passing done? Things like that.

I'm interested in this because I'm currently considering trying ecs for an engine I'm planning, so I'm gathering data on successful implementations of the concept. I could read the whole thread instead of asking but it's very long and thus difficult to get a good overview ^^ thanks.
Hello. :D
There' some stuff about my view of ECS here (http://en.sfml-dev.org/forums/index.php?topic=18062.msg129804#msg129804).
Stuff about Event handling is here (http://en.sfml-dev.org/forums/index.php?topic=18062.msg139016#msg139016).
You can also check out my Using Lua with C++ series (https://eliasdaler.wordpress.com/2015/08/10/using-lua-and-cpp-in-practice/) which show how I implement stuff (though it's simplified there, of  course).
Title: Re:creation - a top down action adventure about undeads
Post by: grok on February 11, 2016, 07:17:49 am
Hi there.
I've been following this topic for a long time. What I can say - you do an amazing job!

One question regarding ECS engine - how  do you process, say 'GraphicsComponents' in the specified order?
For example, let's suppose we have tilemap (i.e. the 'background' layer), then we have HUDS tilemap on top of that, and finally we have our entities like main hero, enemies, whatever. Obviously, during the render we must process them in the specified order: 1) tilemap; 2) HUDS tilemap; 3) enemies and main hero.

Or, suppose, we need to render GUI elements on top of all rendered stuff.

If we just say to our Render system: "hey, take all graphics components and draw them", it will be a mess.

How do you do that? Thank you.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on February 12, 2016, 05:48:32 pm
Hi there.
I've been following this topic for a long time. What I can say - you do an amazing job!
Hello! Thank you :)

One question regarding ECS engine - how  do you process, say 'GraphicsComponents' in the specified order?
For example, let's suppose we have tilemap (i.e. the 'background' layer), then we have HUDS tilemap on top of that, and finally we have our entities like main hero, enemies, whatever. Obviously, during the render we must process them in the specified order: 1) tilemap; 2) HUDS tilemap; 3) enemies and main hero.

Or, suppose, we need to render GUI elements on top of all rendered stuff.

If we just say to our Render system: "hey, take all graphics components and draw them", it will be a mess.

How do you do that? Thank you.
I have two GameStates in stack of states, so PlayingState calls renderingSystem.process() (which draws tilemap and entities) and GUIPlayingState calls state->draw() which just draws stuff on top of everything. That's all there it to it. :)
ECS doesn't mean that everything has to be part of ECS system. GUI is separate, but still can access events and info from entities. But it's drawing is fully separate and I'm okay with that. :D
Title: Re:creation - a top down action adventure about undeads
Post by: totoo on February 24, 2016, 05:27:29 pm
hi Elias ! first of all I'd say what you made till now is great, just keep going, can't wait to play your game!

Actually I'm making my own game too (what a surprise!), and reading yours made me want to use Lua too for scripting. So I'm currently reading your articles in order to learn (which are great btw), and I found a better way than yours to get a table keys (https://eliasdaler.wordpress.com/2013/10/20/lua_and_cpp_pt2/), I don't know if you still use the same code but on your article you're making a string which contains lua code to execute it in a C++ program... definitely not the best way   ;)

So there's mine:

std::vector<std::string> LuaScript::getTableKeys(const std::string& tableName)
{
    std::vector<std::string> strings;

    if(!lua_gettostack(tableName)){
        return strings;
    }

    for(lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)){
        strings.push_back(lua_tostring(L, -2));
    }

    cleanStack();
    return strings;
}

In fact, when using lua_next(), the value is located at the bottom of the stack, whereas the key is located one upper. So getting the value of the key is as easy as that.
Title: Re:creation - a top down action adventure about undeads
Post by: FRex on February 24, 2016, 06:25:19 pm
You might accidentally call lua_tostring on a non string key, which will break lua_next.
Quote
While traversing a table, do not call lua_tolstring directly on a key, unless you know that the key is actually a string. Recall that lua_tolstring may change the value at the given index; this confuses the next call to lua_next.
Title: Re:creation - a top down action adventure about undeads
Post by: totoo on February 24, 2016, 07:43:04 pm
indeed, but in my case (and in his too I guess) the keys I'll catch like this will always have no space, or if there are, I simply need to add brackets and double quotes. If the name has no spaces then it is automatically converted into a string, for example:

player = {
        AnimationComponent = {
               
                animations = {
                        idle = {
                       
                        },
                       
                        moving = {
                       
                        },
                       
                        attacking = {
                       
                        }
                }
        }
}
 

if I catch the keys of the animations table, like this:

std::vector<std::string> vec = script.getTableKeys("player.AnimationComponent.animations");

for(unsigned int i = 0; i != vec.size(); ++i){
    std::cout << vec[i] << std::endl;;
}

this will output this:
idle
moving
attacking
(the order is variable but it does not matter)

and if you want to use spaces in your key name :

player = {

        AnimationComponent = {
               
                animations = {
                        ["moving right"] = {
                       
                        }
                }      
        }
}
 

this will output the correct name, with the spaces  ;)
Title: Re:creation - a top down action adventure about undeads
Post by: FRex on February 24, 2016, 09:44:24 pm
If there is a number in one of the tables then it'll raise an error. If that error is not in a protected environment (pcall) then it'll call the default panic function and call abort.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on February 24, 2016, 10:34:44 pm
Hello, totoo
Thanks for you kind words. Really appreciate that.
I recently wrote an article about the problem. Here: https://eliasdaler.wordpress.com/2016/02/16/using-lua-with-c-iterating-over-lua-tables/
So, it's almost the same as getting all keys in table. But it does more, it gets keys and puts values in LuaRef's which is a lot better, because then you can easily iterate over the table just as you would do in Lua with pairs function! That's because most of the time you don't need a list of keys, you need values too. So this function proves to be pretty useful.
As for the non-string keys... My function checks if the key is string, so there's no problems with that. Most of the time I don't care about non-string keys.

Progress update?
It's been a while since I've posted anything new. So you might be thinking that there's not much to write about. But this is false, I'm working very hard on the game and it's actually what I do most of the time for the last few weeks.
It feels like a completion of the base engine so I can focus more on the content once it's done.
I've done a lot of stuff and there are some pretty neat stuff I want to show and I'll do it as soon as I can!
Don't expect new amazing screenshots and gifs, though (sorry). Some of the coolest stuff I've done is pretty spoiler-heavy and isn't polish because I started to prototype a lot of stuff because making shitty art and doing gameplay stuff makes progress go a lot faster than usual.

One awesome thing I want to share right now is this:
I'm porting a lot of code to Lua. This goes quite well because it makes things faster (Calling Lua from C++ is expensive! More about this later), it make my code easier to modify and expand and it makes me write less code. I feel like I'm changing my philosophy about Lua scripting. :D
For example, I rewrote entity state machine in Lua yesterday. -387 lines of C++. +95 lines of Lua. :D
Once I finish some of the stuff I've already started, I'll share a lot of details and hopefully it will inspire other devs and some will help me improve my design.
Title: Re:creation - a top down action adventure about undeads
Post by: totoo on February 26, 2016, 03:18:01 pm
great!
as you're becoming a Lua pro, I'd like to ask you something. as I said previously I'm currently implementing Lua Scripting, what I made till now is being able to build an entity template with its components from the lua script, that works great. but what I want to do now is calling C++ functions from Lua. I read a lot about registering functions, I've made it work (in both senses) but, there's something I'm thinking about.
in every Lua function found in any script, we must be able to do everything that is possible (get the current animation frame, get the current speed, get the health... everything) so lots of functions have to be registered. But the thing is, everytime we open a new script file, everything about the previous one is deleted, including the registered functions.
Is there any way not to need to register every function (registered with lua_pushcfunction() and lua_setglobal()) each time I open a new script file ? (I'm not using LuaBridge or anything else and I'd like not to for the moment)

thanks.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on February 26, 2016, 09:52:50 pm
You should just use the same Lua state for everything. This way you register all the functions once and then load as many script files as you want. Don't forget to check out this article: https://eliasdaler.wordpress.com/2016/01/07/using-lua-with-c-in-practice-part4/

Btw, feel free to ask me any questions about all the programming stuff by sending me emails: eliasdaler@yandex.ru or posting questions on my blog.
This is a dev log about the game in the first place, so I don't want it to be filled with questions which have no relation to the game or it's engine. People interested in the game would find it pretty hard to navigate in the thread.
Title: Re:creation - a top down action adventure about undeads
Post by: jamesL on March 06, 2016, 04:45:41 am
just saw somebody streaming a game called
Stardew Valley 

and it reminded me of the game in this thread

here is Stardew Valley 
go here and watch the video from 1:58 to about 2:25
http://store.steampowered.com/app/413150/

Title: Re:creation - a top down action adventure about undeads
Post by: SpeCter on March 06, 2016, 12:23:03 pm
Stardew Valley is a completely different game ???
Title: Re:creation - a top down action adventure about undeads
Post by: jamesL on March 06, 2016, 09:00:32 pm
Stardew Valley is a completely different game ???

duh, obviously

but the video portion I mentioned made me think of the screenshorts posted on page 33
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on March 06, 2016, 09:28:58 pm
Well, to be fair, the only similarities I see is the same perspective and some colors... But that's a bit of a stretch :)

New dev log. January-February 2016.
Here's a new dev log (https://eliasdaler.wordpress.com/2016/03/06/recreation-dev-log-january-february-2016/)! It talks about the stuff that I did in the last two months.
Some of the stuff I've already posted there, but there's also new stuff!
Here's one of the new screenshots which I haven't posted before.
(http://i.imgur.com/sZAi57L.png)
I'm pretty satisfied about the progress in the last few months. It may not seem that big from the outside, but the changes and improvements I make are making my engine and game a lot better.
There's also a lot of unfinished / spoiler-y stuff I've yet to show.
What do you think about my progress? :D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on March 08, 2016, 09:13:01 am
I'm working on depth and height in the levels and the progress is great so far.
Check out how one of the sides of the platform is not seen when it reaches the lowest point.
(http://i.imgur.com/uN45czv.gif)
I've tested some of the stuff in lots of SNES top down games and it seems like they use the same method that I use: some tiles are just drawn on top of other tiles. The rules of this are not trivial, so I'll probably write an article about it later. More height updates soon!

Btw, here's an awesome chibi Renatus which my GF drawn. It's the first fan art for my game ever. So cool :D
(http://i.imgur.com/aPZ6ivb.jpg)

And I've just realized that I forgot to tell you that the protagonist has a name, Renatus! So, here it is :D
The name will be customizable for laughs.
Title: Re:creation - a top down action adventure about undeads
Post by: Rhimlock on March 08, 2016, 09:20:42 am
Really great project you have here.

I'm just wondering about your depth-rules.
Shouldn't it be enough for a top down 2d-game to sort the draw-order by Y-coordinate?
Things at the top get drawn before things at the bottom.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on March 08, 2016, 09:34:05 am
Thank you!

No, that's not enough. First of all, if you have flying objects or objects on the ground, you need to introduce z coordinate. Then you'll have to sort by Y and Z at the same time.
And this method only works for sprites, it's different for tiles. Especially considering that I draw tiles using VertexArrays and don't want to render each tile individually, so I have to keep "layers" of tiles which gets complicated pretty quickly. I'll explain more a bit later. :)
Title: Re:creation - a top down action adventure about undeads
Post by: Hapax on March 08, 2016, 04:49:09 pm
I'm working on depth and height in the levels and the progress is great so far.
Check out how one of the sides of the platform is not seen when it reaches the lowest point.
(click to show/hide)
Even though, technically, it's perfect, it doesn't actually look like that platform is lowering. It looks like it's sliding from one side of the gap to the other.
If it's lowering, it really should have some suggestions of that. Shadows (cast onto the platform and/or cast by the platform) are the best but possibly most complicated solutions. However, perceived occlusion (just darkening it as it's lower) can help. Darkening something makes it appear smaller, further away, more occulded and/or less-significant.

I love this project. It's really progressing and I like reading about it.
I don't think it would actually be the type of game that I would play but I'd love to have the entire story to read (along with images and the humour!) ;D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on March 08, 2016, 05:21:56 pm
Even though, technically, it's perfect, it doesn't actually look like that platform is lowering. It looks like it's sliding from one side of the gap to the other.
It's moving in Y axis, so yeah, it is sliding from on side of the gap to the other. I'll make it more explicit a bit later (by making the gap wider and drawing better vertical tiles).
Thanks for the suggestions, though! I'll totally have it in mind once I'll start implementing platforms which move up and down. :D

I love this project. It's really progressing and I like reading about it.
I don't think it would actually be the type of game that I would play but I'd love to have the entire story to read (along with images and the humour!) ;D
Thank you!
Well, maybe someone will make a playthrough or "story-only" video for you to enjoy. Though I'll go by the Earthbound route and put some funny stuff in random interactions and dialogue even with unsignificant NPCs :D

Progress update
And here's what I did with tiles... Now the height totally works! I'm very excited about it because I couldn't figure out the way to do this stuff for two days. And there weren't any articles which could help.
(http://i.imgur.com/ypgVCuN.gif)
I still need to add shadows to make it look more cool, but you get the idea. I'll also add jumping down (and falling!) later.
I'll also write an article about how to do this stuff. It's pretty complicated, so it's worth talking about it in depth. :)
Title: Re:creation - a top down action adventure about undeads
Post by: Hapax on March 08, 2016, 09:37:46 pm
It's moving in Y axis, so yeah, it is sliding from on side of the gap to the other. I'll make it more explicit a bit later (by making the gap wider and drawing better vertical tiles).
Oh, I'm sorry! The irony of me thinking that it did something but did not look like it because it looked like it did something that I thought that it did not look like!  :-X
So, it's travelling from one side of the gap to the other? What would it look like if it was lowering?  ;)

Progress update
That height stuff is a massive step. Good work!
Be aware, though, that obscuring the character is a bad thing. Displaying it through the obstructions (walls etc.) as a transparent or outlined "ghost" sprite is a common solution for this.
Title: Re:creation - a top down action adventure about undeads
Post by: Ethan.Calabria on March 09, 2016, 05:23:16 am
Looks pretty cool!  Some of your marketing efforts must be working too as I see screens of your game re-tweeted from time to time.

I didn't go through the entire thread, but I saw mostly questions / updates about the game mechanics / programming.  How is the story / writing progressing?
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on March 10, 2016, 07:56:20 am
Oh, I'm sorry! The irony of me thinking that it did something but did not look like it because it looked like it did something that I thought that it did not look like!  :-X
Ha-ha, no problem! I realize that this was kinda confused and I'll fix it

So, it's travelling from one side of the gap to the other? What would it look like if it was lowering?  ;)
I don't know, I'll try to make this effect soon and then I'll show it to you :)

That height stuff is a massive step. Good work!
Be aware, though, that obscuring the character is a bad thing. Displaying it through the obstructions (walls etc.) as a transparent or outlined "ghost" sprite is a common solution for this.
Thank you! Btw, the stuff in that gif was fake depth done with some overlays. But now I've made a system which will allow all tiles and entities to have true height as I've found how to draw them properly!
Be aware, though, that obscuring the character is a bad thing. Displaying it through the obstructions (walls etc.) as a transparent or outlined "ghost" sprite is a common solution for this.
Yeah, having an outline will certainly help, though some games are okay with player hinding behind walls and stuff... Well, I'll see, it's not that hard to implement with a simple shader. :D

Looks pretty cool!  Some of your marketing efforts must be working too as I see screens of your game re-tweeted from time to time.
Thank you. Glad to hear that. I didn't do marketing much though, only dev logs and gifs. Once the game is more playable, I'll focus on it more, I'll mail some journalists, make some videos, trailers, Steam Greenlight, etc.! :D

I didn't go through the entire thread, but I saw mostly questions / updates about the game mechanics / programming.  How is the story / writing progressing?
It's progressing quite great! The more I think about the story and characters, the more it makes sense to me. I want to make a connected world, not just a randomly connected sequence of events.
Lots of stuff I develop in the story now is pretty spoiler-y, so I don't talk about it. :D
Non spoiler stuff is not being made yet, because I'm making some stuff which will allow me to do cutscenes / dialogues pretty quickly. So far, the progress is pretty good in this direction. I can make dialogues and cutscenes pretty quickly. I'm also working on all stuff in the gameplay and the engine, so it takes a bit of time.

I plan to focus more on the story stuff a bit later, so maybe you'll see more details about it a bit later. :)
It's certainly richer and deeper than simple "humans fight undeads and they fight back" plot.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on March 10, 2016, 12:22:13 pm
3d stuff update! I can now make levels with height in my level editor!
(http://i.imgur.com/2GeanAx.gif)

The gif that was posted previously wasn't using "true" height, the height was emulated by drawing some tiles above everything with less Z. But now I've realized that I can make levels with "cubic" tiles, which kinda work like voxels. It makes collision detection and height stuff much easier.
I'll write about how drawing algorithm works a bit later, because there's so much more stuff I have yet to do and improve. Hopefully, it doesn't suck in the end. :)

(Btw, the tiles don't look very well without outlines and shadows and that's something I'll work on in the future)
Title: Re:creation - a top down action adventure about undeads
Post by: SpeCter on March 10, 2016, 02:04:44 pm
So basically your tiles have a real z-position now instead of emulating this behaviour with x/y offsets?

Looks pretty neat btw :D
Title: Re:creation - a top down action adventure about undeads
Post by: Hapax on March 10, 2016, 07:22:46 pm
Can your editor hide certain things? I'd suggest a modifiable height limit. If you build a wall like the one in your example above, you still might need to change the floor behind it that is obscured (or build a smaller wall behind it).

If you're feeling adventurous, the editor could now be fully 3D... hehe  ;D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on March 10, 2016, 10:28:50 pm
So basically your tiles have a real z-position now instead of emulating this behaviour with x/y offsets?
Yep. Not only tiles, but objects have real z position too!

Looks pretty neat btw :D
Thank you :)

Can your editor hide certain things? I'd suggest a modifiable height limit. If you build a wall like the one in your example above, you still might need to change the floor behind it that is obscured (or build a smaller wall behind it).
Not yet, but I think I'll add a feature which will let me see vertical slice of the level, so I can see each row individually. This may help. Not sure what's the best interface for it would be, though. I'll see.

If you're feeling adventurous, the editor could now be fully 3D... hehe  ;D
Hehe, I've thought about that. Too much work for little profit. I'll mostly make stuff which isn't obscured behind objects in front of them so 3d is not needed. (Because this will also be a poor level design as the player can't see what's behind the walls!)
Title: Re:creation - a top down action adventure about undeads
Post by: bitano on March 10, 2016, 10:40:31 pm
Hehe, I've thought about that. Too much work for little profit. I'll mostly make stuff which isn't obscured behind objects in front of them so 3d is not needed. (Because this will also be a poor level design as the player can't see what's behind the walls!)
You're flaming so many nintendo games here among which many super mario games (lol). Obscured places were the most rewarding ones! :D

Also: Nice work! The Z implementation looks awesome. Can you also go downwards, or does the level editor start from the base allowing you to only build upwards?
Title: Re:creation - a top down action adventure about undeads
Post by: Tukimitzu on March 10, 2016, 10:54:33 pm
(Because this will also be a poor level design as the player can't see what's behind the walls!)

I'm with you on that.
*caham* chrono trigger *coff coff*
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on March 11, 2016, 07:02:57 am
You're flaming so many nintendo games here among which many super mario games (lol). Obscured places were the most rewarding ones! :D
Ha-ha. Well, I think it's okay to have secrets in obscured places, but it's not a good idea to put stuff you can't see but have to interact with. :D

Also: Nice work! The Z implementation looks awesome. Can you also go downwards, or does the level editor start from the base allowing you to only build upwards?
Thank you! For now, it's limited to tiles with z = 0. But there's nothing preventing me from doing tiles with lesser z, so I'll make it. For example, I can build gaps like one I've showed previously where the platform was.

I'm with you on that.
*caham* chrono trigger *coff coff*
Ha-ha. Did Chrono Trigger really do this a lot? I don't remember such stuff here. :D
Title: Re:creation - a top down action adventure about undeads
Post by: bitano on March 11, 2016, 11:14:23 am
Ha-ha. Well, I think it's okay to have secrets in obscured places, but it's not a good idea to put stuff you can't see but have to interact with. :D
Very true! I was just messing :P

Thank you! For now, it's limited to tiles with z = 0. But there's nothing preventing me from doing tiles with lesser z, so I'll make it. For example, I can build gaps like one I've showed previously where the platform was.
That would be cool. Again obscuring areas would be tricky to prevent i suppose. Unless you make it so that higher Z objects are hidden / transparent when you move behind them (or hide the entire Z layer)...Tricky stuff.

Also i was wondering - How are you dealing with the drawing of higher structures which have a base outside the viewport? If the base tile (Z=0) is culled, isn't the entire structure above the base tile culled as well (Z=1/2/3/4/etc)?

I'm interested in this as i'm working on something somewhat similar.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on March 13, 2016, 08:51:22 pm
Thank you! For now, it's limited to tiles with z = 0. But there's nothing preventing me from doing tiles with lesser z, so I'll make it. For example, I can build gaps like one I've showed previously where the platform was.
That would be cool. Again obscuring areas would be tricky to prevent i suppose. Unless you make it so that higher Z objects are hidden / transparent when you move behind them (or hide the entire Z layer)...Tricky stuff.
I think that I'll just draw outline as Hapax suggested so there'll be no problems with this.

Also i was wondering - How are you dealing with the drawing of higher structures which have a base outside the viewport? If the base tile (Z=0) is culled, isn't the entire structure above the base tile culled as well (Z=1/2/3/4/etc)?
I have no idea how to solve this yet. For now all I can really think about is this: 1) find the biggest z on the map 2) Write z rows below just in case every time.
Yeah, really stupid, but this may do the job if you don't have much height variation (and when z is not very high!)

My drawing algorithm currently works like this:
prevZ = -100
(for each visible tile row) {
   (for each z in row's zs(height variation in row)) {
        draw sprites which lowest Y point is on the row and which have z between prevZ and current Z
        draw tiles with current Z
        prevZ = current Z
    }
}
This gives me correct Z order for everything.
The problem I currently have is that drawing tiles individually is quite slow and I can't really use VertexArray in this case it seems (unless I have VertexArray for each row and z... don't think it will help much). So, does anyone have any ideas how I can improve this?

And by the way, I've been checking out Dear Imgui (https://github.com/ocornut/imgui) which is a very nice immediate mode GUI library which lets me write GUIs for debugging and level editor very easily. I just started using it and implemented my old level editor interface in 1-2 hours! (And improved it a lot in the process, the old one didn't have as many cool things!)
(http://i.imgur.com/jDlAoQg.gif)
I'll write more about experiences with it later, but currently all I can say is this:
Here's all what I have to do to add working checkbox to the window:
ImGui::Checkbox("Show grid", &showGrid); // showGrid is bool
Isn't it cool? :D
Title: AW: Re:creation - a top down action adventure about undeads
Post by: eXpl0it3r on March 14, 2016, 08:10:53 am
Do you use your own Dear ImGui SFML integration?
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on March 14, 2016, 08:12:15 am
Do you use your own Dear ImGui SFML integration?
Nope, I use this one (https://github.com/Mischa-Alff/imgui-backends/tree/master/SFML) by Mischa Alff

bitano, I've created a thread about the problem, so maybe someone will come up with some ideas
http://en.sfml-dev.org/forums/index.php?topic=19971.0

(http://i.imgur.com/4IZROA6.png)
The explanation how I store maps may help everyone visualize everything. I don't just store heights, I store tile Ids for each "z" in the column though.
But still, is there any way to speed up this row by row drawing? Maybe I should still try to create VertexArrays for each row if it possible? (Sometimes it makes no sense, because tiles may have different tilesets or there may be just one or two tiles for given z...)

P.S. Unless there's a way to do proper z-ordering by drawing each "z" tile layer one by one which I can't figure out... :D
Title: Re:creation - a top down action adventure about undeads
Post by: bitano on March 14, 2016, 09:19:20 am
Woa! Thanks for the detailed answer and great idea to dedicate a thread to the issue. Let's see where that leads.
In the meantime, I'll do some puzzling myself :D

Also, that ImGUI looks good. I'm gonna have to borrow that as well. That saves so much work  :o
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on March 14, 2016, 07:13:43 pm
You're welcome!

Right now I'm having a problem of dealing with all this stuff. Can't decide which way is better, "flat" or "3d" one, so I want to discuss it with everyone. I don't really know about all SNES games, but it seems like most of them store tile data as in "flat" approach with some tiles being able to be written above everything. Do you think it's really so?
It seems like "3d" way has more disadvantages then advantages...
Title: Re:creation - a top down action adventure about undeads
Post by: bitano on March 14, 2016, 07:51:38 pm
Right now I'm having a problem of dealing with all this stuff. Can't decide which way is better, "flat" or "3d" one, so I want to discuss it with everyone. I don't really know about all SNES games, but it seems like most of them store tile data as in "flat" approach with some tiles being able to be written above everything. Do you think it's really so?
It seems like "3d" way has more disadvantages then advantages...
I share the dilemma :P. Personally i decided to work on a system that supports the Z index as i'm sure i'll miss it at some point if I don't (when designing creative encounters).

Unless they tricked it somehow, I think Zelda - a link to the past was in fact 3d, as you were able to move over and under bridges, etc (similar to your last demo GIF).
Having said that, from the top of my head i can't think of any situation where the 3D aspect added a whole lot to the player experience... Grrr i'm gonna have to watch a Zelda gameplay vid on youtube now to make sure :-)

[UPDATE]
Check the following example: https://www.youtube.com/watch?v=xf2IO7P5DVA&feature=youtu.be&t=3h15m16s (https://www.youtube.com/watch?v=xf2IO7P5DVA&feature=youtu.be&t=3h15m16s)
The next couple of rooms have some Z-layer mechanics. There are more rooms like this in Zelda where you see both an upper and a lower area that overlap, but most of the game seems pretty flat. I don't think leaving out the overlapping bits would've broken the game :P
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on March 14, 2016, 08:39:56 pm
Well, you see, you can have some sort of Z coordinate which will determine some stuff, like entities not seeing/colliding other entities if they have different Z coords or which entities should be drawn under some tiles and which ones should be drawn above the same tiles.
So, for example, suppose you have a bridge which is a bit higher than most of the ground. You can have it with Z = 1 and all entities on the ground will have Z = 0. So, only entities which have Z = 1 or higher will be drawn above the bridge, so you can be under or above the bridge.
The dilemma is: do I store bridge tiles like I do in "3d" version of tile map or in "flat" version... Uhhh... :D
Title: Re:creation - a top down action adventure about undeads
Post by: bitano on March 14, 2016, 09:06:19 pm
Well, you see, you can have some sort of Z coordinate which will determine some stuff, like entities not seeing/colliding other entities if they have different Z coords or which entities should be drawn under some tiles and which ones should be drawn above the same tiles.
Of course! A character-bound Z index. That makes sense as you always have to go up/down stairs (Z trigger object) to get onto an overlaying tile. So it's probably flat. But enough about Zelda!

The dilemma is: do I store bridge tiles like I do in "3d" version of tile map or in "flat" version... Uhhh... :D
Shouldn't you take a step back, look at what you want to achieve with the game and go from there? You started with a really cool idea and have a lot of functionality in place. You probably want/need to develop some more mechanics for interesting enemies and items. Possibly add level/world-altering effects. You'd have a storyline you want to implement. Would leaving out the 3D stuff in any way impair your game?

Looking at what you shared so far i'd think not, but my knowledge of your game / concept is very limited :D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on March 26, 2016, 03:33:07 pm
I'm back! I've done lots of studying stuff I had to do, so I'm mostly free again and I'm starting working on the game again.

I've managed to improve the graphics a lot for a last few weeks and I'll show a screenshot once I polish everything. It's a pretty big step forward!

Let's talk about tiles and 3/4 perspective though. This is a problem which haunted me for a long time...
As I've said previously, there are two ways I could store tile info:
(http://i.imgur.com/4IZROA6.png)
"3d" approach was the thing I've experimented with. I could set x, y and z coordinates for each tile to be able to handle different heights easily.
While the "3d" approach makes sense, it's pretty hard to work with, because it's very hard to place tiles and think about all the different heights. It totally makes sense in isometric games. 3/4? Not much.
My game isn't going to be very "height based" after all. 3/4 perspective is not very suitable for such gameplay.

There are number of things I want to discuss with everyone because there are lots of ways to manage height in 3/4 perspective and some downsides to a method I'm going to implement (maybe someone will give me some good ideas!)

Suppose I have a tile map like this:
(http://i.imgur.com/T5N7HYf.png)
It's possible to walk under the bridge and on the bridge. There can also be a situation like this:
(http://i.imgur.com/9s15MsY.png)
So, there's a need to establish proper drawing order of tiles and objects. Right now I can think of a simple solution: entities and tiles will have z coordinate. For example if the entity is standing on the grass, its z is 0 and if it's higher, it's z = 1 (or more).

Tiles in the red rectangle will have z = 1:
(http://i.imgur.com/Lk9ONVG.png)
Here's how renderer will draw stuff:
draw tiles with z = 0
draw entities with z = 0
draw tiles with z = 1
draw entities with z = 1
etc...

This is probably how most SNES games did it. Here's a screenshot from The Legend of Zelda: A Link to The Past where layers are clearly visible!
(http://i.imgur.com/2HD36Nn.png)

And this approach works okay in most of the cases... unless there are characters which are more than two tiles high (or some animations like the one on the previous screenshot).  They'll be drawn incorrectly, for example in situations like this:
(http://i.imgur.com/DKJopD1.png)
I don't have a solution to this problem and unless I came up with something, I'll just prevent these situations from happening by not placing entities at such places.

And now for collision. It may vary from one z level to another. For example, for entities which have z = 0 it'll look like this:
(http://i.imgur.com/EI0if8w.png)
(If tile is unmarked, it means that it's walkable, if it's marked by X, it means that tile is completely unwalkable)
When the player starts to climb the ladder, entity's z changes from 0 to 1 and another collision rules work for it, they look like this:
(http://i.imgur.com/umMhe9V.png)
Here arrows show directions in which entity can move while standing on the tile. Red lines show "walls" with which entity will collide, so it'll work as needed. (I've got this idea from various posts on RPG Maker forums, he-he)

So, maybe there are other ways to do similar stuff? Or is my way of doing things alright? What do you think? :D
Title: Re:creation - a top down action adventure about undeads
Post by: Tukimitzu on March 27, 2016, 05:07:28 am
Damn scarecrow, always causing trouble, so many places for it to be, but noo, slightly below the platform is the best spot.

Also, what if I want to jump from the second to the first floor with the character (while performing a double front flip, of course) and want the impact to cause an earthquake that destroys the platform I was on? I think you should handle this situation as well.

I hope you find my criticism helpful.

Cheers!  :)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on March 27, 2016, 09:40:02 am
Damn scarecrow, always causing trouble, so many places for it to be, but noo, slightly below the platform is the best spot.
Ha-ha :D

Also, what if I want to jump from the second to the first floor with the character (while performing a double front flip, of course) and want the impact to cause an earthquake that destroys the platform I was on? I think you should handle this situation as well.
I don't think I'll add jumping. It's pretty hard to implement and make levels having that in mind :)
Title: Re:creation - a top down action adventure about undeads
Post by: Hyden on March 27, 2016, 05:06:23 pm
Love the art style.
Title: Re:creation - a top down action adventure about undeads
Post by: bitano on March 27, 2016, 10:18:34 pm
Looking at your (once again thorough) explanation including visuals, I wanted to reply with something quite profound....but couldn't think of anything. Mainly because i'm thinking you've investigated quite a few options yourself and therefore are well-informed on the pros and cons of each existing method.

I don't think I'll add jumping. It's pretty hard to implement and make levels having that in mind :)
Just wanted to add the question: Does this mean you also don't want to add falling from platforms and/or hovering off of them (or from one to the other) in ghost form?

Also you mentioned preventing placement of entities larger than 2 tiles in those zones, but what if you have a scenario with a 3 tile high moving entity?
Maybe an entity / mob would have a tile-height to check against (and simply cannot move underneath when tile-height > Z)?

Keep up the good work! :D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on April 12, 2016, 11:56:25 am
Also you mentioned preventing placement of entities larger than 2 tiles in those zones, but what if you have a scenario with a 3 tile high moving entity?
Maybe an entity / mob would have a tile-height to check against (and simply cannot move underneath when tile-height > Z)?
I will just keep large entities (mostly bosses) in isolated areas, so they shouldn't be a problem. :)
The problem is not with collision, it's with drawing order, so I just have to prevent large entities from appearing near bridges and stuff like that.

Progress update
Studying continues...

Not a lot of time to work on the game, but I managed to work on level editor for some time and implement some cool stuff with ImGui:
(http://i.imgur.com/iQibpSk.gif)
There's a room for improvement, of course! For example, adding a small preview for each entity in Entity Creation tab.
I've also drawn some new cool stuff but I'll show it once everything is completed.

I've also made a repository (https://github.com/EliasD/imgui-sfml) which contains the code which I use for ImGui. The related discussion about it will be here:
http://en.sfml-dev.org/forums/index.php?topic=20137.0
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on May 07, 2016, 02:48:34 pm
I'm back again! While I was busy studying I've had some time devoted to the game and I'll have more of it in the next months, so the progress will be faster hopefully. :)

Here's the latest screenshot from the game!
(http://i.imgur.com/I2yn8X4.png)
As you can see, there are some new graphics there. Houses were previously just sprites, but now they're created out of tiles which makes creating new variations of houses much easier! Their proportions changed too.

I've also redrawn main character sprite which is more undead-y and has a lot more detail in it!
(http://i.imgur.com/XQTlPUD.png)
I've also worked on the level editor a lot. (click or zoom in to view in better resolution)
(http://i.imgur.com/2qM27HY.gif) (http://i.imgur.com/2qM27HY.gif)
Now I can add tile overlays which makes creating combinations of tiles easier and lets me greatly reduce the number of tiles in tilesets. This makes creating more interesting levels and changing/reusing graphics much easier!
I can also set z-levels for tiles now which determines drawing order (for example, if the tile has z = 1 then all entities with z less than 1 will be drawn below the tile).

One interesting change in code I've done was using std::stringstream to parse bitmap font config files (BMFont format) and level files which reduced loading times a lot (not like it was very high, hehe).  Previously I had a function which worked like this:
auto tokens = splitString("firstToken,secondToken,thirdToken", ',');
// returns std::vector<std::string> with "firstToken", "secondToken" and "thirdToken" in it
for(auto& token : tokens) {
   ... // do something
}
 
This function used stringstream internally but it was still much slower than this code:
std::stringstream ss(str);
std::string token;
while(std::getline(ss, token, ',')) {
    ... // do something
}
There were thousands of splitString calls during level/bitmap font loading, so replacing it with a better solution improved perfomance a lot.
Title: Re:creation - a top down action adventure about undeads
Post by: Mr_Blame on May 07, 2016, 09:04:24 pm
Very cool GUI!
Did you use premade lib or made one yourself?

EDIT:

Found it as your project, and I like it.
Title: Re:creation - a top down action adventure about undeads
Post by: FRex on May 07, 2016, 09:08:22 pm
It's ImGui:
https://github.com/EliasD/imgui-sfml
https://github.com/ocornut/imgui
Title: Re:creation - a top down action adventure about undeads
Post by: TheGuerilla on May 09, 2016, 01:30:19 am
Game looks pretty damn good. Any vague idea when a release will be availible?
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on May 09, 2016, 09:37:51 am
Mr_Blame, thanks!
TheGuerilla, thank you. To be fair, I don't have any idea about the release sadly. Hard to predict how much I'll be working in the next months and how much time some stuff is going to take. My aim for now is a demo which is still not near horizon sadly but I'll try to finish it this year.
Right now I have 2-4 hours per day to work on the game. This isn't much to be fair so even little things take a lot of time considering I have to do everything in those 2-4 hours: programming, art, level design, etc.
Title: Re:creation - a top down action adventure about undeads
Post by: Mr_Blame on May 09, 2016, 10:10:08 am
My aim for now is a demo which is still not near horizon sadly but I'll try to finish it this year.
Welp, will check this thread as rapidly as I can to not miss the demo release :)

EDIT:

Download you SFML version of imGui, this lib will definitely go to my SFML-app-making-lib-collection(or just SFMLamlc).
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on May 09, 2016, 09:55:06 pm
Implemented much better zoom in. This one responds to where the mouse points and is much smoother than the previous one (the previous one was jitterry because of rounding errors!)
This was made with the help from this tutorial (https://github.com/SFML/SFML/wiki/Source:-Zoom-View-At-(specified-pixel)) by Hapax!
(http://i.imgur.com/yE5lKzX.gif)

As I made some work with sf::Views I've realized that the way I was doing things was quite awkward. To be fair, I have global pointers to the views as I sometimes need to switch some view, draw something, switch to another view, etc. This leads to some confusion and globals feel just very wrong.

Here are the views I have in my engine:
1) Game camera view
2) Game camera view with rounded position for pixel-perfect rendering
3) GUI view
4) Level editor view

So, where can I store sf::Views to get easy access to them? How do I make sure that stuff gets drawn correctly? Should I keep putting window.setView in the beginning of each render() function call? (There're several of them, so there may be bugs because some previous function changed the view and the next one assumed that window has another view...) I can't just pass sf::View* to each render() function, because one render function may use several views at one (for example, GUI can be drawn in GUI view and some stuff may be drawn with game camera view, for example when drawing some GUI stuff relative to game entities)
Title: Re:creation - a top down action adventure about undeads
Post by: Hapax on May 10, 2016, 01:53:40 am
You could set the view at the beginning of each render function. It's a tiny thing to do. How many render functions do you have?
If you want to definitely avoid setting them unless they've changed, another option could be to store flags that keep track of if a view has been altered and set the view depending on the flag.
That said, what difference is it making? Are you altering the views in the rendering functions? It may be better to set up each of the views that are needed before any rendering occurs and then just switch amongst them during rendering. Should the views really be altered by the rendering process?

p.s. glad you found the view zooming code useful :)
Depending on how you want the interface to be, you may want to zoom out (only out!) from the opposite pixel (window size - mouse position in window). Try both ways and see what works best for you!
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on May 10, 2016, 09:21:50 am
You could set the view at the beginning of each render function. It's a tiny thing to do. How many render functions do you have?

Not much, in the game it's just two render functions: for the game and for the GUI. But level editor is much more complex: some GUI is drawn with window default view, some GUI is drawn in the world itself (stuff like bounding boxes). So at least two views are needed. Probably the level editor instance will store them as others won't need it.

If you want to definitely avoid setting them unless they've changed, another option could be to store flags that keep track of if a view has been altered and set the view depending on the flag.
That said, what difference is it making? Are you altering the views in the rendering functions? It may be better to set up each of the views that are needed before any rendering occurs and then just switch amongst them during rendering. Should the views really be altered by the rendering process?
Views won't be altered during the rendering. I just don't know what is the best way to access them from rendering functions without using globals. Well, maybe I can add them to Context struct which can be accessed from GameStates, so I can do something like this:
auto& view = *getContext()->gameView;
But PlayingState::render calls RenderingSystem::render so RenderingSystem doesn't have access to Context. So, I should probably pass needed views to the RenderingSystem::render function?
Or maybe I should just do this in PlayingState::render:
window.setView(gameView);
renderingSystem.render(window);
and hope that I won't ever need to draw anything in GUI view from renderingSystem function. :D

EDIT: After a lot of refactoring I've managed to manage views pretty nicely by putting them into Context struct which can be used from GameStates. So the problem is no longer relevant, unless someone has a better approach!

p.s. glad you found the view zooming code useful :)
Depending on how you want the interface to be, you may want to zoom out (only out!) from the opposite pixel (window size - mouse position in window). Try both ways and see what works best for you!
Tried zooming out with the opposite pixel - felt really weird, so I'm going to go with original version. :D
Title: Re:creation - a top down action adventure about undeads
Post by: Carlos Augusto Br Cpp on May 12, 2016, 07:07:13 pm
Hey man...I'm your biggest fan..and I will realy apreciate if you support me..
I have some questions:
1) You use a game engine?If yes tell me what..
2) Where you learn your C++ skills...If you learn at your own tell me why and what material you use?
3) The same question as above but changed to Lua Language...
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on May 12, 2016, 11:20:44 pm
Hey man...I'm your biggest fan..and I will realy apreciate if you support me..
I have some questions:
1) You use a game engine?If yes tell me what..
2) Where you learn your C++ skills...If you learn at your own tell me why and what material you use?
3) The same question as above but changed to Lua Language...
Hey! Glad to hear that, thank you!

1) I'm writing my own engine with the help of SFML. SFML is used for rendering, window creation, input and audio. This is just a basics upon which you can build a game engine which I'm doing right now. You should read this thread and my blog more, there's a lot of info about my engine. 
2) My C++ skills come from lots of books which I've read and lots of time spent programming in C++ (I've been developing in C++ for almost 7 years now!). I'm learning on my own, though there's a lot of help coming from more experienced people telling me what I'm doing right or wrong and telling about best practices.

I should probably write a recommended reading list on my blog, but I'll probably do it later. Okay, let's go!

C++
As far as the learning books go, I can't recommend C++ Primer (5th edition) by Stanley B. Lippman enough (not to be confused with C++ Primer Plus!).
Read it if you're not very confident in your C++ skills and want to learn it more.
As for more advanced/in-depth books (don't be afraid to read them, they're mostly not hard, they're just not tutorial books like C++ Primer)

Resources:

Lua
There's probably only one book I can recommend: Programming in Lua by Roberto Ierusalimschy. Very well written and covers everything you'll need to know about Lua. Can be used for learning from scratch but provides a lot about more difficult concepts.

Resources:
http://lua-users.org/wiki/ - lots of tutorials, sample code, libraries and bindings.

If anyone has anything nice to add, feel free to do so.
Title: Re:creation - a top down action adventure about undeads
Post by: Hapax on May 12, 2016, 11:32:01 pm
I've managed to manage views pretty nicely by putting them into Context struct which can be used from GameStates. So the problem is no longer relevant, unless someone has a better approach
Seems like you've managed to simplify passing the views to the rendering system so sounds like a good design. Nice work.

Tried zooming out with the opposite pixel - felt really weird, so I'm going to go with original version. :D
I expected as much. It's just that I've experienced some interfaces where they would zoom in the alternate way and you can get used to it for that software so you may have had a preference to that style.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on May 12, 2016, 11:52:59 pm
Seems like you've managed to simplify passing the views to the rendering system so sounds like a good design. Nice work.
Thanks. :D
Yeah, it's pretty simple now. Here's how the code looks in PlayingState::draw now:
if (!game.isEditingLevel()) {
    gameCamera.activate(window);
} else {
    levelEditorCamera.activate(window);
}
renderingSystem.draw(window);
As simple as it can get! (Camera::activate just sets Camera's sf::View for the given window).
And I don't need to change the view afterwards. (It's only changed in GUIPlayingState for GUI rendering, but guiCamera can be easily accessed from there).

I expected as much. It's just that I've experienced some interfaces where they would zoom in the alternate way and you can get used to it for that software so you may have had a preference to that style.
I mostly have experience with Paint.NET and Photoshop and it seems like they zoom out based on mouse position. (It feels like most image viewers do this too).
Title: Re:creation - a top down action adventure about undeads
Post by: Hapax on May 12, 2016, 11:59:28 pm
I mostly have experience with Paint.NET and Photoshop and it seems like they zoom out based on mouse position. (It feels like most image viewers do this too).
I agree and I can't think why they wouldn't. Worse still is that I can't remember where I've experienced the other style!

Anyway, nice work on the game. It's good to see it's still on the go  :)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on May 13, 2016, 12:11:05 am
I agree and I can't think why they wouldn't. Worse still is that I can't remember where I've experienced the other style!
Ha-ha :D

Anyway, nice work on the game. It's good to see it's still on the go  :)
Thanks! Hopefully I'll make and show some nice new stuff soon, but considering how drastically my free time appears and disappears it's hard to say for sure.
One thing I can say for sure is that this project would be still going strong no matter what. I've never lost any motivation and it taking so much time doesn't frustrate me at all. (I just hope that other people understand and accept my slow dev speed. :D)
Title: Re:creation - a top down action adventure about undeads
Post by: Carlos Augusto Br Cpp on May 13, 2016, 02:02:59 am
Wow!!! Really Really Thanks for your awnser...you just save my programming life right now...I'm a brazillian who live in a small city in the Amazonia...the city have in base of 20.000 people only...and I are the only one in the city who have interest in game dev and game programming...I read a lot of your articles here and in your wordpress site...and doing this I even have gain a real interest in the Lua programming language...I'm really really want to play re:creation...sorry for this but I have another question..
What program you use to do pixel art and how you learn pixel art....
sorry for my bad english I learn both english and C++ at my own..
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on May 13, 2016, 08:31:38 am
You're welcome. Glad to help you that much!
I use Paint.NET and PyxelEdit. I learned pixel art by learning from amazing tutorials like this (http://gas13.ru/v3/tutorials/sywtbapa_almighty_grass_tile.php) or this (http://opengameart.org/content/les-forges-pixel-art-course). There are tons of others, so be sure to check them out by googling "pixel art tutorial". It's also good to learn how to draw in general because your pixel art will become much better too. I can recommend Drawing on the Right Side of the Brain by Betty Edwards and Keys to Drawing by Bert Dodson.
Title: Re:creation - a top down action adventure about undeads
Post by: Carlos Augusto Br Cpp on May 13, 2016, 04:49:36 pm
Hey bro...Its me again...this time I have a question...Its a bit weird but..what is a thread? in programming and in this amazing forum?
Title: Re:creation - a top down action adventure about undeads
Post by: Tex Killer on May 13, 2016, 06:03:20 pm
Hey bro...Its me again...this time I have a question...Its a bit weird but..what is a thread? in programming and in this amazing forum?

In programing, a thread is where your instructions are executed. Your program can have a single thread (this is the default behaviour), so every instruction has to wait for the previous instructions to complete before it is executed, or you could implement multi-threading. With multi-threading, you create more threads on your program, and assign instructions for them to execute, so the instructions from different threads can execute in parallel (if you have enough processing cores for that, at least).

For exemple, if you have a very extensive calculation to do, you might break it down on four parallel algorithms on four different threads, and they would all run in parallel, taking 1/4 the time it would take to run them in only one thread (if your processor is quad-core or higher).

Here on the forum, a "thread" is where we post. For example, we are posting on the "Re:creation - a top down action adventure about undeads" thread.
Title: Re:creation - a top down action adventure about undeads
Post by: Carlos Augusto Br Cpp on May 13, 2016, 06:30:22 pm
wow thanks...by the way...This means that ever thread I use will consume a core processor of my computer?? for example if I use 8 threads I need to have an Octa-Core processor??and what happens if I not had this all theses processors and I want to use 8 threads?
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on May 13, 2016, 08:20:31 pm
No. The OS usually handles hundreds of threads (how do you think it can handle all those programs that run in parallel ;)), even on CPUs with one core. It constantly switches between them, giving them a chunk of execution time.

This is getting off-topic for this thread (;D), and even for this forum. There are much better resources online to learn what threads are and how to use them, I strongly advise you to learn with them rather than with forum posts on the SFML forum. I don't even know why you asked this question, nobody talked about threads in previous replies...
Title: AW: Re:creation - a top down action adventure about undeads
Post by: eXpl0it3r on May 13, 2016, 08:41:48 pm
You maybe interested in take a look at the Learn Programming Sub-Reddit: https://www.reddit.com/r/learnprogramming/
You can find a lot of answers and resources in the sidebar on that site. They also have an IRC chat that might be interesting for asking many different questions.
Title: Re:creation - a top down action adventure about undeads
Post by: Carlos Augusto Br Cpp on May 13, 2016, 10:22:30 pm
Sorry :-(...  I just had see Elias talking about threads and I don't know what are this...I'm a very beginner in programming...I'm so sorry for this
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on May 14, 2016, 08:34:18 am
Sorry :-(...  I just had see Elias talking about threads and I don't know what are this...I'm a very beginner in programming...I'm so sorry for this
No problem. I was probably talking about this thread as the best source of info about my engine.

And thanks, Tex Killer, Laurent and eXpl0it3r for contributing to this thread and pointing Carlos to a better place to discuss/learn about this stuff. :)

As for now, I want to rewrite my animation editor as a part of in-game editor to make process even more easier! So this means that I'll have to go back to my serialization system (https://bitbucket.org/edaler/meta-stuff) and make interface with ImGui. Hopefully it won't take too long and I'll post results soon. :)
I'm also making some good changes to level format, adding more features for tile overlays and just polishing and making stuff better in general.
Title: Re:creation - a top down action adventure about undeads
Post by: Carlos Augusto Br Cpp on May 14, 2016, 03:10:31 pm
Elias...I'd already see some Gif's animation and I are being much curious how the game will be...in general...It's so good to see the evolution of the process...Today I've tried to setup SFML 2.3.2 in my Code::Blocks IDE..and I did everything on the tutorial of the SFML site...and I fail..this is a frustration because I don't want to download the Visual Studio..If someone were can help me..or give a link of the forum to how to fix this...again sorry for put this here...I'm not very familliar with the forum..
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on May 14, 2016, 03:41:43 pm
You can create a new thread here (http://en.sfml-dev.org/forums/index.php?board=4.0) (be sure to read Code::Blocks + SFML tutorial carefully and try googling your problems, maybe they were solved somewhere before).
Title: Re:creation - a top down action adventure about undeads
Post by: Carlos Augusto Br Cpp on May 14, 2016, 04:10:58 pm
Thanks for your supporting..I really appreciate this...btw...any expectative of the release date(if this is not a secret :) )
I want soo much to play this game...the game had joypad support?
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on May 14, 2016, 08:28:43 pm
Thanks for your supporting..I really appreciate this...btw...any expectative of the release date(if this is not a secret :) )
I want soo much to play this game...the game had joypad support?
You're welcome. I have no idea how soon the game will come out (probably will take more than 1-2 years).
Yes, it has a joypad support, in fact it was pretty easy to write with SFML.
Title: Re:creation - a top down action adventure about undeads
Post by: Jesper Juhl on May 14, 2016, 11:20:48 pm
I just had see Elias talking about threads and I don't know what are this...
Multiple threads of execution all executing concurrently (so you need to be careful and synchronize access to resources).

I'm a very beginner in programming...
Then you probably want to stay far away from threads for a fair bit of time.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on May 14, 2016, 11:23:17 pm
Jesper Juhl, I was talking about forum threads, not other threads, so it's alright.

Progress update! (very excited about it)

A long time ago I've written serialization system which was used for my Qt animation editor. But now I've expanded it immensely and remade most of it in ImGui! (still hard to believe I did it in just one day)
(http://i.imgur.com/qdyvVV9.png)
Here's how serialization code looks:
void Animation::registerClass(MetaBuilder<Animation>& builder)
{
    builder.add("name", &Animation::name);
    builder.add("looped", &Animation::looped);
    builder.add("frameCount", &Animation::frameCount);
    builder.add("frameRect", &Animation::frameRect);
    builder.add("frameTime", &Animation::frameTime);
    builder.add("offset", &Animation::offset);
    builder.add("offsets", &Animation::offsets);
    builder.add("frames", &Animation::frameRects);
    builder.add("sounds", &Animation::soundInfo);
}
The ImGui window is composed by using info from Meta<T> class and each type has specialized element for displaying and editing it! (Bools have checkboxes, sf::Time has InputInt with ms label etc.)

But that's not all. I've previously had some problems with circular dependencies which prevented me from making recursive serialization, but now I've solved it! I can also serialize some STL containers (vector, map, unordered_map) and some SFML stuff (Vector2<T>, Time, Rect<T>)

Here's what I can do. Suppose I have a classes A and B.
struct A {
   std::unordered_map<std::string,B> bs;
}

struct B {
    std::string name;
    int age;
}

Here's how A registered:
builder.add("bs", &A::bs);
And here's how B registered:
builder.add("name", &B::name);
builder.add("age", &B::age);

Suppose there's an instance of A like this:
A a;
a.bs = {
    "first_key" = B{"John Smith", 28},
    "second_key" = B{"Jane Doe", 34}
};
And now I can serialize any instance of A to json by just doing this:
Meta<A>::serialize(a);
This will return this JSON:
{
    "first_key" = {
        name = "John Smith",
        age = 28
     },
     "second_key" = {
        name = "Jane Doe",
        age = 34
     }
}
Here are two things to note:
unordered_map is serialized into a JSON map. Each value of the map is serialized by using Meta<B>::serialize (that's where recursion comes in!)
For defined types (int, float, bool, string, etc.) there are Meta<> specializations, so recursion stops there.

Same stuff works for ImGui almost the same, but the neat thing is that I can map each member directly to a GUI control by passing a pointer to the member into ImGui function. There's no copies, no temporary objects. The C++ object is modified directly. And this is really great and awesome!

And here are some questions I have...
1) How should I handle error handling? Should I throw exceptions? I want to be able to write error messages like this: "Error: Animation::name should be string, but int was passed" if JSON is incorrect. Should serialize/deserialize throw exceptions like this? (Right now I only return true if deserialization was successful and false otherwise... which is not great, of course!), or maybe there are other ways to handle errors... (Silently ignoring them is not the way!)
2) Is there any reliable way to create function for template class which will be called on template class instantiation?  Is such thing possible? How can I achieve it and be sure that static members are initialized at the point the function is called?
For example, I write this function:
void Animation::registerClass(MetaBuilder<Animation>& builder)
and I want it to be called automatically by Meta<Animation> class. I want this to be called automatically because of Meta<T> instantiation:
Meta<T>::init() {
    T::registerClass(MetaBuilder<T>());
}

P.S. All meta stuff code will be open sourced soon! I'll also show how to use ImGui with it a bit later. :)
Title: Re:creation - a top down action adventure about undeads
Post by: Jesper Juhl on May 14, 2016, 11:34:43 pm
Jesper Juhl, I was talking about forum threads, not other threads, so it's alright.
Whoops.  ::)  ;D
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on May 15, 2016, 09:34:43 am
Quote
Is there any reliable way to create function for template class which will be called on template class instantiation?  Is such thing possible?
No, I don't think so. Manual registration of each class will be necessary.
Title: Re:creation - a top down action adventure about undeads
Post by: dabbertorres on May 15, 2016, 10:32:13 am
1) How should I handle error handling? Should I throw exceptions? I want to be able to write error messages like this: "Error: Animation::name should be string, but int was passed" if JSON is incorrect. Should serialize/deserialize throw exceptions like this? (Right now I only return true if deserialization was successful and false otherwise... which is not great, of course!), or maybe there are other ways to handle errors... (Silently ignoring them is not the way!)

I think this is a good use of exceptions.
I usually throw the exception with the error message, catch the exceptions in the caller, and then log the message (plus anything else I find necessary) from there.

2) Is there any reliable way to create function for template class which will be called on template class instantiation?  Is such thing possible? How can I achieve it and be sure that static members are initialized at the point the function is called?
For example, I write this function:
void Animation::registerClass(MetaBuilder<Animation>& builder)
and I want it to be called automatically by Meta<Animation> class. I want this to be called automatically because of Meta<T> instantiation:
Meta<T>::init() {
    T::registerClass(MetaBuilder<T>());
}

If I am understanding what you want to do correctly, I think you could add a static MetaBuilder<T> member to Meta<T>. And then, in the constructor of MetaBuilder<T>, call T::registerClass(*this)

template<typename T>
class MetaBuilder
{
        public:
                MetaBuilder()
                {
                        T::registerClass(*this);
                }
};

template<typename T>
class Meta
{
        static MetaBuilder<T> metaBuilder;
};

 

Also, it looks like this would be more standard C++. It looks like you're passing a temporary to a non-const reference parameter, which is a VC++ extension.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on May 15, 2016, 12:43:57 pm
Quote
Is there any reliable way to create function for template class which will be called on template class instantiation?  Is such thing possible?
No, I don't think so. Manual registration of each class will be necessary.
Yeah, it'll still be manual, but I don't want to call Meta<T>::init() somewhere in code.

I think this is a good use of exceptions.
I usually throw the exception with the error message, catch the exceptions in the caller, and then log the message (plus anything else I find necessary) from there.
Yeah, I'm probably going to use them, thanks!
Your second point about static MetaBuilder variable in interesting, but it doesn't work, because MetaBuilder ctor won't be called automatically (I don't really know why, I've tried this).

There's one method which works, but it looks really dangerous, ha-ha. (Not sure if it will work on every compiler...)
I put these two lines in MetaBuilder<T>::add(...):
(void)Meta<T>::properties; // unordered_map which stores class member pointers
(void)Meta<T>::initialized; // bool which calls Meta<T>::init, see below

And here's a line which is tricky:
bool Meta<T>::initialized = Meta<T>::init();

And here's Meta<T>::init():
MetaBuilder<T> builder;
T::registerClass(builder);

And here's how it all works.
When I write T::registerClass function for particular class, I call MetaBuilder::add<T> methods in it which causes code for MetaBuilder::add<T> to generate. Then I "touch" Meta<T>::properties so that this member is initialized before Meta<T>::initialized. The bool is "touched" too, so it's initialized by calling Meta<T>::init() which calls T::registerClass.

The most dangerous and (probably) unstable part is order of static initialization. If Meta<T>::initialized is initialized before Meta<T>::properties, then the code won't work. Yeah, pretty crazy stuff. :D

(At this point I'm really starting to question this approach which will probably lead me to abandon the idea of calling Meta<T>::init automatically)
Title: Re:creation - a top down action adventure about undeads
Post by: dabbertorres on May 16, 2016, 04:50:48 am
Ah yes, I forgot about a few of those odd static initialization rules, especially with templates.

I got something working though:
(click to show/hide)

Basically, two things are required: an out-of-class provision of Meta<T>::metaBuilder, and a (non-) use of the member. (Above, in Meta<T>::doWork()). Basically, for the compiler/runtime to decide for it to be statically initialized as desired, it must be directly accessed. Plain-Old-Data types don't have this restriction. Kinda weird. But it works, and it's not even that much work.

tl;dr: The above code will have T::registerClass() called for any class used as Meta<T>'s template parameter.

EDIT: Test::registered was just for testing, it wouldn't ever actually be needed, as it will always be true.

So, we came to quite similar conclusions. The constructor being called when desired is the only difference!
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on May 16, 2016, 09:04:27 am
dabbertorres, you know, at this point it's easier to call Meta<T>::init() directly because you have to call Meta<T>::doStuff which does almost the same thing, but a lot harder.
My solution is more complicated as it calls init function just by  instantiating MetaBuilder<T> and calling some of it's functions while registering the class, so no additional calls needed.
For example, when I write this:
void Animation::registerClass(MetaBuilder<Animation>& builder)
{
    builder.add("name", &Animation::name);
    ...
}
 
I call MetaBuilder<Animation>::add. Just instantiation of this method triggers instantiation of Meta<T> and Meta<T>::init is called through some tricks which I explained earlier.

I'm not sure how reliable that method is, though. :D
Title: Re:creation - a top down action adventure about undeads
Post by: dabbertorres on May 16, 2016, 05:05:09 pm
Hehe, I don't blame you! At least it's fun to experiment with different solutions. :D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on May 26, 2016, 12:15:29 am
Right now I'm working on some art and I'm making very neat in-game animation editor (screenshots and gifs coming soon, there'll be lots of features there).

I recently open sourced serialization/deserialization stuff which I use in my game.
Here it is: https://github.com/EliasD/MetaStuff
Other system was used for past several months, but I came up with this system recently and I find it a lot more flexible and easier to work with. Check it out, maybe it'll become useful for you. :)
(Maybe I'll even make an example which will show how it's possible to use ImGui with it to modify members of C++ objects).
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on May 26, 2016, 09:03:22 am
Now that your code is public I can give you various minor comments about it :P

It seems like JsonCast.h has found a way into the "include" folder when it should only be in "example" ;D

Also, you shouldn't use #pragma once alone, even if it's supported by all the common compilers that are able to compile your code.

You should include C++-style headers (<cassert> instead of <assert.h>).

You should enclose your functions and classes into a namespace. "member" is too common to be left in the global scope.

I like the C++14 implementation, it's really small and yet does the job perfectly. The 100% generic approach has some limitations though (ie. how would I get/store/use a single specific MemberPtr?), but you can easily expand this code if your requirements evolve.
Title: Re:creation - a top down action adventure about undeads
Post by: Mortal on May 26, 2016, 10:04:55 am
it is interesting, i haven't seen alike it before, but what took my attention most is your meta function "for_each_arg". i'm afraid, it is not going to do what it is supposed to do, for some reasons the args order is not guaranteed. probably it will fail if args... is empty. you may take a look to this http://stackoverflow.com/questions/28110699/what-does-this-variadic-template-code-do?answertab=votes#tab-top (http://stackoverflow.com/questions/28110699/what-does-this-variadic-template-code-do?answertab=votes#tab-top) for more details.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on May 27, 2016, 12:05:30 am
Now that your code is public I can give you various minor comments about it :P
Thank you for your comments! That's exactly what I wanted, especially coming from awesome programmers like you. :)

It seems like JsonCast.h has found a way into the "include" folder when it should only be in "example" ;D
Fixed!

Also, you shouldn't use #pragma once alone, even if it's supported by all the common compilers that are able to compile your code.
Should I use both pragma once and include guards?

You should include C++-style headers (<cassert> instead of <assert.h>).
Thanks, forgot about that. Fixed.

You should enclose your functions and classes into a namespace. "member" is too common to be left in the global scope.
I have no idea for the namespace yet, any suggestions? :)

I like the C++14 implementation, it's really small and yet does the job perfectly. The 100% generic approach has some limitations though (ie. how would I get/store/use a single specific MemberPtr?), but you can easily expand this code if your requirements evolve.
Thank you! Yeah, getting/storring specific MemberPtr is not yet possible, but doing some stuff for a single member is possible, like this:
for_tuple([](const auto& memberPtr) {
    if (memberPtr.getName() == "someVar") {
        // do something for this particular member
    }, Meta::getMembers<SomeClass>());
Too bad it works in O(n), though it should be much problem. I wish there was a way to store members not in tuple, but in some unoderder_map like structure, this would make things much easier, but this structure has to be heterogeneous!
And I will surely add some stuff (I've added some neat things today, see below)

it is interesting, i haven't seen alike it before, but what took my attention most is your meta function "for_each_arg". i'm afraid, it is not going to do what it is supposed to do, for some reasons the args order is not guaranteed. probably it will fail if args... is empty. you may take a look to this http://stackoverflow.com/questions/28110699/what-does-this-variadic-template-code-do?answertab=votes#tab-top (http://stackoverflow.com/questions/28110699/what-does-this-variadic-template-code-do?answertab=votes#tab-top) for more details.
Thanks for you comment. The order is not guaranteed, yep, but VS, GCC and Clang to stuff in order. I realize that this is not guaranteed but at least there's some order for some compilers! :D
I'll take a look at this later, though. For now you can just think of std::tuple as if it was std::unordered_map with member names as keys. :)
As for empty Args... see my update below. I've added and overload for empty tuple which takes empty tuple and just does nothing with it. This fixes the problem (unless the user calls for_each_arg... which is not needed! :D)

Okay, and now for some new stuff...
(I hope people won't mind me discussing all this stuff in this thread, I wish I could start another thread about this lib, but it's not an SFML Project, so...)

New stuff
I've changed getMembers from being a class member function to Meta struct templated function.
I could have made it a free function, but it's hard to make a template specialization a friend, it's much easier to write "friend class Meta" in classes you want to serialize (it's not required most of the time, though)

Template specialization looks like this:
#include <Meta.h>
template <>
inline auto& Meta::getMembers<Person>()
{
    static auto memberPtrs = std::make_tuple(
        member("someMember", &Class::someMember),
        ...);
    return memberPtrs;
}
 

This template specialization should be included in header, because compiler can't deduce return type if you then try to use this specialization somewhere else.
I was worried that there would be some problems with mixing static with inline (after all Meta::getMembers<T> is static! And inline! And contains static variable! What if it's copied between translation units?)
Worry not, here's a quote which saved my project! :D
Quote
"[..] An inline function with external linkage shall have the same address in all translation units. A static local variable in an extern inline function always refers to the same object. A string literal in an extern inline function is the same object in different translation units." - [dcl.fct.spec]/4
Cool, so the  memberPtrs tuple is created ONCE for each registered type. That's exactly what I want. And here's another cool thing, template function implementation looks like this:

template <typename T>
inline auto& Meta::getMembers()
{
    static std::tuple<> emptyTuple;
    return emptyTuple;
}
 

This means that getMembers<Class>() returns empty tuple for all unregistered classes! (Instead of producing compile error)
Not sure that this is expected behaviour, but I've added overload for forTuple which takes empty tuple. This means that if you do this:
orTuple(/* some lambda */, Meta::getMembers<SomeUnregisteredClass>());
then it'll do nothing.

Some questions
1) I'm thinking about renaming MemberPtr to just Member. Is this reasonable? After all some MemberPtr's may contain only getter and setter function pointer... :D
2) Is there some good namespace which I can use for my project? I have no idea for the name yet. Simple "meta" would be nice, but I feel that it's too generic.
3) What should library do in exceptional cases? (he-he)
Should it assert? Should it throw an exception? Here's and example, I want to add a function which would return non-const reference to member. For example:
T& MemberPtr::getNonConstRef(Class& obj);
But this is only possible if MemberPtr contains pointer to member or pointer to non-const getter.
So, what should I do in such case? (there are many cases like that)
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on May 27, 2016, 09:12:09 am
Quote
Should I use both pragma once and include guards?
I'd say include guards. According to wikipedia, at least gcc and clang are able to detect and optimize them the same way as #pragma once.

Quote
I have no idea for the namespace yet, any suggestions?
I'm not an expert in finding names ;D

Quote
I've changed getMembers from being a class member function to Meta struct templated function.
Much better :)

Quote
1) I'm thinking about renaming MemberPtr to just Member. Is this reasonable?
Sure. Here you're abstracting things, there's no such concept of "pointer" at this level.

Quote
3) What should library do in exceptional cases?
Why are you asking? Any problem with exceptions?
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on May 27, 2016, 09:30:53 am
I'd say include guards. According to wikipedia, at least gcc and clang are able to detect and optimize them the same way as #pragma once.
Will do :)

I'm not an expert in finding names ;D
SFML is a good name. ;D

Much better :)
Neat

Sure. Here you're abstracting things, there's no such concept of "pointer" at this level.
Agreed, I'll rename it to just Member.

Why are you asking? Any problem with exceptions?
Just isn't used to writing them and I don't see them often in code, to be honest. Any good libraries or examples of doing exceptions good way? :D

Btw, I was trying to implement something like this:
template <typename Class, typename F>
inline void Meta::doForMember(const std::string& name, F&& f)
{
    for_tuple([&](const auto& memberPtr) {
        if (memberPtr.getName() == name) {
            f(memberPtr);
        }
    }, getMembers<Class>());
}

...

// can get age like this!
int age;
Meta::doForMember<Person>("age",
     [&age, &person](const auto& memberPtr) { age = memberPtr.get(person); });
 

But this didn't work, because lambda which is passed to doForMember is instantiated for each MemberPtr and so line "age = memberPtr.get(person);" fails for all non-int types. Any tips about what I can do? (This looks like conditional compilation, he-he).
Title: Re:creation - a top down action adventure about undeads
Post by: Laurent on May 27, 2016, 10:05:58 am
Quote
Any good libraries or examples of doing exceptions good way?
I don't know, but it's pretty easy:
- create your own exception class(es)
- throw on exceptional case
- catch where it makes sense to handle the exceptional case

But in your example (function which returns a non-const reference to member), this is a programer error, not a runtime error, so I'd say you should treat this one with an assert -- maybe you could even static_assert with some tricks, as everything is known at compile time?

Quote
But this didn't work, because lambda which is passed to doForMember is instantiated for each MemberPtr and so line "age = memberPtr.get(person);" fails for all non-int types. Any tips about what I can do?
This is the kind of problems you'll run into with such a strongly-typed generic approach.
However I guess this one could easily be solved with a visitor:

class Visitor
{
    template <typename T>
    void visit(const Member<T>&)
    {
    }

    void visit(const Member<int>& member)
    {
        do_something_with(member.get());
    }
};

Visitor visitor;
visit(Meta<Person>::getMembers(), visitor); // for_each(member) visitor.visit(member)
 

This is the typical way to dispatch an heterogeneous container in a strongly-typed context.

This is just the idea, you'll now have to try to wrap this stuff so that it can carry all the needed context (age and person variables), and is more friendly on user-side (so you can use a simple lambda instead of writing a full visitor everytime).

The other typical approach is to introduce an intermediate weakly-typed layer (with a variant class for values, and abstract base classes on top of anything that depends on the underlying member type). But that's a different story.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on May 28, 2016, 12:37:27 am
Thanks for ideas, Laurent. I actually came up with a neat solution to the problem with some inspiration from your example.
I used SFINAE to create function call_if_same_types<T, U> which calls (and instantiates) lambda with given args if types T and U are the same (and does nothing otherwise).
It's used here (https://github.com/EliasD/MetaStuff/blob/master/include/Meta.inl#L38). The coolest thing about this function is that it won't instantiate the lambda with wrong MemberPtr type! So, the user only gets const MemberPtr<T, Class>& member in lambda. The user needs to pass correct member type to doForMember function but that's pretty basic and I don't see any way to deduce member's type without user passing it explicitly.
doForMember allowed me to create two useful functions: getMemberValue and setMemberValue which can be used like this:
int age = Meta::getMemberValue<int>(person, "age");
Meta::setMemberValue<int>(person, "age", 30);

Unfortunately there's very little that my library can do at the compile time, because I can't get access to a given member by it's name, because all Member instances are created during runtime. I'm okay with doing all stuff during runtime, though. :) (It would be cool to be able to use static_assert a lot, but it's hard in my implementation)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on June 01, 2016, 12:48:29 am
Here's how my animation editor looks now:
(http://i.imgur.com/A44zLlb.gif)
Animation properties part is generated with Meta stuff and directly maps widgets to C++ variables, which is pretty cool and shows that spending some time on all this template stuff was useful. :)
I also wrote the tutorial (https://eliasdaler.wordpress.com/2016/05/31/imgui-sfml-tutorial-part-1/) about how to use ImGui with SFML which some of you may find useful. :)
Title: Re:creation - a top down action adventure about undeads
Post by: Lin on June 03, 2016, 03:05:11 am
That looks really nice. The interface is clean, the system is flexible, and overall it's very powerful. I like it a lot!
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on June 04, 2016, 12:00:15 am
That looks really nice. The interface is clean, the system is flexible, and overall it's very powerful. I like it a lot!
Thanks a lot! :D
Title: Re:creation - a top down action adventure about undeads
Post by: Ethan.Calabria on June 04, 2016, 08:50:59 pm
Hey Elias, thanks for the ImGui tutorial, it was great!  I'm looking forward to the second part.  Out of curiosity, do you have a Youtube channel for you or for Re:creation?
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on June 06, 2016, 12:16:40 am
Hey Elias, thanks for the ImGui tutorial, it was great!  I'm looking forward to the second part.  Out of curiosity, do you have a Youtube channel for you or for Re:creation?
You're welcome! :)

I have a youtube channel (https://www.youtube.com/channel/UCQ14f1TLnrnBC5CVs-4c7Pw), but it has just some old covers, ha-ha. Some day it'll be used for Re:creation trailers and dev log updates, though. But I can't say when because I like writing more than speaking. :)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on July 04, 2016, 11:12:56 pm
Hi, everyone, I'm back!
I recently finished my bachelor's degree and now I'm free for some time so I'll work on the game as hard as I can!

(http://i.imgur.com/S1KfulV.gif)

I've published new dev log (https://eliasdaler.wordpress.com/2016/07/04/recreation-dev-log-march-june-2016-part-one/) about what I did in the recent months. There's some new stuff that I didn't write before (especially Action Lists) so be sure to check it out.

Today I've also made some awesome changes to input handling. Input was previously hard coded in C++ and this wasn't very good. But I've moved all input handling in Lua and finally separated input from game logic which is awesome:

playerCallbacks = {
    usePrimaryItem = {
        action = ButtonPressedAction(self.buttons.PrimaryAction),
        f = function()
            playerEntity:usePrimaryItem()
        end
    }
}

...

inputManager:setCallback("Press_Primary", playerCallbacks.usePrimaryItem)
 
So, I register callbacks and bind them to different actions. Suppose that I entered the menu and now pressing Primary Action button does some another thing.

It's pretty easy to change, I just do this:
inputManager:setCallback("Press_Primary", menuCallbacks.select)

Very easy and clean. Btw, ButtonPressedAction calls sf::Keyboard::isPressed and so input handling is very fast.

 Still, it may not be perfect, so feel free to advice some stuff I may do better. :)
Title: Re:creation - a top down action adventure about undeads
Post by: Mortal on July 05, 2016, 01:29:43 am
Hi, everyone, I'm back!
I recently finished my bachelor's degree and now I'm free for some time so I'll work on the game as hard as I can!


congratulation for bachelor's degree Elias.  :)

Today I've also made some awesome changes to input handling. Input was previously hard coded in C++ and this wasn't very good. But I've moved all input handling in Lua and finally separated input from game logic which is awesome:
i'm totally agree with you regarding separation of game logic and input that makes sense for game design. but  why do you thing that implementing input functionality with C++ is bad idea?
Title: Re:creation - a top down action adventure about undeads
Post by: Glocke on July 05, 2016, 08:13:44 am
Hi, everyone, I'm back!
I recently finished my bachelor's degree and now I'm free for some time so I'll work on the game as hard as I can!

Gratz! And nice to have you back :-)

I've published new dev log (https://eliasdaler.wordpress.com/2016/07/04/recreation-dev-log-march-june-2016-part-one/) about what I did in the recent months. There's some new stuff that I didn't write before (especially Action Lists) so be sure to check it out.

Nice :) Keep on coding and posting :-)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on July 05, 2016, 09:37:52 am
congratulation for bachelor's degree Elias.  :)
Thanks

i'm totally agree with you regarding separation of game logic and input that makes sense for game design. but  why do you thing that implementing input functionality with C++ is bad idea?
It's not a bad idea, it's just not as flexible as I want. I want to be able to change input in scripts (not just bindings!) so that I don't have to recompile C++. And if I set up callbacks, they'll probably be Lua functions and calling Lua for each keypress will be inefficient and calling simple update() function in each frame seems to be much faster.

Gratz! And nice to have you back :-)

Thanks!

Nice :) Keep on coding and posting :-)

I will. :)
Title: Re:creation - a top down action adventure about undeads
Post by: Ungod on July 05, 2016, 07:50:29 pm
Decent work so far!

So what you basically do is store a callback function together with a button/key and invoke that callback when the appropriate inputEvent is catched? What if you want multiple callbacks to be invoked on the same keypress?

Btw I think I saw you posting at Sol2 on GitHub (the world is small), is that right? I recently started using it and I think its pretty decent. Do you use it?
Title: Re:creation - a top down action adventure about undeads
Post by: Mario on July 05, 2016, 11:14:05 pm
What if you want multiple callbacks to be invoked on the same keypress?

Use something capable of storing multiple entries, such as a vector? :)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on July 05, 2016, 11:50:43 pm
Decent work so far!

So what you basically do is store a callback function together with a button/key and invoke that callback when the appropriate inputEvent is catched? What if you want multiple callbacks to be invoked on the same keypress?
Yep. Right now I have basic input events like key press or key release but probably will create something more complex if needed.
Right now I'm doing this:
callbacks["PRESS_A"] = { type = ButtonPressedAction(keys.A), f = f1 }
callbacks["PRESS_A2"] = { type = ButtonPressedAction(keys.A), f = f2}
As you can see, both "PRESS_A" and "PRESS_A2" callbacks will be called on one button press.

I don't use vectors as Mario proposed because removing specific callbacks from that vector will be kinda tricky. Suppose I did something like this:
callbacks[ButtonPressedAction(keys.A)] = { PRESS_A = f1, PRESS_A2 = f2}
And now I want to remove PRESS_A callback. The problem is that I can't find table which contains it because doing this:
local callbacksWithA = callbacks[ButtonPressedAction(keys.A)]
won't work, because ButtonPressedAction(keys.A) will create another table and so it won't be the same as the one that was used as key at callback registration. I don't have solution to this problem at the moment. The only thing that comes to my mind is doing this:
callbacks.onButtonPress[keys.A] = { PRESS_A = f1, PRESS_A2 = f2}
So that I can later do this:
local callbacksWithA = callbacks.onButtonPress[keys.A]

Btw I think I saw you posting at Sol2 on GitHub (the world is small), is that right? I recently started using it and I think its pretty decent. Do you use it?
Yep, I've created several issues there. I'm using it and I've written a bit about it in the latest dev log on my blog. It's very good :)
Title: Re:creation - a top down action adventure about undeads
Post by: Ungod on July 06, 2016, 08:04:35 am
Use something capable of storing multiple entries, such as a vector? :)

The result would be a datastructure where just (in most cases) very few vectors have more than one element. Not that aesthectic. Just wondered how one could solve that "better".  :)

Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on July 09, 2016, 01:41:11 am
I was recently inteviewed on CppCast! Listen to the episode here (http://cppcast.com/2016/07/elias-daler/). If you've been following this thread, you probably know most of the stuff, but still, it may be interesting for you. :)

I've also mentioned SFML several times, so it's pretty good too, I think! ;D
Title: Re:creation - a top down action adventure about undeads
Post by: Hapax on July 09, 2016, 04:25:33 pm
I just wanted to point out that, since you've redrawn the player graphics, you should probably update the ones on the original post. ;)
Title: Re:creation - a top down action adventure about undeads
Post by: Tank on July 09, 2016, 10:01:18 pm
Nice CppCast, Elias. :)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on July 10, 2016, 10:29:36 am
I just wanted to point out that, since you've redrawn the player graphics, you should probably update the ones on the original post. ;)
Yup, these animations aren't drawn yet, but I'll update it once I redraw them, thanks :)

Nice CppCast, Elias. :)
Thank you!
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on July 25, 2016, 03:14:34 pm
I'm back! Spent some time with family and taking a rest from all that study stuff. But now I'm back, though I don't have much time to work on the game, so I'll work on some things that I really need to implement which may not be really that interesting.

* Multiple tile maps on the same level. Useful for creating indoor maps which won't require any loading. Much easier to use and implement than having them on the same tile map just far-far away.
* Better collision detection. First of all, I need to use some space partitioning and I'll probably go with the simplest approach: uniform grid. I'll implement quad tree if there's a need for it (probably won't need it, as there's probably won't be lots of entities on the screen at the same time).
I also want to implement diagonal tiles but I don't have any idea how to do them at the moment, so any suggestions are welcome!
* Making entity descriptions pure data. I've talked a bit previously about this, but now it's clearer to me why moving functions out of entity descriptions is awesome.

1) I can easily reuse them. Most functions inside entity description scripts are collision responses and different triggers. Some collision responses may be the same, for example, entities saying "watch where you're going". Copying even one line of the same behavior can be dangerous and lead to some hard to fix bugs (DRY!)
2) Serialization. I want to make entity descriptions serializable so I can edit them inside some Entity Editor (kinda like Animation Editor). I can't save Lua functions, I can only save data.

So, what is the alternative to storing collision response in script and having CollisionSystem call that function on collision? Easy, I use events. CollisionSystem sends OnCollisionEvent and then state machine of the entity catches it and the current state reacts to that event.

This is cooler than I thought at first. Imagine if I want to implement some guy which can carry some precious item and drop it on collision with another entity if it was moving faster than SOME_BIG_SPEED. If he doesn't carry anything, he just swears.

Here's how old approach looks:
some_guy = {
    ...
    CollisionComponent = {
        onCollision = function(this, second)
            local currentState = stateManager.getCurrentState(this)
            if currentState == State.IdleState then
                this:swear()
            elseif currentState == States.CarryingItemState then
                if Vector2f.normalize(second:getVelocity()) > SOME_BIG_SPEED then
                    this:dropItem()
                end
            end
        end
    }
}
 
This is bad, because if/else branches may become pretty big this way. Here's how it will look with my state machine system:
local SomeGuyStates = {
    IdleState = {
        [EventType.CollisionEvent] = {
            callback = function(this, event)
                this:swear()
            end
        }
    },
    CarryingItemState = {
        [EventType.CollisionEvent] = {
            callback = function(this, event)
                if Vector2f.normalize(second:getVelocity()) > SOME_BIG_SPEED then
                    this:dropItem()
                end
            end
        }
    }
}

Okay, that may not look as straightforward as the first approach, but it's much more scalable and let's me easily add intended behavior which varies depending entity's current state.

* Input. I've made some progress in this area. Now I have InputManager in Lua which has stuff like this (some things are simplified:
local playerCallbacks = {
    UseItem = {
        type = InputType.Player,
        callback = function()
            local player = getPlayer()
            player:usePrimaryItem()
        end
    },
    ...
}

function InputManager:initialize()
    self.onPressCallbacks = {}
    self.oneReleaseCallbacks = {}
    ...
end
And then I set input like this.
inputManager.setPressedCallback(Button.PrimaryAction, playerCallbacks.UsePrimaryItem)

* Reloading changes in scripts. Previously I could reload entities by changing their scripts and then typing "reload <ENTITY_NAME>" in in-game console. But this wasn't very efficient, because most changes are local to one component. So now I want to implement something like "reload <ENTITY_NAME>.<COMPONENT_NAME>" (e.g. "reload hero.CollisionComponent")
I can even take it further sometime and make some systems watch over currently used script files and reload them automatically if they detect any changes. Determining the change will be the hardest thing and I just plan to compare component tables inside entity description scripts. If some things changed, reloading system will just re-make the component in each entity of this type and give them copies of new one. Trying to detect changes INSIDE the component is much harder and I won't spend time on that. Though it would be pretty awesome to be able to change one thing inside the script, hit CTRL+S and have it changed in C++ without creating any new objects.

But that's pretty hard to make! Having "reload <ENTITY_NAME>.<COMPONENT_NAME>" will probably be enough for me for now.

* Unbreaking stuff. There are some things that I break with system changes and then don't have time to fix them. For example: some actions lists and complete levels are broken and need to be rewritten. That's what I'm going to do in the next weeks. :D

* Some refactoring and improving code. One thing that I dislike about my code base is that I use raw pointers quite a lot in some places. For example, Entity::get<ComponentType> returns a raw pointer to component. This is not bad, because the component can not be present and then I'll just return nullptr, but I hardly check for that anywhere, so references are the way to go. If I'm really want to know if the component is present, I can call Entity::has<ComponentType> anyway.
There are some small changes that I have to make and I'll write them there if I find them good enough.

* Lua. In recent days I've ported all my Lua/C++ code to sol2 and now LuaBridge is not used anywhere. This feels really good. I also really want to keep Lua/C++ stuff in one place, it's pretty hard to do now (it keeps getting better with events and moving some C++ stuff to action lists though). I wish there was some good example on how to keep Lua/C++ stuff in one place, but I haven't seen this anywhere, so I'll see what works for me.

* Combat. Okay, that one is the coolest. I'll just work on combat, draw some battle animation and see what works and what doesn't. The combat won't be complex, but I want it to be cooler than ALttP. The player won't have a shield in his undead body, so he'll only be able to dodge attacks. Let's see how it works, there aren't many top down action adventure games which use this system.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on July 26, 2016, 07:37:29 pm
Worked with input today, made some cool progress.

First of all, I started to tie input to player states. For example, consider moving around. Player can only move when the hero is in IdleState and MoveState (when you walk around and change the direction without stopping. I could write it like this:
local currState = player:getState()
if currState == State.IdleState or currState == State.MoveState then
    if Input.isPressed(Button.Up) then
        player:moveUp()
    elseif ...
end
First of all, this is not scalable and can lead to spaghetti code and lots of if/else states.  Secondly, the input is tightly coupled to game logic which goes against the separation I try to make. Okay, I can rewrite it like this:
local playerCallbacks = {
    MoveUp = {
        isActive = function()
            return (currState == State.IdleState or currState == State.MoveState)
        end,
        callback = function()
            player:moveUp()
        end
    },
    ...
}

...

inputManager:setPressedCallback(Button.Up, playerCallbacks.MoveUp)
Okay, that's a bit better, because now I can easily redefine input and not tie it too tightly with game logic. isActive function is used as additional check after Input.isPressed(<SOME_BUTTON>) to see if the callback should be called or not. But that solution wasn't good enough for me (suppose that I have X states in which player can move and Y states when he can only move up and down), so I went with more readable and scalable approach, I just do this:
local playerCallbacks = {
    MoveUp = {
        callback = function()
            player:moveUp()
        end
    },
    ...
}

...

local HeroStates = {
    IdleState = {
        enter = function()
            ...
            inputManager:setPressedCallback(Button.Up, playerCallbacks.MoveUp)
        end,
        exit = function()
            ...
            inputManager:setPressedCallback(Button.Up, nil) -- disable this input
            ...
        end
    },
    ... -- same for MoveState
}
Why do I have to disable the callback when I exit the state? That's because each state has to define controls in it. In some cases you only get ability to attack, in some cases "Up" now means another thing.
Awesome! Let me show you how easily expandable this is. Suppose that someone hits the hero. If the hit was too heavy, the controls become a bit reversed! (This is just an example, won't happen in the game). I can easily express it in code without adding new if/else conditions and breaking anything along the way!
local HeroStates = {
    ...
    HurtState = {
        ... -- same controls as IdleState, same code
    },
    HurtBadState = {
        enter = function()
            ...
            inputManager:setPressedCallback(Button.Up, playerCallbacks.MoveDown)
        end,
        exit = function()
            ...
            inputManager:setPressedCallback(Button.Up, nil)
            ...
        end
    }
}
And that's how it works. Maybe I'm overcomplicating stuff, but I'm very satisfied with the end result.
Another thing about input. Right now I use previous and current frame inputs to check if the button was just pressed or just released, but now I think that I'll just use events for that because the same can be achieved with them. Are there any stuff which can't be solved with events and info about the button press at the current frame? I can't think of the situation which isn't solvable with this approach.

And the last thing are events. I think that I need to have some events which can be sent directly to some objects instead of having just one global event queue.
Here's an example where I need that. Suppose two entities collided and I don't want to call collision response callbacks immideately. So I create CollisionEvent which has some data, like ids of first and second entities and some other stuff.
Now entities can either subscribe to particular event and either recieve messages from everyone or subscribe to particular entity. In this case, there's no clear sender and even if there was one, it would still feel kinda awkward. I want to do something like this:
-- event in Lua
-- suppose that 'first' and 'second' collided
local e1 = {
    sender = first,
    recipient = second,
    data = {
        ... -- additional data
    }
}
local e2 = {
 ... -- almost the same with sender and recipient switched around
}
eventManager:queueEvent(e1)
eventManager:queueEvent(e2)
Neat! Now the events will be send from 'first' to 'second' and vice versa instead of telling about it to everyone and then checking if entity is interested in that collision or not (which is really slow). What do you think of that approach?
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on July 31, 2016, 02:06:18 pm
Three days of suffering and now I have this:
(http://i.imgur.com/BMN1jcB.gif)
Yup, now I can handle diagonal tiles! And they can have different angles!
First of all, I didn't use any algorithm or tutorial because I haven't found any which explained it good enough. Most of them are poorly explained, have bugs and fail in lots of cases or have to many limitations (like having to add special "END OF HILL" tile).
So, here's how my method works.
First of all, I have to resolve the collision after I detect it.
(http://i.imgur.com/gc6hpgO.png)
First of all, I check one of the points of the AABB is inside the triangle. The point which is checked depends on the rotation of triangle. In the case shown on the picture, I just use p.x and then calculate yTest like this: yTest = k * p.x + b, where y=kx+b is line equation. Then I check if c.y < yTest (if the y coord of point is below the line). If it is, then it means that the point is inside the triangle.

Then I find dx and dy - intersection depth. If the entity was moving down, I push it by "dy" up. If it was moving left, I push it by "dx" to the right as if it never crossed the boundaries of the triangle.
The most complex situation is pushing it out if it was moving down AND left. In 45 degree case, it's pretty easy and is shown on the picture. For other cases it's harder and so far I haven't found the easy way to push it out perfectly for other angles.

But just pushing it out of the triangle isn't enough. Suppose that entity moves down (player holds the "DOWN" button). It's expected that entity will slide down-right along the wall, so just pushing it out is not enough, I'll have to move it a bit down and right as if it was sliding along the wall.
There are some other considerations to be had, but after all the method works.
After I clean up the code, I'll probably open source it and maybe someone will help me make it even better.

One more thing, I've noticed that my AABB collision test wasn't perfect and didn't detect a collision when it was very small, so I've remade the algorithm and now it looks like this.

sf::Vector2f getIntersectionDepth(const sf::FloatRect& rectA, const sf::FloatRect& rectB)
{
    if (rectA.width == 0.0f || rectA.height == 0.0f || rectB.width == 0.0f || rectB.height == 0.0f) { // rectA or rectB are empty
        return sf::Vector2f();
    }

    sf::Vector2f depth;

    if (rectA.left < rectB.left) {
        depth.x = rectA.left + rectA.width - rectB.left;
    } else {
        depth.x = rectA.left - rectB.left - rectB.width;
    }

    if (rectA.top < rectB.top) {
        depth.y = rectA.top + rectA.height - rectB.top;
    } else {
        depth.y = rectA.top - rectB.top - rectB.height;
    }
    return depth;
}

Previosly, it looked like this:
sf::Vector2f getIntersectionDepth(const sf::FloatRect& rectA, const sf::FloatRect& rectB) {
    if (rectA.width == 0.0f || rectA.height == 0.0f || rectB.width == 0.0f || rectB.height == 0.0f) { // rectA or rectB are empty
        return sf::Vector2f();
    }
    // get centers of rectangles
    sf::Vector2f centerA = sf::Vector2f(rectA.left + rectA.width / 2.0f, rectA.top + rectA.height / 2.0f);
    sf::Vector2f centerB = sf::Vector2f(rectB.left + rectB.width / 2.0f, rectB.top + rectB.height / 2.0f);

    float dx = centerB.x - centerA.x;
    float dy = centerB.y - centerA.y;
    float min_dx = (rectA.width + rectB.width) / 2.0f;
    float min_dy = (rectA.height + rectB.height) / 2.0f;

    if (std::abs(dx) >= min_dx || std::abs(dy) >= min_dy) { // no intersection;
        return sf::Vector2f();
    }

    float depthX = dx > 0 ? min_dx - dx : -min_dx - dx;
    float depthY = dy > 0 ? min_dy - dy : -min_dy - dy;

    return sf::Vector2f(depthX, depthY);
}
This code was used in XNA Platformer example and worked good enough, but after inspecting it, I noticed that there was no need to find centers of each AABB!

There was one small bug with my implementation, though.
At first I wrote one line like this:
depth.x = rectA.left - (rectB.left + rectB.width);
Now, let's say the entity had pos.x == 20.f and I pushed it by some v * dt. The problem was that after resolution, the pos wasn't 20.f, it was something like 19.999999998f; or something. Writing this interestingly enough fixed the problem:
depth.x = rectA.left - rectB.left - rectB.width;
Now the resolution is perfect!

That's it for now. What do you think of the method? Maybe you have some method that is easier to implement? :D
I think that instead of moving it along the slope myself, I need to add something to velocity so the entity will move at the next frame by the needed amount, but I found it too hard to implement unfortunately. :S

(BTW, I think I will only use 45 angle tiles because they're easier to draw and work the best, he-he)
Title: Re:creation - a top down action adventure about undeads
Post by: Mortal on July 31, 2016, 09:29:50 pm
interesting, from demo, it looks work perfectly.  :)

i just want to draw your attention at the condition in getIntersectionDepth(). the condition statement ( if (rectA.width == 0.0f ... ) will never be true due to the floating point. better to round it with some epsilon value.

btw, since you are using AABB collision, sf::Rect can return the intersect rect and i think this what you're want. am i right?
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on July 31, 2016, 10:25:34 pm
interesting, from demo, it looks work perfectly.  :)
Yep, it looks like this, but there are some edge cases when it fails. It also doesn't work correctly with platformers where your have gravity pushing entities downwards... I hope I'll be able to fix it.
This isn't a problem with top-down thankfully, but I want to be sure that the algorithm works no matter what.

i just want to draw your attention at the condition in getIntersectionDepth(). the condition statement ( if (rectA.width == 0.0f ... ) will never be true due to the floating point. better to round it with some epsilon value.
Hmm, that's not true. :P
Check this out: http://ideone.com/bCbpwX
At some point, there's a possibility that you'll lose some precision and (x - x) won't be exactly equal to zero, yes. But if you assign 0.0f to float, you can be sure that this will be equal to 0.0f.
So, I'm just testing if each rect actually has non-zero size. This is rare though and this condition can be probably thrown out. :D

btw, since you are using AABB collision, sf::Rect can return the intersect rect and i think this what you're want. am i right?
Testing for the collision is not enough, I'm also getting intersection depth which is then used for collision resolution. :)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on August 10, 2016, 11:44:20 pm
I drew new walking animation and made some slight changes to Renatus' design.
(http://i.imgur.com/6EGzDqc.gif)
I think it's much better than all previous iterations. :D
(http://i.imgur.com/ibsa5Po.gif)
It looks very clean. :D
The coolest thing about it is that it was pretty cheap to make. 2nd and 4th frames are idle frames and 1st and 3rd just mirror each other.

I've also made some random tile tests to figure out how much "nature-like" I can make roads and the result looks pretty good:
(http://i.imgur.com/6D2gZEV.png)
That's only 5 road-grass transition tile variations (some tiles are just mirrored and rotated). Now I'll have to draw something like that for Re:creation :D

Don't have much time to work on the game atm but hopefully I'll soon get some!
Title: Re: Re:creation - a top down action adventure about undeads
Post by: Xoodar on August 12, 2016, 12:38:22 am
The game looks awesome!
I started following you some weeks ago on Twitter and on your blog, you are capable of inspire others, congratulations!
I have one question about the level saving/loading.
How do you handle them? I mean, how do you handle different tilesets in one level-room?
Title: Re:creation - a top down action adventure about undeads
Post by: Mr_Blame on August 12, 2016, 02:16:58 pm
For no reason the new main character animation reminds me Earthbound characters walk cycle.:) Looks like I played to much Earthbound last week :P
Title: Re: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on August 20, 2016, 11:48:01 pm
The game looks awesome!
I started following you some weeks ago on Twitter and on your blog, you are capable of inspire others, congratulations!
I have one question about the level saving/loading.
How do you handle them? I mean, how do you handle different tilesets in one level-room?
Thank you! And I'm very glad to hear that I inspire people. :)

Level consists of stuff stored in txt (mostly tile info) and some additional Lua scripts which contain some data like music path, ambient path, area info, etc. and functions which are executed when you enter different areas on the level.

And what do you mean by level saving? Do you mean in-game saving or saving level after it has been edited in level editor?

Different tilesets are handled with multiple vertex arrays. :)

For no reason the new main character animation reminds me Earthbound characters walk cycle.:) Looks like I played to much Earthbound last week :P
Ha-ha, Mother 3 walking cycles actually inspired me a lot, so it's no coincidence :D



A bit off-topic: I've just finished preparing/taking exams for my Master's degree (which is why I didn't do anything about the game for a long time). I'm finally going to get my degree in HSE which was the best option for me, so yay!
And also, that means that I'll finally get some free time to work on the game again. (But who knows, maybe this new study will be pretty demanding, I'll see).
Title: Re: Re:creation - a top down action adventure about undeads
Post by: Xoodar on August 29, 2016, 02:34:10 am
Thank you! And I'm very glad to hear that I inspire people. :)

Level consists of stuff stored in txt (mostly tile info) and some additional Lua scripts which contain some data like music path, ambient path, area info, etc. and functions which are executed when you enter different areas on the level.

And what do you mean by level saving? Do you mean in-game saving or saving level after it has been edited in level editor?

Different tilesets are handled with multiple vertex arrays. :)

I mean, when you save a level, with two different tilesets in it, how do you save it? I never worked with levels like it, i'm very curious.
And can you tell me more about vertex arrays with different tilesets?
Thank you! :)
Title: Re:creation - a top down action adventure about undeads
Post by: Mr_Blame on August 29, 2016, 02:52:54 pm
You need to have a header in your file e.g.
YourFile.txt:
   tileset1.png tileset2.png


Algorithm:
Extract a line and extract from this line tile set paths. Then you know what to do ;).
Title: Re:creation - a top down action adventure about undeads
Post by: Xoodar on September 01, 2016, 06:22:00 pm
You need to have a header in your file e.g.
YourFile.txt:
   tileset1.png tileset2.png


Algorithm:
Extract a line and extract from this line tile set paths. Then you know what to do ;).
No i... i... i don't D:
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on September 03, 2016, 07:43:45 pm
You need to have a header in your file e.g.
YourFile.txt:
   tileset1.png tileset2.png


Algorithm:
Extract a line and extract from this line tile set paths. Then you know what to do ;).
No i... i... i don't D:
I'll explain my level file structure soon! Sorry for the delay, I'm quite busy at the moment. :)
Title: Re:creation - a top down action adventure about undeads
Post by: Xoodar on September 04, 2016, 03:21:15 am
i will wait!
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on September 18, 2016, 11:47:12 pm
Sorry for such a long delay again!
Okay, first of all, if you have tilesets on different textures (different files), you can't use the same vertex array for them because sf::VertexArray maps vertices to texture coords and you assume that the texture is the only one. So, suppose you have a level which has two tilesets (let's give them ids, 0 and 1). Tiles in such level can be stored something like this:
1:0,0:1,0:0,...
Where x:y means that tile has id x and tilesetId y. (that's how I store them)
You'll have to have to VertexArrays for each tileset. The first one will correspond to tileset with id = 0 and second one - to tileset with id = 1. Each vertex array will contain only those vertices which correspond to tiles which have a corresponding tilesetId. So, for tileId you'll store the first tile in example file and won't store the second tile.
Hope it all makes sense, feel free to ask more questions if you want. (You can write me an e-mail, it's better to chat there: eliasdaler@yandex.ru), or you can PM me here.



Btw, I'm working on the game pretty hard now. Fixing old rusty code, adding necessary stuff, cleaning up the engine structure, etc. Hope I'll finish all that stuff soon. Any tips on not over engineering and being okay with some your code? (There needs to be book on that, ha-ha!)
Title: Re:creation - a top down action adventure about undeads
Post by: Lin on September 22, 2016, 11:24:50 am
Btw, I'm working on the game pretty hard now. Fixing old rusty code, adding necessary stuff, cleaning up the engine structure, etc. Hope I'll finish all that stuff soon. Any tips on not over engineering and being okay with some your code? (There needs to be book on that, ha-ha!)
That seems to be the theme of every programmer that does everything for personal gain, including myself :( To prevent it, I've decided to just keep everything the same until the end and I have a finished product. Then when I want to do version 1.1, or start optimizing the code, or implement modding support etc, I'll go back and redo what I feel needs redoing. As you work, you'll always come up with ideas for how things could better be done, but you'll never actually get things done that way.

So in short, the only solution is don't (lol) - that's what planning is for I guess.
Title: Re:creation - a top down action adventure about undeads
Post by: Tukimitzu on September 25, 2016, 05:29:26 am
Any tips on not over engineering and being okay with some your code?

If you know something can be done better, save it for the next game. Only change things that are precluding something else to work. It's not like players care if you are scripting or hardcoding anyway.

And as I say this I'm writing my own version of strtok.  ::)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on September 28, 2016, 11:32:40 am
If you know something can be done better, save it for the next game. Only change things that are precluding something else to work. It's not like players care if you are scripting or hardcoding anyway.
It's not about the players or other programmers checking out my code, it's about being helpful and kind to my future self. Scripting helps me iterate much faster, write cleaner code which has less bugs and is much easier to modify. And if I kept thinking, "ehhh, I'll change/implement it for the next game", I'd probably be confused by all the messy code and hardcoded stuff all around... While it's okay for a smaller project, my project isn't small, so I can't just "go with the flow". :S

The same applies to what Lin has said. I wouldn't make it to 1.0 with the tools I previously had. Or maybe I could but the game would be much worse and buggier than it is even now.
Take my level editor for example... After reimplementing it's interface with ImGui now helps me build much more complex levels in less time. I don't have to remember countless key bindings, I can easily add new abilities to it, etc.



I've started working on the game really hard again two weeks ago and I've made a huge progress since then. Most of the things I did can be considered refactoring and repairing broken stuff, but doing so, I've managed to improve the quality of the code and easily implement some cool things I previously couldn't.
Most of the work was done by porting some stuff from C++ to Lua, because Lua provides great simplicity and wrappers for difficult stuff which I write in C++ and then can call from Lua.

There are still lots of things I have to do before I stop doing "invisible" work and repaying my programmer debt... But I feel like I'm on the right path and things have been going very well for the last two weeks.

What makes me especially happy is that I move on pretty quick and work on very important things. Things that let me implement new game features. Things that let me fix bugs, make the game easier to expand and modify.

Yes, I could have made a game with lots of bad code and then I could have made another one where the code was better. But this isn't a case for my game, because I don't want to have many limitations which will limit me.

Here's an example of the thing that probably increased re-usability of the code and allowed me to implement very complex cutscenes in no time: action lists. Yes, I've managed to do similar stuff with state machinest... but can you imagine how difficult it would be if I had to do big cutscenes with primitive tools? This would have hurt my desire to make cutscenes really awesome and I'd be looking for a easy way out. This is not the approach I want to take.

Hopefully, I haven't been doing lots of wasteful work which you would consider as overkill. (Well, I can think of one thing: Meta serialization/deserialization system). But I think that most things I do are made to make me build the game, not just some random engine. YAGNI is an important principle which I follow and there haven't been a thing I've made for the game which I don't use.

I realize that the progress hasn't been as quick as some people want it to be. But you have to understand lots of factors which cause this: I'm a solo developer, I develop my engine from scratch (almost), I have other things to do in my life, as well as several others (which I'll explain in an article I plan to write soon).

I'll explain in detail what I did in next post which will summarize all the things I did in the previous 2-3 months.
Let's see what I'll have to say in a week or two. Hopefully, things will be very optimistic by then and I'll start working on a new content, of which there haven't been much lately.
I hope that this will be kind of a "reboot" of the thread and I'll be able to deliver more stuff.
And I just want to thank everyone for all the support and encouragment in this thread. All of it fills me with great pride for my work and makes me work harder and make Re:creation the best game I can do.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on October 05, 2016, 08:41:39 am
Just got my game's gifs stolen on 9gag: http://9gag.com/gag/a25X7P9
Some guy claimed that he's been developing the game, but he's not me, of course.
The game got lots of attention and praise, so it's pretty good, I guess. Any thoughts on this?
UPD: made a post there: http://9gag.com/gag/aNWb6V0
Title: Re:creation - a top down action adventure about undeads
Post by: SpeCter on October 05, 2016, 01:39:43 pm
Obviously not cool, maybe you should add watermarks or something  in the future which makes it harder to just copy and claim it as your own.
I can only imagine that you have very mixed feelings about this, since it got so much praise(which is nice) but the praise is directed at the wrong person(some attention seeking whore on 9gag).
Title: Re:creation - a top down action adventure about undeads
Post by: SpaceInJourney on October 05, 2016, 03:14:49 pm
Good job, I seen all images from first one (I found them on your imgur album which you made) and game has made really great progress! Can't wait to see finished version.
Title: Re:creation - a top down action adventure about undeads
Post by: dabbertorres on October 05, 2016, 07:00:31 pm
Damn. The watermark is a good idea. Maybe make the watermark a link to your site/devblogs/etc just in case someone does steal it again without looking too hard.

Also, looks like there is a report option, although I haven't used 9gag, so I don't know how effective it is.
Title: Re:creation - a top down action adventure about undeads
Post by: Hapax on October 05, 2016, 10:20:21 pm
Sorry to hear about the theft, Elias. Why on Earth would they be claiming to be developing and promise other stuff that they obviously cannot deliver? I mean, he "just read a lot online to learn how to make this", which understates and undermines how much involvement this game obviously requires!

Did you post on his thread as well making your own thread?
Title: Re:creation - a top down action adventure about undeads
Post by: Ungod on October 05, 2016, 11:02:16 pm
Wow, internet is sometimes so ridiculous...

While I was shocked at the first time, I now - 5 mins later - think that you pretty much benefit from that. I mean 3k comments and they are mainly positive. Wow.

To be serious: All in all just a very nice advertising and you had zero effort yourself. I mean what danger could result from this? Even if he keeps posting stuff, he just makes your gifs more famous.

I think you should see it like that: People will remember the art-style and the gameplay-mechanics. They will not remember and at all they do not really care WHO posted the gifs.

Title: AW: Re:creation - a top down action adventure about undeads
Post by: eXpl0it3r on October 06, 2016, 02:17:54 am
To be serious: All in all just a very nice advertising and you had zero effort yourself. I mean what danger could result from this? Even if he keeps posting stuff, he just makes your gifs more famous.
One problem is, that he also promised to make it free for all 9gaggers. So if some people then find the real game they might feel entitled to get the game for free, which may result in a shitstorm or just negative "reviews".

Plus whatever the person keeps saying might put Elias or the game in a wrong light.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on October 06, 2016, 09:01:42 am
Thanks for the support, guys!

Obviously not cool, maybe you should add watermarks or something  in the future which makes it harder to just copy and claim it as your own.
Yeah, I thought about this, maybe a very small watermark may be helpful. Something like (Re:creation made by @EliasDaler). Even if the gif is not stolen, but just reposted somewhere, people can find the game easily without asking people what game it is.

I can only imagine that you have very mixed feelings about this, since it got so much praise(which is nice) but the praise is directed at the wrong person(some attention seeking whore on 9gag).
Yes. Honestly, I'm quite shocked at how many people got hyped about the game. I didn't think that it was that attractive to so many people. I'm a bit worried about people saying that it's a rip-off of Link to the Past and I hope that it doesn't look that way in reality. :)

Good job, I seen all images from first one (I found them on your imgur album which you made) and game has made really great progress! Can't wait to see finished version.
Thank you!

Damn. The watermark is a good idea. Maybe make the watermark a link to your site/devblogs/etc just in case someone does steal it again without looking too hard.
Yeah, see the note about watermark above.

Also, looks like there is a report option, although I haven't used 9gag, so I don't know how effective it is.
Yes, I reported it, but it doesn't even let you explain why you think that it's a copyright infringement. And there's no option to contact the mods or the guy who posted gifs, so not much I can do.

Sorry to hear about the theft, Elias. Why on Earth would they be claiming to be developing and promise other stuff that they obviously cannot deliver? I mean, he "just read a lot online to learn how to make this", which understates and undermines how much involvement this game obviously requires!
Yeah, I have no idea why he does this? I can understand (but, of course, don't support) people who steal and sell games claiming to be their creators... at least they get some profit, right?
In this case, the OP gets literally nothing. Just some sweet karma, I guess? :S

Did you post on his thread as well making your own thread?
Yes, I made some comments there, made my own thread, but they didn't get much attention.

Wow, internet is sometimes so ridiculous...

While I was shocked at the first time, I now - 5 mins later - think that you pretty much benefit from that. I mean 3k comments and they are mainly positive. Wow.
Yes, I'm very glad about the comments. So many positive ones, so many people saying that they'd play it. Feels very nice and I didn't expect that one gif could make so many people interested.

To be serious: All in all just a very nice advertising and you had zero effort yourself. I mean what danger could result from this? Even if he keeps posting stuff, he just makes your gifs more famous.

I think you should see it like that: People will remember the art-style and the gameplay-mechanics. They will not remember and at all they do not really care WHO posted the gifs.
I completely agree with what eXpl0it3r said about this.
And here are some examples of OP acting stupidly:
(http://i.imgur.com/xVmQsLa.png)
(http://i.imgur.com/kuU4pZb.png)

Free promotion is great, but just imagine people who hear about the game for the first time and then associate it with dev acting like a edgy teenager.  :(

UPD: I've made a reddit post (https://np.reddit.com/r/gamedev/comments/564fla/my_game_gifs_were_posted_on_9gag_op_said_that_he/) about the issue.
Title: Re:creation - a top down action adventure about undeads
Post by: Ungod on October 06, 2016, 11:23:41 am
That was indeed an oversight of mine. The reason is, that I didnt see those comment myself.
If you are lucky, most other people wont read them either and just take a short glace on the gifs.
(I dont know what the 9gag community is like).

Anyway, I totally understand your distaste about that stuff, I just try to find positive aspects - and I think there
are some.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on October 06, 2016, 11:29:46 am
Sure, I think that I didn't lose much and people may remember the game when they'll see it next time!  ;D
Title: Re:creation - a top down action adventure about undeads
Post by: Brax on October 06, 2016, 11:42:24 am
As Ungod already mentioned, you can have benefits from this - free advertisement. But you do need to continue bashing the thief until people realise he stole it.
Not much you can do, but to continue what you are already doing - grab a megaphone and yell that he stole your artwork. Post on all social media you are using, get as many people as possible to know that and share.

The thief can't keep his charade for long. He doesn't have access your game, and will be unable to fulfill his "promise" to 9gagers.
The people who expect the free game must know that they have been lied to. Even after that, if they have the audacity to ask for a free game, they won't have any solid basis for that request, because you haven't made such promise, so all their "complaints" are invalid.  ;)

Besides, people who want your game for free will try to pirate it anyway. :-\
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on October 06, 2016, 12:26:53 pm
As Ungod already mentioned, you can have benefits from this - free advertisement. But you do need to continue bashing the thief until people realise he stole it.
Not much you can do, but to continue what you are already doing - grab a megaphone and yell that he stole your artwork. Post on all social media you are using, get as many people as possible to know that and share.
Yup, I think the thread on reddit may help. I've also found out how to contract 9gag mods, so maybe this will help too.

The thief can't keep his charade for long. He doesn't have access your game, and will be unable to fulfill his "promise" to 9gagers.
The people who expect the free game must know that they have been lied to. Even after that, if they have the audacity to ask for a free game, they won't have any solid basis for that request, because you haven't made such promise, so all their "complaints" are invalid.  ;)
Yep! And I think that calling him out will scare him from continuing to lie.

Besides, people who want your game for free will try to pirate it anyway. :-\
Yup. And I plan to do what Anodyne's developers did: put it on torrent trackers myself. It doesn't mean that the game will be free, but at least people won't have to download buggy versions or viruses!
Title: Re:creation - a top down action adventure about undeads
Post by: Sub on October 06, 2016, 10:27:46 pm
Damn, people can be such jerks.  It reminds me of when people would IM the guys who created Super Meat Boy asking for help with a bogus support problem, edit the conversation to make the developer seem like he was an asshole, and then post it on reddit / social media. 

On the bright side, I think this is indicative of you creating something that is worthy of attention, so at least there's that. 
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on October 06, 2016, 10:59:30 pm
Damn, people can be such jerks.  It reminds me of when people would IM the guys who created Super Meat Boy asking for help with a bogus support problem, edit the conversation to make the developer seem like he was an asshole, and then post it on reddit / social media. 
Ha-ha, yeah, I remember that. It was so stupid and absurd, it was hilarious. xD

On the bright side, I think this is indicative of you creating something that is worthy of attention, so at least there's that.
Yeah, I'm very surprised to find out how much attention this game could possibly have and how much people it attracts. I don't expect much, so this is very flattering.
Title: Re:creation - a top down action adventure about undeads
Post by: Ruckamongus on October 07, 2016, 12:03:06 am
Hey man, I haven't been following this thread on SFML forums for a couple months, but I saw your post on Reddit just now. People are really shitty, and I'm so sorry you've got to go through something like this. I hope things work out for you and this doesn't discourage you from continuing this awesome project and your blog posts (I really appreciate them, especially the Lua stuff!). Best of luck, Elias.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on October 07, 2016, 11:03:54 am
Thank you! In fact, this encouraged me more, because of all the support and positive feedback I've got. I'm really blown away by the response. It makes me want to work harder, which is especially great considering the improvements about the engine I've made. I'll post more info soon. :)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on October 10, 2016, 10:14:05 pm
Working hard on all kinds of stuff, but I want to share it all in a big blog post once I'm done with huge chunk of work that I've planned. :D

For now, take a look at how animation progressed... I made the last iteration yesterday, quite happy with it now! (arms changed, and legs too!)
(http://i.imgur.com/bCdBa80.gif)
Title: Re:creation - a top down action adventure about undeads
Post by: SpeCter on October 11, 2016, 10:25:14 am
Even though the animation in the last one is definately the best I still like the second one the most(only the helmet seems weird)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on October 11, 2016, 09:55:55 pm
Even though the animation in the last one is definately the best I still like the second one the most(only the helmet seems weird)
It looks pretty okay when you see it like this, but it felt too boring in the game. That's the most frustrating thing, ha-ha. :D
Title: Re:creation - a top down action adventure about undeads
Post by: scionOfBytes on October 12, 2016, 04:14:39 pm
Hi, Kaylors (https://www.reddit.com/user/Kaylors) from Reddit. Really looking forward to the release of this game. How far along are you?
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on October 12, 2016, 08:08:30 pm
Hi, Kaylors (https://www.reddit.com/user/Kaylors) from Reddit. Really looking forward to the release of this game. How far along are you?
Hi. I'm really far away. From some gifs the game may have given you impression that I have most of the things done, but the truth is: I haven't. It's just that I have some basic systems done and I'm pretty good at polishing and hiding unfinished stuff. :)



So, I'm almost finished with most of the engine (blog post will be coming, yeah) and I want to start working much faster. I really want to focus on the game itself, because from the looks of it, the main mechanic is what grabs people's attention.

I have to make combat and recreation feel great. I have to make some awesome and funny cutscenes. I have to do a lot. And I want to do it faster, which means that I won't do polish and won't do much art. This, unfortunately, means, that I won't have many gifs to show, because I don't want people to see my ugly throwaway art.

But! I will talk about the progress and maybe I'll still show something interesting from time to time.

In recent weeks I was not only refactoring the engine and making new tools, but I also started to fix a lot of things that were broken and some of them I've rewritten from scratch. For example, I rewrote recreation sequence in Lua and it's now much less buggy, the code is easier to understand and modify.

I also had combat and house entering/exit broken. It was all fixed with much better code: I now use events more often and I made lots of entity states reusable, so, for example, hero, archer and enemy with sword have the same AttackState! (Written completely in Lua, btw).

Working on gameplay elements felt really great. I think I didn't have so much confidence about the game for a really long time. So now I want to really make things happen. I feel like most of the tools are in a very good condition and it seems like I've finally figured out how to make stuff! (Action lists and events were an incredibly powerful addition).

So yeah, I hope things work out and I don't get stuck again!
Title: Re:creation - a top down action adventure about undeads
Post by: SushiKru on October 14, 2016, 12:16:29 am
Hello

First congradulations for your game, it looks really awesome, i read some of your tutorials about entity/component/system and LUA and it's really helps me to understand how it works.
I have a question, i am trying (for learning purpose) to implement an ECS but i can't figure how the game state should be handled. By game state i mean the differents states of the game (title screen, options screen, loading screen, in game screen, maybe the fighting screen in a jrpg etc ...). Do you use a class above everything that will handle screen transitions or do you just use ECS to accomplish this ? Are your systems always working even if they are not needed ? for example does MovementSystem exists even if you are in the title screen ? Or do you add them depending on the screen ?
I was thinking about a GameStateSystem  but i am really not sure how it could work:

enum State { title, inGame, loading }
class GameStateSystem : System {

  void update() {
    if (m_nextState != m_currState) {
      switch (m_nextState) {
        case inGame:
           // what you do here ?
           break;
      }
    }
  }

  void setState(State state) {
    m_nextState = state;
  }
}
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on October 15, 2016, 08:56:07 am
SushiKru, thank you!

Here's one important thing: using ECS doesn't mean you have to build everything with ECS in mind. In my game, states are implemented as a bunch of classes which have enter, exit, update, draw, handleEvent virtual functions. I also have a stack of game states, so I can have PlayingState and then push GUIPausedState on top of it.

The StateManager calls update from top to bottom (GUIPausedState, PlayingState) and if one of the current states returns false, it stops. GUIPausedState can return false and then PlayingState update won't be called and this is what achieves pause.

On the other hand, draw is called from bottom to the to (PlayingState and then GUIPausedState). In GUIPausedState you can draw your overlay menu, for example.

All systems are created at the start of the game, but their update functions are called from PlayingState::update only (well, I also have RenderingSystem::draw and PlayingState::draw calls that, but for others update call is enough).

Transitions between states can be accomplished by making some states like FadeOutFromBlackState or something like that. And then you'll just have LoadingState pushing PlayingState and FadeOutFromBlackState to state stack after it's done loading stuff (and popping itself from it). And once FadeOutFromBlackState finishes, it can pop itself from stack (possibly sending an event which PlayingState and other things can catch, so it'll start processing player input and updating stuff...)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on October 15, 2016, 07:36:12 pm
Just a little thing I did in 3 minutes. But hey, it made such an improvement!
(http://i.imgur.com/36HyuEh.gif)
This works extremely simple: I just start playing "idle" animations from the random frames. :D
This will work really great for making the world feel more alive, especially when I'll add more animations to the scenery.
Title: Re:creation - a top down action adventure about undeads
Post by: SushiKru on October 16, 2016, 08:29:09 pm
SushiKru, thank you!

Here's one important thing: using ECS doesn't mean you have to build everything with ECS in mind. In my game, states are implemented as a bunch of classes which have enter, exit, update, draw, handleEvent virtual functions. I also have a stack of game states, so I can have PlayingState and then push GUIPausedState on top of it.

The StateManager calls update from top to bottom (GUIPausedState, PlayingState) and if one of the current states returns false, it stops. GUIPausedState can return false and then PlayingState update won't be called and this is what achieves pause.

On the other hand, draw is called from bottom to the to (PlayingState and then GUIPausedState). In GUIPausedState you can draw your overlay menu, for example.

All systems are created at the start of the game, but their update functions are called from PlayingState::update only (well, I also have RenderingSystem::draw and PlayingState::draw calls that, but for others update call is enough).

Transitions between states can be accomplished by making some states like FadeOutFromBlackState or something like that. And then you'll just have LoadingState pushing PlayingState and FadeOutFromBlackState to state stack after it's done loading stuff (and popping itself from it). And once FadeOutFromBlackState finishes, it can pop itself from stack (possibly sending an event which PlayingState and other things can catch, so it'll start processing player input and updating stuff...)

Yeah this is what i read on few topics in stackoverflow or gamedev. I think the RenderSystem is a special case, i can't imagine how it could work if the render is done in update(), the idea of having a draw() function that is called at a specific time is probably a better solution. You can even call it on a different thread so you will use 2 cpus core (well it's overkill for a 2D game probably  :D)
Thank you for the answer, so a state machine above everything, and depending on the state i could create different ECS. It's really hard to understand fully ECS, when you start using it, you want to do everything with it but it's probably not a good idea.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on October 17, 2016, 12:09:22 am
You're welcome!
I think it's better to update more than you render. Sometimes you can update faster than you draw, it's good for input and slowdowns due to rendering (e.g. if you start rendering at 20 FPS, your deltas get big and may kinda ruin your physics system, things like "bullet through the wall problem" and such).
Check out this (https://github.com/SFML/SFML-Game-Development-Book/blob/master/01_Intro/Source/Game.cpp#L37) implementation of the game loop, I like it a lot and currently use it for my game.
As for the ECS - just use it for game objects only. Don't bother with the rest until you have a reason to do so. Keep things simple! :D
Title: Re:creation - a top down action adventure about undeads
Post by: Hapax on October 18, 2016, 08:51:55 pm
Animation offsets add natural feel to them. Good addition! :)

I think it's better to render more than you update.
I think it's possible that you may have phrased this incorrectly. ;)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on October 20, 2016, 08:15:58 am
Animation offsets add natural feel to them. Good addition! :)
Thanks!

I think it's better to render more than you update.
I think it's possible that you may have phrased this incorrectly. ;)
Oops, I'll fix that :D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on October 20, 2016, 11:55:27 am
Little details... Cat's talking animation stops when translation is shown.
(http://i.imgur.com/dKRkCKn.gif)
And meowing now corresponds to translated text more, he-he.
Don't worry, I work on much bigger stuff too, I just don't have much time to write it down! (Everything will be written in a huge blog post soon)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on October 30, 2016, 12:58:45 am
Working on a lot of engine stuff. Not just for "I'm gonna need this later", but just finishing very important stuff which is crucial for quick iteration and development.

One such feature is a console, which was previously written in SFML, but now is written with ImGui! It finally has history, native-like text field, scrolling, etc.
And I've made special "Lua" mode for it, which lets me just input Lua commands which are then called with lua_dostring. This allows me to do stuff like this!
(http://i.imgur.com/DdKtJqU.gif)
And that's just one tool which will make my life better. There are other tools which I'll soon show, which will free me from printf debugging! (some things can't be debugged with printf/cout/breakpoints!)

Also, I only recently understood that it's time to move my object's origin to something reasonable.
(http://i.imgur.com/mdaD6SI.png)
Like this. Previously it was left up corner of a sprite. Yeah, silly, I know!
I wonder if there'll be some things which are obvious, but aren't talked about often. (just remembered that I created "damage" entity instead of just placing damage rect and disabling/enabling it when attack occurs).

One more thing I want to talk about: what is the best way to handle collision rect? In some games it's okay to have a static one, but in my case, it should change depending on entity's direction, and maybe even on animation! (Fighting games do this). And I wonder... what's the best way to separate animation and collision so that they won't depend too much on each other? Any ideas? :D
Title: Re:creation - a top down action adventure about undeads
Post by: Ethan.Calabria on October 31, 2016, 08:22:07 pm
And I wonder... what's the best way to separate animation and collision so that they won't depend too much on each other? Any ideas? :D

I don't know what the best way is, but the way I'd do it is have animation frames associated with an attack geometry class.  The class would describe the initial size of the collision geometry (a rect for example), and then keys for size and rotation, which would be interpolated over the frames until the end frame (which could default to the animated end, or be specified).  It would have an entityID associated with it. 

I'd do basically the same thing for the hitboxes.  Then I'd sort them based on which quadrant (or some smaller factor) they're in.  There would be a similar sort for the collision geometry.  When any collision geometry was active, it would then check against the hitboxes in it's same quadrant.  If it hits, the event system would tell the attacker it hit, and the one attacked that it was hit...and then those entities would handle their own behavior. 

That's my very straightforward approach.  I'm not really sure how well it would work, my own game is turn-based, so the animations themselves don't determine if something is hit or not, that's determined beforehand.  I tried to keep it fairly generic since I don't know how you have your game set up.  Anyway, don't know if you'll use any of those ideas, but maybe it will inspire something cleverer.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on November 06, 2016, 09:34:29 pm
Thanks for your ideas Ethan, I'll certainly think about how to make something similar in my game.

Sorry for no posts lately. I'm working hard on the game. So much stuff done, that I'm afraid that writing about them will take me a lot of time. But there's so much nice stuff I did! So I can't promise anything at the moment, but I'll try my best. :D

P.S. gifs from my game got featured in an ImGui talk. That's pretty nice. :D
https://youtu.be/LSRJ1jZq90k?t=3m18s
Title: Re:creation - a top down action adventure about undeads
Post by: Mortal on November 07, 2016, 02:43:00 am
that's really a good news, congrat for your success Elias.  :)

when you going to release the game. i believe this is good time to this step. "CppCon" is sponsored by Microsoft and Google and many more.  even the entire C++ community are gathered in "CppCon" conferences. this is great opportunity for you.



Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on November 07, 2016, 10:28:01 am
Thanks!
Yes, I hope that I'll be able to deliver some talks at CppCon some day. Maybe something about Lua/C++ interaction, maybe a Re:creation dev talk or postmortem (*wink-wink*) one day.

I need to work hard to make this happen! :D
Title: Re:creation - a top down action adventure about undeads
Post by: Hapax on November 07, 2016, 03:39:55 pm
Still going well, I see! :)

I have just noticed that the shadows are slightly mismatched.

(http://i.imgur.com/DdKtJqU.gif)
The angles of your dynamically created shadows are different for differently sized objects. For example, compare the building's shadow to the shadow of the small item in front of it.

You can see it more clearly in your original explanation (http://en.sfml-dev.org/forums/index.php?topic=18062.msg139941#msg139941). The vertical line of the building should have its shadow at the same angle to the scarecrow's shadow vertical line. The scarecrow looks more skewed than the building.

If I was to guess, it looks like you the skewing is done based on offsets which are based on overall size (or similar) but the angle of 1-2 (and 0-3) here:
(https://i.imgur.com/WPhqio0.png)
should always be the same for every shadow.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on November 10, 2016, 08:46:09 am
Yep!

Thanks for noticing that. I'll try to see how I can make it more consistent.  :D
But I'm doubting that automatic shadows will work as good as I thought, so maybe I'll have to go back to hand drawn shadows.
The biggest problem is objects casting shadows on walls/non-flat surfaces. See the tree on the left in the latest gif. The shadow should be different. (Or maybe I shouldn't place trees like this, but this will limit level design, which isn't very good).
Title: Re:creation - a top down action adventure about undeads
Post by: Hapax on November 10, 2016, 11:35:28 pm
You could break them up and seperate into sections for different planes. For examples, that tree's shadow would have two parts: one for the ground and one for the vertical building front.

Personally, I would think that hand-drawn shadows are the better option. That way they appear exactly as you intend. The worst culprit for automatic shadows are things like trees that are quite deep and should have a mostly round shadow since the light is usually somewhat above and the viewer is not.

Manually drawing shadows can take more time, though, and may still become victim to level-design. Again, with that tree, a hand-drawn shadow would still have to take into account that building...

That's right; I'm always here to spot the insignificant things ;D
Title: Re:creation - a top down action adventure about undeads
Post by: felaugmar on November 11, 2016, 02:19:03 am
I kind of liked your idea @Hapax;
Two generated shadows.

Do a try @Elias Daler, for sure the effect will be interesting.  ;D

But for a more dynamic shadow maybe you need to add the shadow to collision system and re-create based on the objects touching it.
Hmm, maybe it's not so simple :)
Title: Re:creation - a top down action adventure about undeads
Post by: Tank on November 15, 2016, 08:03:18 am
Don't make him over-engineer even more, @Hapax. ;-) IMO they look just fine right now. Making them better should probably be targeted in the polishing state.
Title: Re:creation - a top down action adventure about undeads
Post by: grumpaladin on November 17, 2016, 04:46:37 pm
I seem pretty late to the party but I just wanted to say that this project looks amazing and it's very inspiring.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on November 17, 2016, 06:16:19 pm
Hey everyone, sorry I didn't write anything for such a long time!
I have some very good news: I've got a new laptop! My old one was six years old and developing on it was very painful for me, compilations took a really long time, VS randomly freezed from time to time, etc. But now everything works so fast! Pair that with VS 2017 RC which is even faster than VS 2015, and I'm perfectly happy. :D

I'm currently writing a dev log about what I've done in the last four months, it should be done in a week, maybe less. So much stuff to cover...

I also started working on my Master's thesis project which will be done in Unreal Engine 4. It probably will be very time consuming, so I won't have as much time to work on the game as I previously had... but on the other hand, I'll still be doing game dev and learning about good engine and game design. Maybe I'll apply some of the stuff I learn to my engine (without over-engineering, of course! I'm constantly amazed by amount of stuff UE4 has...).


As for the lighting... I think I'm going to draw them by hand because having some shadows hand-drawn and some generated will look odd and not very consistent. I'll try to find a way to draw as less shadows as possible, because that's what SNES games did and still looked very nice.

Drawing vertical part of the shadow on other objects is a good idea, unfortunately it will only work in cases where the object has flat surface and is perpendicular to the floor. Otherwise I'll have to do normal maps, specify entity's surface type, etc... That's too complex! So yeah, I think hand drawn shadows are the way to go.

grumpaladin, thank you!  ;D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on November 27, 2016, 10:16:25 pm
New Re:creation dev log (https://eliasdaler.github.io/re-creation-devlog-july-november2016). Talking about what I've done in the last five months. I hope you find it interesting to read!
(http://i.imgur.com/R2F7YLf.gif)
Feel free to ask stuff about things mentioned here. And I'll probably start posting regurarly soon! Just didn't want to bore you with all the restructuring and refactoring. :D

P.S. One quick question for people who've done it before... How can I easily manage input contexts? (switch input callbacks during menus, interactions, etc.)
For example, if the player goes near some NPC, primary action button calls "interact" function, not "use primary item" button. Right now I manually handle such input changes, which means that I have to manually change input in menus or dialogues and later restore it to previous state... I'm afraid that it may lead to some nasty bugs!)
Title: Re:creation - a top down action adventure about undeads
Post by: sjaustirni on November 27, 2016, 10:30:17 pm
I haven't implemented complex GUIs yet, but if I did, I'd probably use a simple State Machine http://stackoverflow.com/questions/595231/state-machines-and-user-interface-work-any-examples-experience
https://en.wikipedia.org/wiki/Event-driven_finite-state_machine
https://developer.apple.com/library/content/documentation/General/Conceptual/GameplayKit_Guide/StateMachine.html
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on November 27, 2016, 11:05:32 pm
I haven't implemented complex GUIs yet, but if I did, I'd probably use a simple State Machine http://stackoverflow.com/questions/595231/state-machines-and-user-interface-work-any-examples-experience
https://en.wikipedia.org/wiki/Event-driven_finite-state_machine
https://developer.apple.com/library/content/documentation/General/Conceptual/GameplayKit_Guide/StateMachine.html
I already have state machines implemented. I have thought about FSMs for input, but seeing how much states and transitions I'll have makes me sad. :D

Just some examples. Input may have these states:
1) WASD - move, F - attack, T - become a ghost (normal state)
2) WASD - move, F - select a corpse, T - return to main body (recreation/ghost state)
3) WASD - move, F - interact, T - become a ghost (when possible to interact with entity)
4) WASD - move cursor, F - choose primary item, Enter - close the inventory (in Interaction state)
And then we have dialogues...
5) F - speed up the text (when text is being displayed)
6) F - next phrase/dialogue line (when all text in current phrase displayed)
7) AD - select answer, F - confirm.
etc.

Tons of states, tons of possible transitions... For example, suppose player goes near some NPC and talks to it.  Transitions: 1->3->5->6->3.
What if NPC goes away after the dialogue? We get this: 1->3->5->6->1.

(Or maybe this isn't that bad as I think? Maybe if I manually manage transitions in code, I can make it all maintainable...)
Title: Re:creation - a top down action adventure about undeads
Post by: sjaustirni on November 28, 2016, 03:15:22 pm
I do not have the needed insight, but it seems, that you  have 2 main states (non-dialogue and dialogue), with 2 more levels of depth for the former, whilst each state has up to 2 possible transitions.

Try to draw diagrams and also go hierarchical. FSMs are always easier with diagrams.
Title: Re:creation - a top down action adventure about undeads
Post by: Tukimitzu on December 05, 2016, 04:28:45 pm
Can you explain how did you made so your console input text box stay active after pressing enter?
(click to show/hide)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 06, 2016, 08:39:16 am
Can you explain how did you made so your console input text box stay active after pressing enter?
(click to show/hide)
Check out imgui_demo.cpp and how Console example is implemented there, it's pretty complex and I just copy-pasted this code (https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp#L2216).


The work on the game continues! And the biggest change I've made since the dev log is GUI implementation.
Previously I did GUI manually. Storing various sprites and GUI's state in GameStates, etc. But this causes the following problems:
1) Some GUI code was very repetitive
2) GUI was hard coded, I've manually set positions to each sprite and text string
3) GUI callbacks were in C++ which I don't like, because with most of the logic, game state and wrappers being in Lua, it's much easier to do things on Lua side.
4) I've managed to remove almost all GameState's, but GUIs were pretty hard to do in Lua, so I couldn't move GUI states there. (main menu, inventory screen, game UI, dialogue GUI, etc.)

My first idea was not the easiest one: I wanted to expose some of SFML's interface to Lua to draw GUI stuff from Lua and handle all the logic there too. Looking back at it now, it just looks like a really bad idea which would have cost me tons of hours!

Thankfully, after I've started making C++ GUI classes, I've realized that there's no need for doing drawing or even basic GUI logic in Lua! So, let's look at the current stuff I've got going. Here's how the main menu looks now (it isn't a final look, of course!)
(http://i.imgur.com/5YrAVXx.png)

Here's a JSON which defines it:
(click to show/hide)

As you can see, GUI has a few basic classes: StaticText, TextButton, Image, NinePatch. I can create children to any element and what's nice is that all positions are kept relative to the parent element, so it's easy to organize stuff! Right now the positions are still kinda hard coded (no automatic placement and aligning), but it's totally fine.
I can also add callbacks to buttons like this:
return {
        callbacks = {
                {
                        tag = "CONTINUE_BUTTON",
                        onPress = function(self)
                                continueGame()
                        end
                },
                {
                        tag = "NEW_GAME_BUTTON",
                        onPress = function(self)
                                print("NEW GAME IS NOT IMPLEMENTED YET")
                        end
                },
                {
                        tag = "EXIT_BUTTON",
                        onPress = function(self)
                                exitGame()
                        end
                }
        }
}

There's nothing novel about the implementation, just base GuiElement class which inherits from sf::Drawable and sf::Transformable, has some children and virtual load, update and draw functions.
Cursor has pretty nice input: it's kinda like key repeat, when you hold "down", it scrolls down the first time with bigger delay, but then continues scrolling down with less delay between "ticks". I manually keep track of time for delays to make it available to gamepad input and also not to depend on system settings (you can easly change delay of key repeat).

GUI system is already powerful, I've managed to make a Dialogue GUI with it!
(http://i.imgur.com/wH0lbnV.png)
It looks and behaves the same way as the old GUI, but now it's much easier to control it, drawing it is just this:
target.draw(gui);

I will also implement main game UI next and also inventory screen. They will be a bit trickier to make, but it'll be so worth it. I'll also do options menu which will require some additional GUI work, but this will be done a bit later.

So, handling GUI is much easier now, but the best thing about it is that now I can have just a bunch of GameStates: MenuState (all the GUI will be there: main menu, dialogue, inventory screen, game UI, etc. and I'll just switch between them), LoadingState, GameState (which just calls updates to entity systems and rendering system draw function), TransitionState (used to in-between areas transitions, very tricky, uses some shaders, so I don't want to do it in Lua) and that's it! Other game states (mini-games, ghost state, etc.) can be easily implemented in Lua now.

They don't contain any of the game logic, all of it is now in Lua and this makes me incredibly happy! Engine and game are almost separate now, which means that it'll be easy for me to reuse my engine for other projects in the future.


I've also started working on AI... and there's so many things I have to do here! Better state machines (or maybe even planning system), better path finding... Path finding aspect is pretty hard to do, because I'll have to implement some algorithm for automatically building a nav-mesh (or maybe I'll be fine with just using grid graphs?) I don't want to create graphs by hand, it'll take lots of time and in the end it doesn't give very good results.

Some games just use steering behaviours for AI (and I've previously used just them too!), but this is only fine as long as your enemies are some monsters or "possesed" people (older Zelda games only use steering algorithms). I want enemies in my game be a just bit smarter and not get stuck in any obstacles on their way.

(http://i.imgur.com/blavawF.png)
Enemies in Link to the Past get stuck all the time. They don't get completely stuck, however, because steering algorithm slides them along the wall. But it's still not as good as proper path finding. (Or maybe I'm overthinking it...)

Hope implementation of all that stuff won't take long. But I'm a bit glad that I'll finally get the chance to write all this stuff.


But that's not all. I'm also planning to work on combat system and I'll try to make combos, targeting and dodging to feel good. I want combat to feel a bit like it does in Dark Souls or 3d Zeldas. Basically, you approach the enemy, target it and now can circle around it, dodging it's hits and hitting it with combos. Not sure how it would work in 4 directions (it would have been perfect in 8 directions, but I can't draw so many animations!), and so far I haven't seen any 2d action rpgs with complex combat, so it'll be pretty interesting to see what I can do.

The closest to what I want is Bastion (hey, the main character uses hammer too!), but it uses isometric perspective and has 8 directions. If anyone knows good 2d top-down games with good melee combat system, please tell me about it! ;D
Title: Re:creation - a top down action adventure about undeads
Post by: shadowmouse on December 06, 2016, 11:36:17 pm
If you want to be adventurous, Hyper Light Drifter has a pretty cool combat system iirc. It's not exactly like re:creation, but it is a 2d top down 8/16 style game, so I reckon if you use basic 2d Zelda combat as your base, you could take influence from more complicated systems like that of Hyper Light Drifter.
Title: Re:creation - a top down action adventure about undeads
Post by: dabbertorres on December 07, 2016, 02:54:01 am
Here's what I can think of that I've enjoyed:

Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 09, 2016, 08:40:14 am
Thanks for suggestions, guys! I'll totally check them all out. :D

I've also started working on AI!
(http://i.imgur.com/rIDHRLM.gif)
The red path is original path found using Dijkstra's algorithm (going to implement A* soon!), the green line is "smoothed" path which just removes unnecessary edges to give even more efficient and natural paths.
The grid graph is created with a bit of brute force... I create a grid and then remove all vertices/edges which collide with the level. This gives somewhat okay result, though it's not very fast and very likely to be improved in the future.

I'm really glad it was pretty fast and easy to implement, there isn't much want to improve there! One more thing I'll soon add is wall avoidance which will make the movement even better.

From there I plan to implement a bit better AI state machines (or maybe I'll use behavioural trees and some goal planning behaviour). Some games use very simple AI, because the enemies are just some random monsters which may stuck in walls and it'll look okay, but in Re:creation you're mostly fighting with people, so they have to be somewhat intelligent, but of course I'm not going to make something overly complex.
Title: Re:creation - a top down action adventure about undeads
Post by: Mario on December 09, 2016, 10:51:20 am
To be honest this sounds a bit overkill for a tile based game with rectangular areas only. :) I'd try using some splines or bezier curve for the green path. Add some random deviation for a more natural movement and you should be fine.

Btw. you shouldn't have to create your navigation mesh before I think (although it's probably helpful). Have you tried just associating infinite costs with paths going through geometry?
Title: Re:creation - a top down action adventure about undeads
Post by: Mortal on December 09, 2016, 04:20:06 pm
it looks really neat,  :)

have you tested with U-shape ?
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 10, 2016, 10:11:28 pm
Mario, but as you can see, there are rotated boxes which don't work with grids well. As for bezier curves... that's a possibility, but too much work, as for now. Maybe I'll add them later.
I think I'll just use grid based graphs with some edges and vertices removed just like I do in this demo. Probably will work fine! :D

Mortal, thank you! What do you mean by U-shape?
Title: Re:creation - a top down action adventure about undeads
Post by: Mortal on December 11, 2016, 12:05:23 am
i mean the worst nightmare of Dijkstra’s algorithm, according to this site (http://theory.stanford.edu/~amitp/GameProgramming/AStarComparison.html)  ;D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on December 11, 2016, 09:25:16 am
Dijkstra’s algorithm will consider a lot of edges, but will still work in the case of U-shape. Perfomance is not critical for pathfinding at this point, as it's still very fast compared to rendering and collision. I'll write A* soon, though. :D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on April 19, 2017, 11:36:39 pm
It's alive!
(http://i.imgur.com/VmM5VRa.gif)
Sorry for the silence: I wanted to make a huge dev log once I've made a lot of new art and gameplay stuff, but the semester got hard and I only had time to work on engine stuff, but still made a significant progress.
Here's the latest dev log: https://eliasdaler.github.io/re-creation-devlog-december-march/

Hope you like it! And I hope that the next one will contain a lot more new things in it, not just engine/code related details.
Title: Re:creation - a top down action adventure about undeads
Post by: Mario on April 20, 2017, 10:43:45 am
Would really be interested to see how your C++/Lua interaction works, especially considering the subclassing (in this example components). Are you just copying metatables around or are you doing more?
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on April 20, 2017, 10:59:42 am
Would really be interested to see how your C++/Lua interaction works, especially considering the subclassing (in this example components). Are you just copying metatables around or are you doing more?
I use middleclass (https://github.com/kikito/middleclass) for OOP, and yes, it just copies metatables and for subclassing it stores base class metatable.

As for C++/Lua interaction. It mostly happens via events.For example, collision system checks for all the collisions and if they happen, it adds collision even to global event queue. After all systems finished processing, C++ calls Lua's "processEvent" function which calls callbacks for each happened event. Here's an example of enemy's callback on damage (it's going to get more complex later, but it works for now!):
callback = function(entity, event)
    if entity:getCurrentStateName() ~= "HurtState" then
      playSound("enemy_hit")
      local health = entity.components.health
      if health:getHealth() > 0 then
          entity:changeState("HurtState")
          health:decreaseHealth(event.data.damageAmount)
      end
    end
end

All Lua's components are currently accessed in Lua scripts only, so I don't have to deal with C++ getting components from Lua, as these components are very game-specific and game-specific things don't happen on C++ side anymore! :)
Title: Re:creation - a top down action adventure about undeads
Post by: Mario on April 20, 2017, 11:22:07 am
Cool, didn't know that library so far. :)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on April 20, 2017, 11:26:49 am
Cool, didn't know that library so far. :)
It's very convenient for OOP. And check out other kikito's repositories, he does a lot of useful Lua (and not only) stuff. :D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on May 19, 2017, 11:37:08 pm
I'm back! Starting out slowly, but with lots of confidence. Can't promise much, as I have lots of study to do (3 homeworks, 3 big projects, exams coming up, ugh!)
So, first of all, I was a little afraid that I'll look at the code and be either confused or have a burning desire to fix a lot of stuff in it. But thankfully major recent refactorings came out pretty well, so I started working on the game right away.

First, I decided to make platforms which follow waypoints.Waypoints are just entities without any components. All I need is to position them in the world and have platform follow them. Of course, this will also be used for other entities, like humans following predetermined paths.

I still have no idea how to store paths in a good way, so right now I just hardcode them by their tags. Each waypoint just gets a tag like "waypoint1", "waypoint2", etc. The path is stored in Lua like this:
somePath = { "waypoint1", "waypoint2", "waypoint3" }
Maybe I'll store them in map files at some point.

And then I realized that I can't set tag via level editor interface (previously I set them by hand in map file, ha-ha), so I quickly made this:
(http://i.imgur.com/GZYmcE4.gif)
ImGui is trully brilliant for such quick and useful interfaces.

And then I've made platforms follow the path. It was very easy. I created FollowPathAction which is an action which can be used in action lists. It stores an array of waypoint tags and then iterates over them, creating GoToAction for each waypoint until the end of the path is reached. I've also made some additional conditions there:
The result looks like this:
(http://i.imgur.com/z1YaT12.gif)

Nice! It took me 3-4 hours to make all this stuff (with some small bug-fixing of other stuff that I discovered was broken), so it's pretty nice how quickly I can make some gameplay things. :)

Next up is tile collision porting from my test project which has diagonal collisions. I also want to some simple tile interactions. For example, running on grass vs rock will have different sounds, running on tiles with sand will leave footprints, etc. I'll also use this system to implement falling into pits, because right now you can't do that! :D

P.S. I've also made some nice organization change: now all transform related things (position, facing direction) are grouped in Transform component, all child-parent related things are in HierarchyComponent, so now I do something like this:
auto pos = someEntity.transform.getPosition();
/* ... */
someEntity.hierarchy.addChild(otherEntity);
I made this components public, so I could have easy access to them, instead of calling template get<ComponentType> function every time. Not much difference, but the code looks less noisy. :)
Title: Re:creation - a top down action adventure about undeads
Post by: FRex on May 20, 2017, 01:39:04 pm
Why a pop up and not an edit box right in the same window? I thought more modern UX/UI is moving away from such pop ups.
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on May 20, 2017, 03:01:39 pm
Why a pop up and not an edit box right in the same window? I thought more modern UX/UI is moving away from such pop ups.
Hmm, I just found popups easier to implement, because for edit box in the same window to work, I need to somehow catch event of exiting edit box and then apply it to entity. I'll see if it's easy to do with ImGui, I agree that it'll be better. Maybe I'll even make property table like this:
(https://www.mathworks.com/matlabcentral/mlc-downloads/downloads/submissions/38864/versions/7/screenshot.jpg)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on June 01, 2017, 09:09:51 pm
Okay, I've made lots of stuff again!

Tile collision, falling into pits
First of all, you can fall into pits now.
(http://i.imgur.com/PZJAVne.gif)

For that to work, I had to integrate previously implemented collision detection into my game. This only took several hours, but now I have diagonal collision as well, which will allow me to make more interesting levels!
(http://i.imgur.com/o7lnoCu.gif)

I also used cornering system from tiles to entities as well, so that hero now doesn't get stuck on corners of another objects and gets pushed it needed direction automatically.
(http://i.imgur.com/k984dZ5.gif)

So, how does falling work?
Now in every frame I check if common tile of entity changes. As most entities don't occupy many tiles, I just iterate over all tiles it intersects and if all of them are of the same type (e.g. "fall tiles"), I send CommonTileChanged event. Hero's state machine catches that event, sees that common tile is now a "fall tile" and changes hero's current state to FallState.
This will work with other systems good as well, for example if I add footstep sounds, I will use CommonTileChanged event to change walking sounds from "grass" footsteps to "rock" footsteps, depending on which tiles player walks on.

Platforms
Things don't stop here. If player steps on the platform, he doesn't fall! This is not as simple as it looks, but I'm glad I didn't have to hardcode it.
(http://i.imgur.com/svSdh2n.gif)

When player collides with platform, CollisionEvent is queued. CommonTileChanged event is queued too, but as CollisionSystem checks collisions before TileCollisionSystem, CollisionEvents is processed first afterwards. When something collides with moving platform, it adds it to child list (if it wasn't added before). Hero becomes a child of moving platform and inherits platform's position (moves with it).
Then CommonTileChanged event is checked, but in the callback I check if entity has a parent or not. If it does, it won't go to FallState, so the hero doesn't fall into a pit, as it has moving platform as a parent. I'll probably make it event more explicit, maybe I'll add isFlying flag which will be true for moving platform and later in CommonTileChanged callback I'll check it on parent of entity which is about to fall down. I'll see what works the best. :)

Huge changes to ECS implementation
I've also checked out EntityX (https://github.com/alecthomas/entityx) source code and found some very useful things which I liked about its implementation. In my implementation references to components of currently active entities were stored in corresponding systems. So, CollisionSystem had vector of references to CollisionComponents. But now I implemented the system which allows me just to do this:

for(auto& e : entityManager.getEntitiesWith<CollisionComponent, MovementComponent>()) {
    auto& mc = e.get<MovementComponent>();
    auto& cc = e.get<CollisionComponent>();
    ... // do something
}
Nice! This allows me to always get active entities with needed components and not have to store and constantly update component lists as entities get deactivated or components get disabled.

The implementation is pretty simple. First of all, each component type get unique id from 0 to N. And I also started to store all entity's components in a std::array<std::unique_ptr<Component>, MAX_COMPONENTS>. I don't have a lot of component types (I'm only counting those implemented in C++, low level ones!), so this array is very small and holds pointers after all. But this means that I can get needed components very fast just by using their unique id as an array index! I previously used unordered_map for getting storing components and getting components was pretty slow, especially when done frequently, it became noticeable in profiler.
I can also now very quickly test if entity has needed components or not. I store activeComponentMask bitset which has bits set to 1 in corresponding positions if component is active (not only present, but active, as I can sometimes disable collision, for example!).

EntityManager stores ids of currently active entities (entities nearby the hero which need to be updated) and getEntitiesWith returns EntityView object which is then used for easy iteration. Iterator just checks if entity has needed components by comparing mask being searched to activeComponentMask. It all works very fast even with lots of entities, which makes me very happy, as I don't have to store component lists anywhere now.

Iterating over tile indices
I've also implemented cool range/iterator for 2d indices. I had lots of code like this:
const auto tilesIdx = TileMap::getTileIndicesInRect(boundingBox);
// tilesIdx is sf::IntRect which has (left-top) set to left-top tile in range and (width, height) correspond number of X and Y tiles
for (int y = 0; y < tilesIdx.height; ++y) {
    for (int x = 0; x < tilesIdx.width; ++x) {
    // for all tiles that entity intersects...
        const TileIndex tileIndex(tilesIdx.left + x, tilesIdx.top + y); // this is sf::Vector 2f
        const auto& tile = tileMap.getTile(tileIndex);
        ... // do something
But this got really annoying as I wrote this code again and again... And then I realized, what if I make range which returns indices like this?
(0, 0), (1, 0), (2, 0), ... (5, 0), (0, 1), (1, 1), ...
And I've made this range by implementing RowColumnIterator which operator++ increases x if it's less than number of X tiles in range. And it worked perfectly! Now I just write code like this:
for(const auto& tileIndex : TileMap::getTileIndicesInRect(boundingBox)) {
    const auto& tile = tileMap.getTile(tileIndex);
    ... // do something
}
Much better!
Title: Re:creation - a top down action adventure about undeads
Post by: Ethan.Calabria on June 03, 2017, 06:52:07 pm
That's a great falling animation!

It's always really interesting to me to see how other developers program their engines...there's a lot of ways to accomplish things I never would have thought of with my own style.
Title: Re:creation - a top down action adventure about undeads
Post by: Carlos Augusto Br Cpp on June 04, 2017, 12:38:00 am
Hey Elias... when will you give to us the grace of an demo?  :D
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on June 04, 2017, 03:13:20 pm
That's a great falling animation!

It's always really interesting to me to see how other developers program their engines...there's a lot of ways to accomplish things I never would have thought of with my own style.
Thanks! I wish more people talked about their engines in depth. It would really help other people learn. :)

Hey Elias... when will you give to us the grace of an demo?  :D
Sorry, I have no idea. It's hard to work regularly with lots of study needed to do, plus I'm just starting to actually use my engine and not add new features all the time, so hopefully I'll get some estimate in a 2-3 months of work on the game. :)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on June 12, 2017, 11:37:25 pm
First of all...this thread have reached over 100,000 views!

I want to thank everyone for reading this thread and making it so awesome with your replies. I didn't think that my game will get so much attention and so I'm very glad it happened like this. Thank you.

What to you think of the thread so far? Anything that you want me to write more about or something unrelated to current progress that you want to discuss? :)


And it's time for another dev log!
Things are progressing quite well. I don't have much time to work on the game, but it's great to see how much I'm able to do with so little time!

AI field of view
I've used rectangles for AI previously, but it didn't work so well because human field of view doesn't quite work like that. I had no idea how to implement "circle sector" field of view, but it turned out to be pretty simple.
First of all, I wanted some way to visualize each entity's field of view. Thankfully, SFML has sf::PrimitiveType::TriangleFan for sf::VertexArray, so implementing CircleSector class was very simple.
(http://i.imgur.com/vyl5bJy.gif)
Then came implementation for AI. So, here's what I do
1) Find all entities which are closer than circle's radius
2) Calculate dot product of enemy's heading and ||playerPosition - enemyPosition||. If it's less than cos(viewAngle/2) then player is in enemy's field of view.
Here's a picture for you to visualize what's happening:
(http://i.imgur.com/waQ9FSG.png)
3) Check if any obstacles or solid tiles are on the way between enemy and player. This is done via ray-tracing. Right now I use one ray which goes from enemy to player, but one ray may not be enough because of situations like this:
(http://i.imgur.com/aae4a6R.png)
Instead, I'll use three parallel (or maybe at small angle?) rays so that this will happen instead:
(http://i.imgur.com/yo5Wszd.png)

Entity's heading
Previously entities could only face four directions only: up, left, down and right. This came from animations being drawn only in four directions, so I didn't have direction vector. But having it is certainly is useful, especially for AI! This also lets me easily compute current entity animation direction based on current heading.
As you can see here, archer's field of view turns smoothly instead of player's discrete heading movement (that's because I'm using keyboard to move, only gamepad's stick can be used to achieve smoother movement)
(http://i.imgur.com/bWd44uw.gif)
This seemed like a pretty big change for me, but good encapsulation helped me implement this in a few minutes! There were lots of calls like this:
someEntity.transform.setDirection(Direction::Down);
So, all I had to do now is to set needed heading to (0, 1) instead of setting direction variable to Direction.Down. I've also had to rewrite getDirection function to return one of four directions based on heading variable, but that was pretty easy to do, of course. And that's all I had to change in regards to previous direction variable being used by some systems. Imagine if this field was public? Ohh, I'd have to change a lot! So, getters and setters can be an important time-saver sometimes!

Improved archer's AI
After field of view improvement I decided to tune archer's AI a bit. I made archer follow the player so that he could get a better shot. The algorithm is pretty simple right now, so I won't explain it.
(http://i.imgur.com/LaCV0gD.gif)
As AI gets more complex, I'm thinking about trying to use behaviour trees, but we'll see, maybe state machines with some simple goal based system will work just fine! If anyone dealt with behaviour trees before, please tell me your experience with them.

Small (but important) changes
First of all, I've finally started to render stuff to sf::RenderTexture so that I will always get pixel perfect rendering even when rotating/scaling stuff. It also prevents tearing even at weird resolutions and also allows me to easily apply shaders to the whole frame.
And by the way, when I enter level editor, I start to render to window which can be of any size, so that I can zoom level out and still see things clearly.

I also finally moved origin of entity's position from top-left sprite corner to center of its collision box like this:
(http://i.imgur.com/mdaD6SI.png)
This makes a lot of things easier to handle as I usually want to position entities next to each other based on this origin, not on top-left corner of the sprite which is not useful at all. Using center of collision box as origin allows me to only store collision box size and I can easily calculate worldBoundingBox from player's current position and this size. This origin is also used for AI's field of view which works just fine. I'll also change sprite's origin based on current animation (e.g. if entity changes origin relative to frame boundaries).

And I also finally separated Animation from GraphicsComponent making AnimationComponent. This simplified a lot of things and I should have done it sooner, but oh well. The new AnimationSystem takes care of all animation related things and makes RenderingSystem's code even more simple.
Title: Re:creation - a top down action adventure about undeads
Post by: BluFedora on August 11, 2017, 07:54:56 pm
Hey for the Archer AI (if you aren’t already), you should use the player’s heading to determine a direction to overshoot the arrow as to add a nice sense of difficulty. This would encourage quicker reflexes. Of course it’s your game but I want to help with this small suggestion. 😀
Title: Re:creation - a top down action adventure about undeads
Post by: Schorsch on March 20, 2018, 02:34:13 pm
Hey,
do you still develop on this game? I saw on twitter that you have another project with this games engine. Will you return to this one?
Title: Re:creation - a top down action adventure about undeads
Post by: eXpl0it3r on March 20, 2018, 02:40:46 pm
Checkout Elias' "2017" blog post (https://eliasdaler.github.io/2017/) where he explains the current situation with Re:creation. :)
Title: Re:creation - a top down action adventure about undeads
Post by: Elias Daler on March 23, 2018, 09:54:14 am
Yes, situation is still the same. I'm working hard on Tomb Painter now. Re:creation is put on a shelf for now.
You can see Tomb Painter stuff on my Twitter (https://twitter.com/EliasDaler), and I'll make a thread for it here soon. :)
Title: Re:creation - a top down action adventure about undeads [hiatus]
Post by: AnhBao on August 30, 2021, 09:47:13 pm
Hello :> I'm new guy to game dev, ECS. Sfml and a bunch of things. I just want to ask that it has been 2 or 3 years, have you released the game? Can I find it somewhere? And your project is so cool and awesome, you really spent lots of time for it, which maybe I will never be able to do. Thats all I want to say, amazing work you did, so wonderful!