Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411423 Posts in 69363 Topics- by 58416 Members - Latest Member: JamesAGreen

April 19, 2024, 12:55:28 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityDevLogsRe:creation - action adventure game about undeads
Pages: 1 ... 3 4 [5] 6 7 ... 9
Print
Author Topic: Re:creation - action adventure game about undeads  (Read 27416 times)
eliasdaler
Guest
« Reply #80 on: December 16, 2015, 09:30:14 AM »

It's too early in the morning after a Ludum Dare all-nighter to comment on this Tired
How did it go? :D

... but I salute any fellow coder who cleans up his code Coffee
I do this all the time. After all, the less time you spend cleaning up the bad parts, the more crappy code you have to deal with later AT ONCE. :D
Logged
JobLeonard
Level 10
*****



View Profile
« Reply #81 on: December 16, 2015, 09:54:31 AM »

We created a katamari damacy/arena shmup in space hybrid:

http://ludumdare.com/compo/ludum-dare-34/?action=preview&uid=18490

Difficulty is completely unbalanced though

Anyway, yay to minimal technical debt!
Logged
eliasdaler
Guest
« Reply #82 on: December 16, 2015, 01:53:40 PM »

We created a katamari damacy/arena shmup in space hybrid:
http://ludumdare.com/compo/ludum-dare-34/?action=preview&uid=18490
Difficulty is completely unbalanced though
Nice job! Smiley


Progress update...
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:
Code: (cpp)
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:
  • Set property by name
  • Get property by name
  • Serialize to JSON
  • Deserialize from JSON
Let's look at the code:
Code: (cpp)
// 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:


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:
Code: (cpp)
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):
Code: (cpp)
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:
Code: (cpp)
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.
« Last Edit: December 16, 2015, 10:44:40 PM by eliasdaler » Logged
eliasdaler
Guest
« Reply #83 on: December 17, 2015, 06:14:35 AM »

TL;DR:


Thanks to Laurent's suggestions, I've made everything even more awesome.
I've tried out more complex classes and here are the results.
Animation class stays the same, let's add GraphicsComponent class:
Code: (cpp)
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:
Code: (cpp)
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) :
Code: (none)
{
"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:
Code: (cpp)
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:
Code: (cpp)
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:
Code: (cpp)
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.
Logged
eliasdaler
Guest
« Reply #84 on: December 29, 2015, 02:12:35 PM »

I'm almost done with this animation tool and it looks pretty neat. :D
Here's the process of creating up animation

Changing values in the table changes variables in C++ Animation instance (in previous gifs JSON itself was changed and animation was then reloaded), which can be easily serialized to JSON with just one line of code!
Code: (cpp)
file << Meta<Animation>::serialize(animation); // where file is std::ofstream
This creates the following JSON:
Code:
{
    "frameCount" : 8,
    "frameRect" :
    [
        100,
        0,
        24,
        24
    ],
    "frameTime" : 150,
    "looped" : false,
    "name" : "fall_start",
    "offset" :
    [
        0,
        0
    ]
}

As for other stuff... 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.
Logged
eliasdaler
Guest
« Reply #85 on: January 03, 2016, 01:37:51 PM »

Check out my latest blog post which summarizes what has been happening with Re:creation in 2015. Lots of pictures and gifs included. This has been a great year.
Read it here
Logged
eliasdaler
Guest
« Reply #86 on: January 05, 2016, 02:13:23 PM »

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:
Code: (lua)
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
Logged
eliasdaler
Guest
« Reply #87 on: January 08, 2016, 12:30:21 AM »

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 Grin
https://eliasdaler.wordpress.com/2016/01/07/using-lua-with-c-in-practice-part4/

And 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.
Code: (lua)
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)
Logged
Drof
Level 0
***



View Profile WWW
« Reply #88 on: January 08, 2016, 05:35:50 AM »

It's looking good man! A few comments if you're interested.

I think the trees in your forest scenes seem a little out of place with how dark they are. They contrast a lot and make them seem much more important than they really are, which feels unsettling to me.

I think your environments are best when they communicate an atmosphere. The city scene with the fog looks amazing, although I think it would be a bit better with a style similar to the lost woods in aLttP. Perhaps a suggestion is to approach environments from the angle of something like Nifflas' Knytt games? Bugs buzzing around, leaves falling to the ground, stuff like that. I think it would be really next-level polish.

Also, a question since I also program:

Do you think the amount of work you've done setting up tools and cleaning up code is worth it in the end? I find I can lose weeks to refactoring and cleaning up, only to discover what I really need out of the code and have to refactor it again anyways. At this point, I pretty much only refactor or set up a tool if I know it'll save hours put into the project.

I've never made any serious tools other than unity editor scripts, so I'm not sure how much time it usually takes to do these things.
Logged

eliasdaler
Guest
« Reply #89 on: January 08, 2016, 11:18:04 PM »

It's looking good man! A few comments if you're interested.
Thanks!

I think the trees in your forest scenes seem a little out of place with how dark they are. They contrast a lot and make them seem much more important than they really are, which feels unsettling to me.
That's a valid point. I'll see if I can fix it without redoing much stuff :D

Perhaps a suggestion is to approach environments from the angle of something like Nifflas' Knytt games? Bugs buzzing around, leaves falling to the ground, stuff like that. I think it would be really next-level polish.
Good idea, I'm going to be trying out different stuff soon, so let's see how it goes. Particle system would be nice to have. Hope it won't be hard to make.


Also, a question since I also program:

