It’s been a while since my last update (I’m sure I’ve said this in an earlier blog post too) so here’s what I’ve been doing! I took a bit of a break from working on Metamorphoser 2.0 to finally play Nier: Automata and it blew me away. I feel like Yoko Taro really gets me haha. There were a few themes that I recognised from my game reset/you which was surprising since I started work on it way before I got into Nier. I also read LPs of Nier: Gestalt/Replicant and Drakengard to get the full backstory and found yet more similarities to my own work. It’s kind of amazing when that happens, it’s like “wow this person I don’t even know halfway across the world thinks the same way I do about creating fiction. That’s super cool”.

Now the actual updates

So… back to my own work. After a long time agonising over how I wanted Jack’s route to pan out I finally had a breakthrough and drafted out his ending. In short: it’s going to hurt. Technically he has two endings. I call them the “good” and “bad” endings but they’re both equally terrible… Sorry Jack. I think the only ending where awful things don’t happen to every major character is actually the doctor’s, weirdly enough. In all the other endings it’s death and pain for everyone :)

New CGs

First big thing I’ve been working on since the last update is… new CGs!! I’ve completed 3 new CGs so far:

The doctor grabs Carter by his tie

The doc decides to mess with Carter because he notices Carter has a bit of a crush on him and he thinks it’s funny. Yeah he’s a dick.

The doc gestures with his bionic arm to a column of flesh erupting out of the ground

The doc summons his terrifying flesh monster from a parallel dimension. I did say he was a mad sorcerer scientist didn’t I?

An unnamed character with blond hair, one green eye and one brown eye examines their face in the mirror

And this is… well, spoilers. This is a CG from what was the ‘true end’ in the first version of the game where Carter kills Isaac but in 2.0 that turns out very differently for both of them…

Layered images

Another cool thing I’ve added since the last update is… layered images!! I was kind of waiting for Renpy version 7 to release before I worked on the actual game code again because of this new feature. In this update I talked about using Renpy’s LiveComposite to make sprites with interchangeable parts so you didn’t have to export ten million images for all your expressions. The only downside was there was a lot of copypasting code to define each expression. In Renpy 7 layered images were introduced, making the code to do that so much DRYer.

Here’s the old code for just one expression:

init:
    $ carter_height = 577
    $ carter_width = 358
    image carter normal = LiveComposite(
        (carter_width, carter_height),
        (0, 0), "assets/images/sprites/carter/uniform.png",
        (0, 0), "assets/images/sprites/carter/eyes_normal_colour.png",
        (0, 0), "assets/images/sprites/carter/eyebrows_normal_colour.png",
        (0, 0), "assets/images/sprites/carter/glasses_colour.png",
        (0, 0), "assets/images/sprites/carter/mouth_normal.png",
        (0, 0), "assets/images/sprites/carter/hair.png",
        (0, 0), "assets/images/sprites/carter/eyebrows_normal_lines.png",
        (0, 0), "assets/images/sprites/carter/eyes_normal_lines.png",
        (0, 0), "assets/images/sprites/carter/glasses_lines.png",
    )

And here’s all the new code for the layered image which can produce uh… (someone good at maths should work this out) a lot of different expressions with no change to the initial code.

layeredimage carter:

    group outfit:
        attribute uniform default:
            "assets/images/sprites/carter/uniform.png"

    attribute blush:
        "assets/images/sprites/carter/blush.png"

    group eyes:
        attribute e_normal default:
            "assets/images/sprites/carter/eyes_normal_colour.png"
        attribute e_normal_side:
            "assets/images/sprites/carter/eyes_normal_side.png"
        attribute e_narrowed:
            "assets/images/sprites/carter/eyes_narrowed_colour.png"
        attribute e_narrowed_side:
            "assets/images/sprites/carter/eyes_narrowed_side.png"
        attribute e_wide:
            "assets/images/sprites/carter/eyes_wide_colour.png"
        attribute e_smile:
            "assets/images/sprites/carter/eyes_smile_colour.png"

    group eyebrows:
        attribute eb_normal default:
            "assets/images/sprites/carter/eyebrows_normal_colour.png"
        attribute eb_frown:
            "assets/images/sprites/carter/eyebrows_frown_colour.png"
        attribute eb_raised:
            "assets/images/sprites/carter/eyebrows_raised_colour.png"
        attribute eb_sad:
            "assets/images/sprites/carter/eyebrows_sad_colour.png"
        attribute eb_suspicious:
            "assets/images/sprites/carter/eyebrows_suspicious_colour.png"

    group mouth:
        attribute m_normal default:
            "assets/images/sprites/carter/mouth_normal.png"
        attribute m_open1:
            "assets/images/sprites/carter/mouth_open1.png"
        attribute m_open2:
            "assets/images/sprites/carter/mouth_open2.png"
        attribute m_open3:
            "assets/images/sprites/carter/mouth_open3.png"
        attribute m_smile:
            "assets/images/sprites/carter/mouth_smile.png"

    group glasses:
        attribute glasses_on default:
            "assets/images/sprites/carter/glasses_colour.png"

    always:
        "assets/images/sprites/carter/hair.png"

    group eyes:
        attribute e_normal default:
            "assets/images/sprites/carter/eyes_normal_lines.png"
        attribute e_normal_side:
            "assets/images/sprites/carter/eyes_normal_lines.png"
        attribute e_narrowed:
            "assets/images/sprites/carter/eyes_narrowed_lines.png"
        attribute e_narrowed_side:
            "assets/images/sprites/carter/eyes_narrowed_lines.png"
        attribute e_wide:
            "assets/images/sprites/carter/eyes_wide_lines.png"
        attribute e_smile:
            "assets/images/sprites/carter/eyes_smile_lines.png"

    group eyebrows:
        attribute eb_normal default:
            "assets/images/sprites/carter/eyebrows_normal_lines.png"
        attribute eb_frown:
            "assets/images/sprites/carter/eyebrows_frown_lines.png"
        attribute eb_raised:
            "assets/images/sprites/carter/eyebrows_raised_lines.png"
        attribute eb_sad:
            "assets/images/sprites/carter/eyebrows_sad_lines.png"
        attribute eb_suspicious:
            "assets/images/sprites/carter/eyebrows_suspicious_lines.png"

    group glasses:
        attribute glasses_on default:
            "assets/images/sprites/carter/glasses_lines.png"

Carter’s sprite is much bigger than the others due to having separate layers for the lines and colour of his eyebrows and eyes so that his expressions can still be seen clearly under the hair covering his face. Isaac’s is much smaller by comparison:

layeredimage isaac:
    group outfit:
        attribute uniform default:
            "assets/images/sprites/isaac/uniform.png"
        attribute uniform_blood:
            "assets/images/sprites/isaac/uniform_blood.png"

    group eyes:
        attribute e_normal default:
            "assets/images/sprites/isaac/eyes_normal.png"
        attribute e_closed:
            "assets/images/sprites/isaac/eyes_closed.png"
        attribute e_red:
            "assets/images/sprites/isaac/eyes_red.png"
        attribute e_side:
            "assets/images/sprites/isaac/eyes_side.png"
        attribute e_smile:
            "assets/images/sprites/isaac/eyes_smile.png"
        attribute e_wide:
            "assets/images/sprites/isaac/eyes_wide.png"
        attribute e_wink:
            "assets/images/sprites/isaac/eyes_wink.png"

    group eyebrows:
        attribute eb_normal default:
            "assets/images/sprites/isaac/eyebrows_normal.png"
        attribute eb_frown:
            "assets/images/sprites/isaac/eyebrows_frown.png"
        attribute eb_raised:
            "assets/images/sprites/isaac/eyebrows_raised.png"
        attribute eb_sad:
            "assets/images/sprites/isaac/eyebrows_sad.png"
        attribute eb_suspicious:
            "assets/images/sprites/isaac/eyebrows_suspicious.png"

    group mouth:
        attribute m_normal default:
            "assets/images/sprites/isaac/mouth_normal.png"
        attribute m_grin:
            "assets/images/sprites/isaac/mouth_grin.png"
        attribute m_open1:
            "assets/images/sprites/isaac/mouth_open1.png"
        attribute m_open2:
            "assets/images/sprites/isaac/mouth_open2.png"
        attribute m_pout:
            "assets/images/sprites/isaac/mouth_pout.png"
        attribute m_smile:
            "assets/images/sprites/isaac/mouth_smile.png"

    always:
        "assets/images/sprites/isaac/hair.png"

And to use these in the game script you show them like so:

show isaac e_closed eb_normal m_grin at left
show carter e_normal eb_normal m_normal at right
with dissolve

It means more typing out to display a particular expression but it gives you a lot more granular control for what kind of expression you want to show. I like this system a lot - it’s much easier to set up and work with than LiveComposite. And! You don’t just have to use it for displaying sprites! I created a CG for the classroom scenes with Carter and Jack and defined it as a layered image. So it’s kind of like a CG but with different expressions like a sprite.

Screenshot from the game showing Jack and Carter talking at their desks. Jack says: "Must have been a good first date - you're never this late."

Screenshot from the game showing Jack and Carter talking at their desks. Carter says: "Keep it down, idiot."

Changes in POV

As for actual work on the script, I had a few brainwaves for things I could do to improve storytelling and game mechanics. In version 1 there are just a couple of scenes where the POV changes from Carter to a third person narrator in order to show the player things that are happening while Carter isn’t in the scene. In v2 I decided instead of having a 3rd person narrator I could stick to first person… but change the character who is narrating. In this case, we get inside the doc’s head a little bit (this also ties into some stuff that happens in his route) which 1. is a nice contrast from Carter in terms of character, and 2. gives the player some insight into the doc’s feelings that explain his motivations a bit better. Plus it’s a nice change going from writing snarky piece of shit Carter to eccentric troubled father Hamzah.

[Game over] [Continue?]

Another cool feature I added is a retry screen. Since the basic structure of the game is one long ‘true’ route with dead ends that branch off along the way, I thought it would be nice if the player had a way to quickly go back to where they screwed up without having to reload a save or play everything again. So, now when you get to a bad end you get a nice message from a mysterious voice in red (Yes this is a character in the game. No I’m not telling you who it is.) asking you if you want to go back and retry:

NVL screen with text saying "You died"

NVL screen with further text saying "You decided to rush headlong into danger right away didn't you? Making choices like that without thinking will get you killed. Unless of course, that's what you want. Try to be more careful in future. Do you want to go back to that choice and retry?"

NVL screen with a choice: "Yes" or "No (go back to the main menu)"

This particular text shows if you choose the first bad option on your very first playthrough. Your next playthroughs get this text instead:

??? "Well, that was a bad decision."
??? "If you're not careful you'll be killed. Again."
??? "Unless of course, that's what you want."
??? "Try to be more careful in future."
??? "Do you want to go back to that choice and retry?"

I’ve not yet decided whether I want to do some kind of 4th-wall-breaking secret ending to do with this character but I’m considering it. I think it’d be cool ;)

That’s all!

That’s all I got for this update. It’s uh… a lot. Mainly because I haven’t updated in a while. See you in another 3 months I guess o/