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 440119 times)

0 Members and 1 Guest are viewing this topic.

Elias Daler

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

dabbertorres

  • Hero Member
  • *****
  • Posts: 506
    • View Profile
    • website/blog
Re:creation - a top down action adventure about undeads
« Reply #466 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.

Elias Daler

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

Mario

  • SFML Team
  • Hero Member
  • *****
  • Posts: 879
    • View Profile
Re:creation - a top down action adventure about undeads
« Reply #468 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)).
« Last Edit: January 06, 2016, 10:49:38 pm by Mario »

Elias Daler

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

ZackTheHuman

  • Newbie
  • *
  • Posts: 33
    • View Profile
Re:creation - a top down action adventure about undeads
« Reply #470 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.
Project Hikari Dev Blog: http://hikari.zackthehuman.com/blog/

Elias Daler

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

FRex

  • Hero Member
  • *****
  • Posts: 1845
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re:creation - a top down action adventure about undeads
« Reply #472 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.
Back to C++ gamedev with SFML in May 2023

Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re:creation - a top down action adventure about undeads
« Reply #473 on: January 08, 2016, 07:45:11 am »
That's good to know, thanks. But how is this better than using local tables?
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler

FRex

  • Hero Member
  • *****
  • Posts: 1845
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re:creation - a top down action adventure about undeads
« Reply #474 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.
Back to C++ gamedev with SFML in May 2023

Elias Daler

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

Elias Daler

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


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


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

Ironbell

  • Jr. Member
  • **
  • Posts: 61
    • View Profile
    • Cendric
Re:creation - a top down action adventure about undeads
« Reply #477 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.)

Elias Daler

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

SpeCter

  • Full Member
  • ***
  • Posts: 151
    • View Profile
Re:creation - a top down action adventure about undeads
« Reply #479 on: January 16, 2016, 10:14:53 am »
Well you did much groundwork and I think that your devspeed might skyrocket now :D