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

Author Topic: Tomb Painter - Game Boy inspired game about painting tombs  (Read 2671 times)

0 Members and 1 Guest are viewing this topic.

Elias Daler

  • Hero Member
  • *****
  • Posts: 587
    • View Profile
    • Blog
    • Email
Tomb Painter - Game Boy inspired game about painting tombs
« on: June 09, 2019, 11:12:04 am »

Site: https://eliasdaler.github.io/
Developer: Elias Daler - everything
Dev logs: https://eliasdaler.github.io/tags/#Tomb+Painter
Twitter: @eliasdaler
Platforms: PC, Mac, Linux
Start of development: August 2017
Release date: 202X (let's hope it's not 203X)

Hello, everyone! My name is Elias Daler and I'm making a game called Tomb Painter.
You may know me from Re:creation (which is now in hiatus), and here I am with another game.

In the game, a painter arrives on mysterious island, which has strange things going on with it. Blob-shaped monsters made of paint start to appear from an ancient tomb. The only way to stop this is to paint beautiful patterns which were washed away by a flood that happened some time ago.

The main mechanic is that you can draw on floors and paint stuff by hitting it with your brush. By painting on the floor, you solve different puzzles.







The game is done in 4 colors (technically it's sometimes 8, because it has two palettes from time to time) and in 160x144 resolution, just like Game Boy!
« Last Edit: June 09, 2019, 02:13:55 pm by Elias Daler »
Tomb Painter, Re:creation dev | eliasdaler.github.io | @EliasDaler | Tomb Painter dev log

Elias Daler

  • Hero Member
  • *****
  • Posts: 587
    • View Profile
    • Blog
    • Email
Re: Tomb Painter - Game Boy inspired game about painting tombs
« Reply #1 on: June 09, 2019, 11:12:15 am »
Tomb Painter started as a small prototype inspired by Minit. At first it looked like this:


I was pretty surprised that so much can be accomplished with only two colors, but I wanted a bit more detail, so I’ve decided to use 4 colors, just like Game Boy did:





The palette is applied as a shared, so it allows me to easily swap to any 4 color palette:



I've spent a lot of time making a painting system so that paint trails look good, and I'm quite proud of it!



Read more in first dev log I've posted a while ago. More technical details are too come soon. Currently I'm working on a level editor and it looks better and better every day:




Components are displayed and are editable in editor: https://gfycat.com/ambitiousheartyabyssiniangroundhornbill
Pixel perfect selection: https://gfycat.com/frenchgaseoushoiho
Tomb Painter, Re:creation dev | eliasdaler.github.io | @EliasDaler | Tomb Painter dev log

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 9299
    • View Profile
    • development blog
    • Email
Re: Tomb Painter - Game Boy inspired game about painting tombs
« Reply #2 on: June 09, 2019, 06:21:08 pm »
Awesome work as always! :)

Looking forward to getting a demo of this.
Official FAQ: https://www.sfml-dev.org/faq.php
Nightly Builds: https://www.nightlybuilds.ch/
——————————————————————
Dev Blog: https://dev.my-gate.net/
Thor: http://www.bromeon.ch/libraries/thor/

pvigier

  • Newbie
  • *
  • Posts: 9
    • View Profile
    • pvigier's blog
Re: Tomb Painter - Game Boy inspired game about painting tombs
« Reply #3 on: June 13, 2019, 11:53:18 pm »
Looks great! I like your art style.

I have read your devlog, your replay system is awesome!

Elias Daler

  • Hero Member
  • *****
  • Posts: 587
    • View Profile
    • Blog
    • Email
Re: Tomb Painter - Game Boy inspired game about painting tombs
« Reply #4 on: September 15, 2019, 06:05:06 pm »
Thanks a lot, everyone. :)

Working on animated tiles recently, also did a lot about level editor and I'll publish a new dev log soon. :)
As you can see, both synced (waves) and unsynced (flowers) animations are supported.
TileAnimation system tracks all tiles which need to be animated, and when it's time to change a frame, it updates needed vertices in vertex array.


Level editor looks like this now:

* Added a toolbar. Previously tile editor had "three modes" - tile creation, entity selection, entity creation. Now I can easily add new tools!
* Empty tiles can't be selected for tile brush, also non-first animation frames for animated tiles can't be selected too
* Added tile layers.
* "Tile stamp tool" lets me combine tiles into "tile entities", e.g. house is a big stamp which can be applied to create new houses easily:

* Finally started to work on the second level - it was not easy to make sure that new level loads correctly and everything works well (there's a very elaborate scheme to find out which prefabs/entities are needed for the next level):

« Last Edit: September 15, 2019, 06:10:58 pm by Elias Daler »
Tomb Painter, Re:creation dev | eliasdaler.github.io | @EliasDaler | Tomb Painter dev log

Elias Daler

  • Hero Member
  • *****
  • Posts: 587
    • View Profile
    • Blog
    • Email
Re: Tomb Painter - Game Boy inspired game about painting tombs
« Reply #5 on: September 17, 2019, 10:10:08 am »

Spikes! I'm starting to work on some dungeon puzzles, yay :)

Here's their script. Pretty cool how easy they were to make with all the systems my engine has.

local EntityState = require("EntityState")

local coroutineManager = require 'Managers'.coroutineManager

local actions = require 'actions.wrappers'
local delay = actions.delay
local waitForAnimationEnd = actions.waitForAnimationEnd

local SPIKES_DELAY_TIME = 2.0

-- SpikesHiddenState
local SpikesHiddenState = EntityState:subclass("SpikesHiddenState")

function SpikesHiddenState:enter(e, args)
    e:setAnimation("hidden")
    e:setComponentEnabled("damage", false)

    coroutineManager:launch(
        function()
            delay(SPIKES_DELAY_TIME)
            e:changeState("SpikesRisingState")
        end
    )
end

-- SpikesRisingState
local SpikesRisingState = EntityState:subclass("SpikesRisingState")

function SpikesRisingState:enter(e)
    e:setComponentEnabled("damage", true)

    coroutineManager:launch(
        function()
            e:setAnimation("rising")
            waitForAnimationEnd(e)
            e:changeState("SpikesRisedState")
        end
    )
end

-- SpikesRisedState
local SpikesRisedState = EntityState:subclass("SpikesRisedState")

function SpikesRisedState:enter(e)
    e:setAnimation("rised")

    coroutineManager:launch(
        function()
            delay(SPIKES_DELAY_TIME)
            e:changeState("SpikesDescendingState")
        end
    )
end

-- SpikesDescendingState
local SpikesDescendingState = EntityState:subclass("SpikesDescendingState")

function SpikesDescendingState:enter(e)
    coroutineManager:launch(
        function()
            e:setAnimation("descending")
            waitForAnimationEnd(e)
            e:changeState("SpikesHiddenState")
        end
    )
end


return {
    SpikesHiddenState,
    SpikesRisingState,
    SpikesRisedState,
    SpikesDescendingState,
}
 

But with coroutine system I can also write something like this:

    coroutineManager:launch(
        function()
            while true do
                  e:setAnimation("hidden")
                  e:setComponentEnabled("damage", false)
                  delay(SPIKES_DELAY_TIME)

                  e:setComponentEnabled("damage", true)
                  e:setAnimation("rising")
                  waitForAnimation(e)

                  e:setAnimation("rised")
                  delay(SPIKES_DELAY_TIME)

                  e:setAnimation("descending")
                  waitForAnimation(e)
            end
        end
    )

... but for now I think I'll go with good old state based approach, which I think it more readable.
« Last Edit: September 17, 2019, 10:14:17 am by Elias Daler »
Tomb Painter, Re:creation dev | eliasdaler.github.io | @EliasDaler | Tomb Painter dev log

Elias Daler

  • Hero Member
  • *****
  • Posts: 587
    • View Profile
    • Blog
    • Email
Re: Tomb Painter - Game Boy inspired game about painting tombs
« Reply #6 on: September 19, 2019, 10:58:18 am »
Added filtering for prefab names. Now I can find prefabs and create them faster:


ImGui is so awesome - I only had to write this code to have this work:
    static ImGuiTextFilter filter;
    filter.Draw("Filter");
    if (ImGui::ListBoxHeader("Prefab")) {
        for (const auto& prefabName : prefabNames) {
            if (filter.PassFilter(prefabName.c_str())) {
                if (ImGui::Selectable(prefabName.c_str(), selectedPrefabName == prefabName)) {
                    selectedPrefabName = prefabName;
                    selected = true;
                }
            }
        }
        ImGui::ListBoxFooter();
    }
« Last Edit: September 19, 2019, 11:05:47 am by Elias Daler »
Tomb Painter, Re:creation dev | eliasdaler.github.io | @EliasDaler | Tomb Painter dev log

billarhos

  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: Tomb Painter - Game Boy inspired game about painting tombs
« Reply #7 on: September 20, 2019, 02:14:29 pm »
Quote
if (ImGui::Selectable(prefabName.c_str(), selectedPrefabName == prefabName)) {
                    selectedPrefabName = prefabName;
                    selected = true;
                    break;

                }

If u add a break, i think it make it a liitle faster

Elias Daler

  • Hero Member
  • *****
  • Posts: 587
    • View Profile
    • Blog
    • Email
Re: Tomb Painter - Game Boy inspired game about painting tombs
« Reply #8 on: September 20, 2019, 02:24:02 pm »
If I add a break, other prefabs in the list won't be displayed.
Tomb Painter, Re:creation dev | eliasdaler.github.io | @EliasDaler | Tomb Painter dev log

Elias Daler

  • Hero Member
  • *****
  • Posts: 587
    • View Profile
    • Blog
    • Email
Re: Tomb Painter - Game Boy inspired game about painting tombs
« Reply #9 on: September 22, 2019, 04:54:11 pm »
Doing more level editor/dev tools stuff... It's amazing how everything comes together now!


Here it is in action:
https://gfycat.com/presentleanbangeltiger

You can see how everything is dynamic and makes it easy for me to debug the game in action.

Also, I've finally solved the problem of entity lifetime that was bugging me for quite a long. Now there are three types of entities:
* AlwaysSpawn - spawned when level loads
* SpawnOnRoomEnter - spawned when you enter the room, despawned when you exit it. Used for enemies (it's easier to create an entity from scratch than to try to restore its state)
* DoNotSpawn - used for NPCs mainly - these are spawned by manager whichi takes a save and then looks where NPC is currently in this save. If the room is current one - the NPC is spawned. This allows me to have NPCs "travelling" between rooms and levels.

Also, now when I enter level editor, the level state is completely restored thanks to a clear separation. Every temporary object is removed, every SpawnOnRoomEnter/DoNotSpawn object is spawned, so that I can edit it, and then killed, when resuming the game. It works amazingly well. :)
Tomb Painter, Re:creation dev | eliasdaler.github.io | @EliasDaler | Tomb Painter dev log

Elias Daler

  • Hero Member
  • *****
  • Posts: 587
    • View Profile
    • Blog
    • Email
Re: Tomb Painter - Game Boy inspired game about painting tombs
« Reply #10 on: September 23, 2019, 12:30:35 pm »
Working on quests - tried to simplify stuff as much as possible, and put it in one script per quest. And it works well! Here's an example of quest state:

InHouseState.entityStates = {
    luna = function(e, quest)
        setActionListOnInteraction(e, beforeKill, quest)
    end
}

InHouseState.sceneEnter = {
    luna_house_basement = function(quest)
        saveManager:setQuestData(QUEST_TAG, "went_to_basement", true)
        spawnByTag("basement_slime") -- spawn a boss
    end
}

InHouseState.sceneExit = {
    luna_house_basement = function(quest)
        despawnByTag("basement_slime") -- despawn a boss
    end
}
 

entityStates is used to describe what function should be called on an entity when it appears on scene. In this case, when "luna" appears on the scene, she gets a new interaction function which will launch a specific cutscene.

sceneEnter/sceneExit are used to describe what happens when you enter/exit the scene in the specific quest state. In this case, it's used to spawn a boss in "luna_house_basement" until you kill it (and then the quest state changes and different script plays each time you enter the basement)

Here's what's good about this mechanism - entities and scenes don't know anything about quests - quest itself does the things when it's in corresponding state, so I can easily add more and more logic to them without touching scene/NPC script - it's all encapsulated into quest script!



Another thing I've added in an event logger. It allows me to subscribe to events of needed type and then inspect the data in each event. Very useful for debugging!



Here it is in action:
https://gfycat.com/sardonicmenacinggrackle
Tomb Painter, Re:creation dev | eliasdaler.github.io | @EliasDaler | Tomb Painter dev log