Do you think the amount of work you've done setting up tools and cleaning up code is worth it in the end? I find I can lose weeks to refactoring and cleaning up, only to discover what I really need out of the code and have to refactor it again anyways. At this point, I pretty much only refactor or set up a tool if I know it'll save hours put into the project.

I've never made any serious tools other than unity editor scripts, so I'm not sure how much time it usually takes to do these things.
Yes, it was completely worth it. It takes time to develop tools, but if you do it right, it makes the game so much easier to develop. For example, I've spent a lot of time on level editor, but now I use it all the time and can quickly make/edit a level. Scripts are a great tool too. They make it really easy to expand the game without modifying C++ code.

As for refactoring... Here's what I wrote in this blog post and want to cite again.

Quote from: Elias Daler
I don’t let my code rot that’s why I always improve it by refactoring, restructuring and decoupling. But I don’t just sit down and start refactoring just for its sake. It happens naturally. Sometimes it’s caused by bugs, sometimes it’s caused by the potential bugs. Refactoring is started by awkward interfaces which let me make mistakes or slow me down a lot.
Some refactoring happens when you implement something cool and then see how it can improve your code. For example, I started making event manager just for gameplay purposes but later figured out that this can help me decouple lots of stuff which led to very positive changes in my code!

But sometimes refactoring is needed when you are stuck. This is what happened this November with my project. First of all, I’ve tried to make fixed delta time for smoother camera movement. I’ve also wanted to make input, collision and other stuff update more frequently than rendering. But this was not possible, because rendering wasn’t completely decoupled and some stuff was just not possible to make with the old system.
As I started to rewrite stuff, I’ve noticed that some global variables were not needed anymore, some loops were easily replaced with std::find_if or std::remove_if, some raw pointers could be replaced with std::unique_ptr and so on.
Refactoring is almost always worth it if you notice problems with your initial design. Especially if it lets you do stuff wrong way. Code Complete and Effective C++ talk a lot about that. Smiley
Logged
Drof
Level 0
***



View Profile WWW
« Reply #90 on: January 09, 2016, 02:25:47 AM »

Refactoring is almost always worth it if you notice problems with your initial design. Especially if it lets you do stuff wrong way. Code Complete and Effective C++ talk a lot about that. Smiley

I think I'd like to offer a counterpoint to that - there isn't any point to refactoring code you won't need to reference again. Especially in long term projects, I think there's a danger of getting caught in a loop where you look at code you wrote years ago and realize there's now a better way to do it. That might be because you've gotten better, or simply that a new plugin is out there.

The thing I usually keep in mind is that refactoring isn't actually getting the game closer to being finished. For it to be useful, you have to save the time you put into it later on. It can't just be because it's better. Not saying that's what you're doing, but it's something that I bring up a lot when I'm faced with groan-worthy code. It might not be pleasant to work with, but if I don't have to see it much and it works, then it's better to move towards that finish line.

I've heard lots of good stuff about tools though. It really depends on what you're doing. I think any decent framework you lay down before actually putting in content can extremely speed up the process. I'm not usually faced with those problems, but I'm working on a relatively small game.
Logged

eliasdaler
Guest
« Reply #91 on: January 10, 2016, 02:07:48 PM »

Completely agreed. I have some awful code which works and I can ignore it for a long time. But as long as the code breaks something or the interface is too awkward to progress: I refactor it right away.
It's also important to at least remember where the awful code is, so once you have time, you can refactor it and make it work better. A simple // TODO is good enough in most cases. As long as it does the thing, doesn't break the game and doesn't make the game slow it's fine.
I'm just working too much time on the engine and so the good interface is really important for me, because that's what I'll use to make a game. And I don't want to hunt countless bugs because of my laziness. :D

Progress update
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


Code: (lua)
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
Logged
eliasdaler
Guest
« Reply #92 on: January 17, 2016, 11:45:40 PM »

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

I've spend lots of time drawing stuff in axonometric perspective and giving more volume to stuff.

Here's an old screenshot for comparison:


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


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. Smiley
Logged
eliasdaler
Guest
« Reply #93 on: January 23, 2016, 01:56:42 AM »

Meanwhile I've been redrawing stuff in Undead Cafe.
Here's how it looks now:

Old screenshot for comparison:


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


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)
Logged
eliasdaler
Guest
« Reply #94 on: January 30, 2016, 12:33:47 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.

Here's how this looks in Lua:
Code: (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!
Logged
Mr Bazooka
Level 0
**



View Profile
« Reply #95 on: January 30, 2016, 12:42:59 AM »

Just stopping by to say I love the concept!
Logged
JobLeonard
Level 10
*****



View Profile
« Reply #96 on: January 30, 2016, 01:16:12 AM »

Nice Earthbound reference Wink
Logged
eliasdaler
Guest
« Reply #97 on: January 30, 2016, 09:20:51 AM »

Just stopping by to say I love the concept!
Thank you!

Nice Earthbound reference Wink
Thanks. :D
At first I was too obvious with that reference:

...but then I decided to make it a bit more subtle and funnier :D (and make the joke fit the game more)
Logged
eliasdaler
Guest
« Reply #98 on: January 31, 2016, 07:36:32 AM »

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:





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
« Last Edit: January 31, 2016, 07:42:32 AM by eliasdaler » Logged
eliasdaler
Guest
« Reply #99 on: February 10, 2016, 12:20:49 AM »

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

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!


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:
Code: (lua)
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:
Code: (lua)
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
Logged
Pages: 1 ... 3 4 [5] 6 7 ... 9
Print
Jump to:  

Theme orange-lt created by panic