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

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

0 Members and 2 Guests are viewing this topic.

Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re:creation - a top down action rpg about undeads
« Reply #15 on: May 05, 2015, 12:41:52 am »

Made smooth level transition. Area name is displayed.
« Last Edit: May 05, 2015, 07:49:04 am by Elias Daler »
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler

fakepotato

  • Newbie
  • *
  • Posts: 39
    • View Profile
    • Email
Re:creation - a top down action rpg about undeads
« Reply #16 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!
Infinite insomnia.

Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re:creation - a top down action rpg about undeads
« Reply #17 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!
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler

Grimshaw

  • Hero Member
  • *****
  • Posts: 631
  • Nephilim SDK
    • View Profile
Re:creation - a top down action rpg about undeads
« Reply #18 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?

Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re:creation - a top down action rpg about undeads
« Reply #19 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).

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.
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler

Grimshaw

  • Hero Member
  • *****
  • Posts: 631
  • Nephilim SDK
    • View Profile
Re:creation - a top down action rpg about undeads
« Reply #20 on: May 05, 2015, 02:38:36 pm »
Thanks for your answer. You are a very sensible engineer, you only deserve praise here :)

Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re:creation - a top down action rpg about undeads
« Reply #21 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. :)
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re:creation - a top down action rpg about undeads
« Reply #22 on: May 06, 2015, 05:32:19 pm »
Wow. This looks amazing.
Well done.

iride

  • Jr. Member
  • **
  • Posts: 88
    • View Profile
    • Email
Re:creation - a top down action rpg about undeads
« Reply #23 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()]);
}
 

shadowmouse

  • Sr. Member
  • ****
  • Posts: 302
    • View Profile
Re:creation - a top down action rpg about undeads
« Reply #24 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.

Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re:creation - a top down action rpg about undeads
« Reply #25 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. :)
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler

Grimshaw

  • Hero Member
  • *****
  • Posts: 631
  • Nephilim SDK
    • View Profile
Re:creation - a top down action rpg about undeads
« Reply #26 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 :)

Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re:creation - a top down action rpg about undeads
« Reply #27 on: May 07, 2015, 07:55:42 am »
@Grimshaw Thanks! Glad to hear it. :)

Progress update.

Okay, so arrows are not hard coded anymore!

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. :)
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler

ChronicRat

  • Sr. Member
  • ****
  • Posts: 327
  • C++ programmer
    • View Profile
    • My blog
Re:creation - a top down action rpg about undeads
« Reply #28 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?

Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re:creation - a top down action rpg about undeads
« Reply #29 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. :)
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler