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

Login with username, password and session length

 
Advanced search

1363100 Posts in 63672 Topics- by 55558 Members - Latest Member: monikasingh

July 20, 2019, 12:19:14 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityDevLogsRe:creation - action adventure game about undeads
Pages: 1 [2] 3 4 ... 9
Print
Author Topic: Re:creation - action adventure game about undeads  (Read 17669 times)
eliasdaler
Level 1
*



View Profile WWW
« Reply #20 on: August 21, 2015, 07:49:08 AM »

Making walking animations.



I've made enemies more detalized. I'm a lot more satisfied with how they looks now.


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)
Logged


Re:creation dev | Blog | @EliasDaler
LeviFSG
Level 0
**



View Profile
« Reply #21 on: August 22, 2015, 07:33:05 AM »

Sounds good, but I also have no idea how that would pan out considering no one did it! Someone has to be the first, right Smiley? Following this thread, I love the little programming explanations you added!
Logged
eliasdaler
Level 1
*



View Profile WWW
« Reply #22 on: August 23, 2015, 01:10:32 AM »

@ShalottFSG I don't think my game's idea is novel. Well, Prototype had this gameplay mechanic and I've also heard about some other game which had the same mechanic too (I don't remember the name). I didn't play in these games though. The point is: this idea is not overused and there's a lot of stuff to do with it, so I'm still trying to figure out what I can do with it. Some puzzles work pretty neat already. :D
And thanks!

Also, here's a progress update!
New character! A mysterious cute cat with no name. (yet)


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.
Logged


Re:creation dev | Blog | @EliasDaler
LeviFSG
Level 0
**



View Profile
« Reply #23 on: August 23, 2015, 05:59:13 AM »

Lovely sprite art  Smiley
Logged
eliasdaler
Level 1
*



View Profile WWW
« Reply #24 on: August 24, 2015, 02:18:54 PM »

Lovely sprite art  Smiley

Thanks!
Logged


Re:creation dev | Blog | @EliasDaler
eliasdaler
Level 1
*



View Profile WWW
« Reply #25 on: August 27, 2015, 09:23:39 AM »

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!)


Another carpet:
Logged


Re:creation dev | Blog | @EliasDaler
Cyril
Level 0
**


View Profile
« Reply #26 on: August 27, 2015, 01:26:07 PM »

I enjoy the colors in this game. And I like that you have added the cat. Btw, I have 3 in real life.  Coffee
Logged
JobLeonard
Level 10
*****



View Profile
« Reply #27 on: August 28, 2015, 01:30:10 AM »

That cat. I don't trust him. He's up to something, I know it. -_-
Logged
Adinimys
Level 0
**


View Profile
« Reply #28 on: August 28, 2015, 02:20:49 AM »

Hello eliasdaler   Smiley

I just registered on the forum and when I saw that you had a thread here I though that I should go say hello. Your posts on using LuaBridge in C++ helped me a lot to get started integrating Lua in my C++ engine built with SFML so thanks a lot !  Grin

Good luck for your project, I really like the art style and your work is really inspiring for me as I use the same tools as you for building my game.
And the idea of solving puzzles by taking control of dead bodies is nice. Count me in if you need playtesters at some point Smiley
Logged
eliasdaler
Level 1
*



View Profile WWW
« Reply #29 on: August 28, 2015, 08:07:45 AM »

@Cyril, thanks! Somehow, I don't spend too much time looking for perfect colors. I guess it's just a skill I've gained. Glad you like the cat, I like it too! :D

@JobLeonard, even I don't know what he's up to!

@Adinimys, glad you liked them, you're welcome. Thanks for you kind words. Smiley
Do you have a link to your game's dev log/blog/site?

By the way, my awesome GF made this for me!


Zelda's "Got item" sound
Logged


Re:creation dev | Blog | @EliasDaler
Adinimys
Level 0
**


View Profile
« Reply #30 on: August 30, 2015, 01:52:39 AM »

Quote
Do you have a link to your game's dev log/blog/site?

No I haven't started one yet. I'm quite inexperienced in programing and I feel that trying to write a blog about the design of my little humble engine would only result in a big mess ^^

Here is a digression about my current work. I hope it's not bothering you to have it in your thread, I'll remove it if it's a problem :

<digression>
Right now I'm experimenting with LuaBridge, I find the documentation not to be the best that could be (but I've never coded in Lua before so that might be the reason of my issues). I'm trying to figure out how to divide my code between C++ and Lua. I thought of having the core classes of gameplay in C++ (like a Monster class) and add variables and methods in Lua (like for ex a Vampire would be a Monster and in Lua I would give him a BloodCounter variable) but I don't manage to do that. I don't know if the best way is to try to "inherit" from monster or if I can in Lua have my Vampire = Monster() then do Vampire["BloodCounter"] = 1.
It seems that the second option is not working like an usual "Lua native" table... and I don't know how to do this.

I thought about doing like you did for the interactions (the witch for example) and call from C++ functions that would be defined in Lua as well as having the content of variables in Lua. But if I'm not mistaken this way I wouldn't be able to add a variable or a method in Lua and this is crippling for the possibilities of modifications without recompiling.
</digression>

To go back to your work, how long did you spend working on the engine ? It's starting to feel long for me and I would like to start coding the real game right now but first I need this damn script to be useful ^^
Logged
eliasdaler
Level 1
*



View Profile WWW
« Reply #31 on: August 31, 2015, 10:48:23 PM »

@Adinimys, no problems, the discussion of various methods is a worthy topic.
I'm not experienced with using classic OOP for game dev so I can't say a lot about this.
First of all, you should read Programming in Lua which is free online and a good read.
I have no idea how to inherit from C++ classes in Lua (not sure if it's even possible). I suggest you to inherit from base classes in C++ and then override some functions from the base class so that they call other functions in Lua.

For example, suppose you have

Code: (cpp)
class Monster

Now you have some classes like

Code: (cpp)
class Vampire : public Monster

and

Code: (cpp)
class Troll : public Monster

You can then define their interact() functions like this:

Code: (cpp)
void Vampire::interact(...) {
    // call vampire.interact function in Lua
}

Code: (cpp)
void Troll::interact(...) {
   // call troll.interact function in Lua
}

So, you can have vampire and troll table which define interaction functions in Lua (and some other stuff, like collision responce function, for example. Or some vamrire and troll stats (moving speed, health, etc.).

But you see, the inheritance is not really needed anymore

You can have pointers to interact and collision response functions in a Monster class by setting vampire.interact to one Monster and troll.interact to another. So, this makes the inheritance tree easier. But if you really need inheritance in this case, use the method I've proposed later. You will still gain a lot from Lua.
If you have some more questions, create another thread or feel free to write me, [email protected]

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:

Code: (cpp)
class IComponentList {
...
};

and this class:

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

and then this map:

Code: (cpp)
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:

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

Code: (cpp)
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).
« Last Edit: August 31, 2015, 11:33:33 PM by eliasdaler » Logged


Re:creation dev | Blog | @EliasDaler
Samson
Level 0
**


View Profile
« Reply #32 on: September 01, 2015, 08:54:31 AM »

This is a neat concept. Happy to see you explain your process as well.  Smiley

However I do feel the need to say, it's fairly obvious to me that some of your art assets are heavily based on a link to the past. That's fine! It's a well loved style, but just be careful. I wouldn't expect Nintendo breathing down your neck, but I remember the trouble the Midora folks went though.

From a purely aesthetic standpoint, this results in some of LTTP-like art clashing with the other stuff (or vice-versa). I think you would do well to keep things a little more consistent; you clearly have the skills.

Good luck!
« Last Edit: September 01, 2015, 09:00:35 AM by Samson » Logged
eliasdaler
Level 1
*



View Profile WWW
« Reply #33 on: September 01, 2015, 11:10:46 AM »

@Samson, thanks!
Are there any particular assets which look too similar to LTTP?
I don't copy-paste any art from other games but sometimes I need to draw sprites which are so small that there's no way for two sprites to be completely different. For example, the arrow sprite. It's one pixel wide, there's not many ways to draw the arrowhead which would look great, etc.
Logged


Re:creation dev | Blog | @EliasDaler
Samson
Level 0
**


View Profile
« Reply #34 on: September 01, 2015, 11:24:54 AM »

Hi there! It's difficult not to sound accusatory, but It's not a massive problem. I know you aren't copying.
The image that made me decide to mention it was your prison-looking area in your first post. Compare it to:



Like you say, there's only so many ways to do these things, and LTTP is great inspiration.
Logged
eliasdaler
Level 1
*



View Profile WWW
« Reply #35 on: September 01, 2015, 01:13:58 PM »

Yeah, I realize that it looks pretty similar. But this is because I copied the perspective used for cells. I tried to make the cell look as different as possible while still maintaining this perspective. Smiley
Logged


Re:creation dev | Blog | @EliasDaler
Myran
Level 0
**



View Profile
« Reply #36 on: September 01, 2015, 03:08:45 PM »

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.
I have a somewhat similar case for units in my engine, I allocate them continously and of course get the problem with invalidated pointers and stuff. So the way I solved it was to use relative pointers instead of absolute ones.
So basically I have a scene with an array of units and another array of what units are in use. Whenever I need to make a new unit I look through the array of what units are in use and if I find one that isn't in use I pick that one, otherwise I allocate a new, bigger, unit array and memcopy all old units to the new one.
Whenever I would usually use a Unit* I instead use a custom class which contains just the index that this unit is in the scenes big unit array and to dereference it I just take the scenes unit array pointer and offset it by that index.
In some places (basically in the script environment) I don't know what scene a Unit belongs to, for those cases I made a fat pointer that contains both the Unit index and a pointer to its scene.
If I destroy a unit I just mark it as not in use in the scenes array for that and it will eventually be reused.
Logged
eliasdaler
Level 1
*



View Profile WWW
« Reply #37 on: September 01, 2015, 08:28:54 PM »

@Myran, it's a good way of doing things. So, if you need to reallocate units, you can just change the index in Unit object and all objects which use it won't need to know about it?
Logged


Re:creation dev | Blog | @EliasDaler
eliasdaler
Level 1
*



View Profile WWW
« Reply #38 on: September 03, 2015, 09:11:55 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
Logged


Re:creation dev | Blog | @EliasDaler
zath
Level 0
**



View Profile
« Reply #39 on: September 04, 2015, 11:36:14 AM »

I hope you don't mind the discussion on the ECS design!

My approach to the similar problem was to create a block type (not really a type, just an alias):

Code:
        template <typename T>
        using DataBlock = std::array<DataContainer<T>, EntitiesPerBlock>;

        template <typename T>
        using DataBlockPtr = std::unique_ptr<DataBlock<T>>;

Then there's a class that's responsible for creating/destroying a structure that holds all components:

Code:
    template <typename T>
    class ComponentManager {
    // [...]
        ComponentManager(...) {
            typename priv::DataBlockPtr<T> ptr(new priv::DataBlock<T>);
            mDataBlocks.push_back(std::move(ptr));
        }

    private:
        std::vector<  std::unique_ptr< priv::DataBlock<T> >  > mDataBlocks;
    }

So every time the DataBlock is added to the vector, the component-holding structure is created for EntitiesPerBlock number of entities. I'm using unique_ptr so when vector reallocates objects, the memory of object is not touched at all, just a new unique_ptr is created. This way if I had any pointers flying around, they won't be invalidated due to vector's reallocations.

Now, DataContainer is just a struct that holds a boolean indicating whether entity is created/free, and some raw memory:

Code:
        template <typename T>
        struct DataContainer
        {
            bool   allocated{false};
            char   container[sizeof(T)];

            T& data() { return *(reinterpret_cast<T*>(container)); }
         };

Then when you want to create entity, you need no allocations at all (placement new):

Code:
        void receive(const EntityCreatedEvent& event)
        {
            auto& c = container(event.entity);
            if (c.allocated) {
                throw std::bad_alloc();
            }

            void* ptr = reinterpret_cast<void*>(c.container);
#ifndef ENGINE_DEBUG_MEM
            std::memset(ptr, ENGINE_DEBUG_TAKEN_SYMBOL, sizeof(T));
#endif
            // Constructor is called!     
            new (reinterpret_cast<void*>(ptr)) T;

            c.allocated = true;
        }

And when you need to destroy the entity, its components got destroyed as well, but no deallocation takes place:

Code:
       void receive(const EntityDestroyedEvent& event) {
           auto& c = container(event.entity);
           // [...]
           assert(c.allocated && "Deallocation of not allocated memory!");
           T* ptr = &(c.data());

           // Destroy component-holding structure
           ptr->~T();
#ifndef ENGINE_DEBUG_MEM
           std::memset(&c, ENGINE_DEBUG_RELEASED_SYMBOL, sizeof(T));
#endif
           c.allocated = false;
       }

I really wanted this kind of design because:
- it prevents pointer invalidations
- all components data are close to each other
- when making a save/load feature it's much easier just to dump/read a block of memory to/from the file. Each entity and references to other entities are just numbers (indices). There's the method to easily get list of components for given entity index. I try not to store any pointers (when possible) so when loading a state of game I don't need to do any/much pointer patching. Just load block of memory and you're ready.

Have you tried/considered similar approach?
Logged

Pages: 1 [2] 3 4 ... 9
Print
Jump to:  

Theme orange-lt created by panic