<![CDATA[ruby0x1.notes]]>https://notes.underscorediscovery.com/Ghost 0.11Sun, 31 Jan 2021 03:19:03 GMT60<![CDATA[UE4 - list blueprint assets by type]]>I'm busy working on a project in unreal lately, and ran into the desire to enumerate a list of blueprint assets from a folder. This post has a simple solution.

I looked around and found this post which covers finding UClass from a type, native or from assets, but didn't

https://notes.underscorediscovery.com/ue4-list-blueprint-assets-by-type/07696f7c-4ec8-4117-bde8-2db45b0baa69Tue, 27 Mar 2018 13:22:25 GMT

I'm busy working on a project in unreal lately, and ran into the desire to enumerate a list of blueprint assets from a folder. This post has a simple solution.

I looked around and found this post which covers finding UClass from a type, native or from assets, but didn't feel right for my needs. I then found out about UObjectLibrary and after figuring out some of it's API, found this post which also helped. UObjectLibrary been working well and has lots of neat little helpers in the API for what I wanted, and the code is simple.

The code is at the end of the post.

important notes

Make sure the path you use exists in the cooked data in packaged builds. The project has settings for forcing folders to be cooked, add them there if your code is assuming they exist.

All Content/<folder> paths are referenced as /Game/<folder> when using this. Here we have /Game/Trees and /Game/Cards.

UE4 - list blueprint assets by type

The point

Let's say I was doing some procedural generation, and I wanted to spawn some trees (or even whole chunks of a level). These trees can be made into blueprint actors, and spawned dynamically. But how do I get a list of them to spawn from in the first place? That's what we want here, and this is what we'll get.

UE4 - list blueprint assets by type

Type filtering
You'll notice that Type Class filter, this is useful to be specific about the sub class, so that you can cast knowing each result is of the right type.

For example, in my case I have a c++ class called EventCard that all my "card" blueprints inherit from, then I can select it here. Then, I can cast to the specific class and use it as that type, if I wanted to. (This also means you can mix types in the same path/folder, and query only ones that you want).

This example also shows how you can take the type and spawn an actor from it. Since the class is just a type of tree, we are now creating one actual tree from it. We can do that several times for the same class, making many from one.

UE4 - list blueprint assets by type

C++ spawning/usage
This code example assumes all my blueprints are inheriting from the c++ class AEventCard, which they are. (see unreal wiki for GetWorld() alternative)

TArray<UClass*> list;  
helper::GetBlueprintsOf(AEventCard::StaticClass(), TEXT("/Game/Trees"), list);  
UClass* cardClass = list[0]; //assume it found one, use the first one  
AEventCard* card = GetWorld()->SpawnActor<AEventCard>(cardClass);  

Code setup

In my case I had two goals:

  • I want to use this from c++
  • And I want to use to use it from blueprints

The general idea is we want one c++ function, and then one blueprint-facing wrapper function to expose that. The Unreal Wiki has some great examples of exposing stuff to blueprints so I won't get too specific, but I will provide hopefully a clear example of how it'll be setup.

I already have a general purpose blueprint function library in c++, called "TypesAndGlobals", this is where I'll expose it. If you don't have one (and want to use this and don't mind c++ in your project) you would create one from File -> New C++ class and choose Blueprint Function Library as the parent class.

Once the function is exposed then we get this:

UE4 - list blueprint assets by type

The code

<![CDATA[new game+ / Celeste launches tomorrow!]]>

Celeste is a game I had the privilege of working on, and it launches tomorrow (25th Jan) on Switch, PS4, Steam and the day after (26th Jan) for Xbox One!
All the details are here

I recently completed the main story path again on Switch,

https://notes.underscorediscovery.com/celeste-game-launch/936edfba-31cd-42a1-addc-683aa273fbf0Thu, 25 Jan 2018 03:16:11 GMT

new game+ / Celeste launches tomorrow!

Celeste is a game I had the privilege of working on, and it launches tomorrow (25th Jan) on Switch, PS4, Steam and the day after (26th Jan) for Xbox One!
All the details are here

I recently completed the main story path again on Switch, and it feels weird to say that this game is in my list of all time favourites. It is, though. I adore this game.

The love and attention poured into Celeste really shows, and the whole team worked together to create something great that'll stick with me for a long while. I'm honoured to have worked with them, and I respect every one of the people that poured the heart of this game from their own.

new game+ / Celeste launches tomorrow!

Worth it!

Even though Celeste is a challenging precision platformer (and wow some of the extra side levels are challenging), it still has an accessible main story path that a lot of people will be able to complete. It's worth the challenge, and makes the game so good at what it is. I'd encourage you to try it if you're able!

If for any reason you'd like a different way to play, the game includes Assist Mode. This allows you to play without dying, slow down time, have infinite dashes and more - so if you just want to exist in the world and experience the story,
you're welcome to.

new game+ / Celeste launches tomorrow!

The game has 700+ areas with a ton of secrets, challenges, and lore and it's such a rich experience. The speed running aspect of the game later on is going to be so much fun to watch, too.

I hope you'll love it as much as I do!

p.s The soundtrack is ridiculously good, as well as the B-sides soundtrack.

p.p.s Don't miss Theo's instagram every day, TheoUnderStars.
Looks like Theo is on the way to the mountain...

new game+ / Celeste launches tomorrow!

<![CDATA[game designer's bench: Golf Story]]>https://notes.underscorediscovery.com/designers-bench-golf-story/760cd44c-6ca6-4ecf-b0b0-f2698748e18eWed, 10 Jan 2018 23:00:00 GMT

I've been playing Golf Story on the Switch and was pleasantly surprised. It's weird but in a good way, and I like a lot of things about it. Some things about it mechanically and overall bother me, so I brought it to the bench to ponder why!

note: there are very minor (but not really) spoilers.
also note: you don't have to have played to find this interesting reading, I hope.
also note note: If you want to enjoy it without me whispering "this is weird?" while you play, play it first!

“Game designer's bench” is a design work bench! It's a bunch of words about game design. The aim is opinions and insight into design from one perspective, and to keep posts free of senseless negativity while still being fair and direct. Also, ideally presenting solutions or ways to tackle design problems presented.

More directly, the hope is to raise interesting questions and be critical of the medium, and hopefully help us make better games.

You can subscribe to these posts directly via the game design tag or subscribe via this mailing list at the bottom of this post.

Golf Story is an RPG around a young golfer looking to turn pro. You play through a series of areas, encountering people, items, mini games and puzzles. The game is longer than I expected (I'm over 16 hours in) and better than I expected (for an RPG about golf).

This game has a lot of good moments. I laughed, and I have enjoyed playing it. I can recommend it, as it's surprising in ways that I think make it a nice experience. You can watch the trailer below, to see what I mean and if you'll like it.

I'm going to approach this post from a mechanical and design consistency perspective, not a narrative or tone one.

For all the good parts that I like about it, it also seems to suffer from things that appear to be a side effect of either rushing for a launch window (even though it's been out a while already), or a lack of design experience.

I can't assume either of those, but that's how it FEELS to me. Sometimes the design decisions just don't make any sense, especially in the context of a fairly well made and polished game like this.

Identity, vision and pillars

Golf Story seems uncertain of what it is.
I kept asking "wait, but who is this piece of the game for"?

It doesn't seem to have an answer.

Misunderstanding "challenge"

In a game about golf, there are a lot of natural obstacles present (like the elements, trees, hazards, and so on) that the game has but doesn't really utilitize to it's fullest. It has wind, water, weeds, bunkers and trees but you're never really challenged by them - they just exist and slow you down by the normal rules of golf. There's no segments that use those in a mechanically interesting way.

The game does add new and often novel ideas like the turtles, moles and birds and I like that, however it also fills the gaps in the game with tasks that give me the impression they don't really know what challenge, especially in this game, is about.

Golf Story has many boring non-challenges, lots of easy challenges, unfair challenges, and later on some difficult and (sometimes) frustrating challenges. I'll go into details on some of these later.

Order, progression and balance
The progression doesn't feel well defined, like sometimes it feels well balanced for the stage of the game you're in, but often not.

An example is in the second area, you have to run around and race time with a fairly tight time window, on a course you've likely never walked on before, and this is only the second foot race (iirc). The previous one you'd have been in that area a while, the "track" was basically square, so this challenge feels comparatively tricky. This took a few tries, and especially compared to the later footrace challenges which have a much simpler courses to navigate, these footrace challenges can feel out of order.

The game swings pretty far toward the "non-challenges", task lists and easy puzzles earlier in the game, book-ended by 9 hole games on the courses. The more challenging things to do only start showing up much later - like in the last area - except for a few that are mixed between the often trivial tasks and puzzles.

There are some 'challenges' that don't actually give you any goals - like when you're tasked with mowing a lawn. There are obvious things to ride over (like weeds) and that's it, your actual purpose isn't told to you, so you end up running around aimlessly unsure of what you're doing. There's no progress indication like in every other challenge, and then you're interrupted and the sequence suddenly ends. It was confusing and inconsistent.

I don't mind most of this really, it's just worth noting that I feel a lack of intentional structure in the challenges pacing and progression makes the game feel a lot more inconsistent to me as a player.

game designer's bench: Golf Story

Challenge overall
Overall, some things require failing to figure out how they work. Some things are near-impossible to fail. Some things take several tries and are challenging. It's a rollercoaster of ideas in no logical order.

One could say that it's a varied experience for various player types, but I personally consider it rather just inconsistent, as there are inconsistencies in almost every layer.

Good challenges

Golf Story does have some sense of the things that it's about, because it does have some challenges that are good. Things like "play only the rough", "play only bunkers" give you a different way to play the same hole. It challenges you to try things differently, explore your clubs, and get a better feel for the later challenges. There's many examples like this, where the designer seems aware and the game seems to have insight into the player.

This isn't just mechanical either, in the secrets and mysteries, sometimes in the narrative - there's an awareness of good design and the challenges are interesting enough, and rewarding to progress through.

Giving the player tools to get better at the game through the mechanics in a cohesive and consistent way, while also building the game and the world up at the same time, means there is lots of good stuff going on. That makes all the rest of this stuff so confusing.

Non-challenges and wasting the player's time

Then on the other hand we have these kinds of challenges. As one example, there's a section in the game where you hit a ball into the water to some turtles (there are no turtles in the water yet).

The “challenge” here is non existent. You have double the amount of chances to make three shots. Each shot is already pre-configured to hit directly into the target. The target you have to hit is massive, very hard to miss (even if you max-slice it into the wind). Literally any player can hit them first time, without changing any swing settings. But, you still have to do it "twice", because there are 6 shots and three targets. (Once you have the turtles, you also have to do it again, just differently).

Golf Story doesn't seem to recognize how little value there is here for the player. This is isn't challenging to any of it's perceived player types. Like, it's not a problem that they give you the space to fail, but it is a problem that there is no real space to fail mechanically at all.

All this ends up doing is wasting the players time doing a checklist, you can "beat" this with your eyes closed.

This feels like padding, because it adds nothing, and doesn't ask anything. It doesn't progress a narrative, it doesn't build the world, it doesn't grow the player. There's a bunch of examples like this that feel tacked on, I won't enumerate them all but the inconsistency is strange.

Almost like someone said an RPG has to be x many hours so there's a bunch of stuff in the way to make it take longer. Almost...

Pointless input mechanics

The only terribly silly mechanic worth mentioning is the "electric wedge ore mining". The implementation is really not great. Below the description is a short video showing both digging and mining.

With the digging mechanic that is similar to the mining one (which is introduced first), you have to press a button at the right time and the window of time gets smaller and moves around as you succeed. Missing incurs a small input delay. The digging mechanic is consistent with the world and the gameplay, and it makes sense. It also actually asks something of the player, it's not tedious, and you can get better at it.

The ore mining however, feels like an attempt to flip this idea on it's head - the input moves faster on each success but the input window stays still. On paper, it's ok as an inversion of the time window getting smaller to press - it's almost the same conceptually.

The problem is this mechanic is just plain tedious. It's long winded and doesn't really ask anything of the player. Compare the two side by side, in the video below. The digging even has a failed attempt, slowing it down. The mining is executed without a mistake. The mining is over 16 seconds of button mashing, hitting the button 20 times in a row.

It feels like mashing a button to just dismiss it, and the failure state becomes actually annoying, because input is blocked when you're trying to escape a dialog you've been stuck in for what feels like forever. The ore mechanic is not interesting for the player in the slightest.

It also wastes the players time, by asking them to do this on 5 different pieces of ore, in a row, every time.

Progression obfuscation

This section is harder to articulate, because it's the inconsistency and lack of vision/clarity in the overall design, across the whole game, that bothers me.

The connection between the progression, the mechanics, the narratives and the player's mental model of the way the game works throughout isn't particularly well defined. It ties into why it feels like it's just unsure of itself as a game.

On their own or without the context, the more difficult challenges can be seen as optional things to do that the player can ignore. However, they're not telegraphed as optional, often challenges block progression.

It means that I'm never sure if my progress is hinged on any particular challenge or not. Sometimes literally every challenge is connected in an intertwined order-of-operations fashion, and sometimes none are related at all. As a player, you probably won't know till you progress, and often you progress by accident.

This is mentioned in the general design section too, but often you're sent along the progression in the game without warning. This usually involves progress being tied to pressing a button to talk to someone, when you weren't read to progress yet. This is worse when the section you progress into is blocking, or changes the world.

Lost connections
As a concrete example, in the Coldwind Wastes course your narrative progresses by retrieving a fire ball. You're asked to unfreeze some things using it, and by doing so unlock several challenges.

Here my mental model is maybe that my progression is tied to the challenges from the frozen people right? Except there are several challenges that are (suddenly) actually challenging, some even require dexterity that more casual players may not have, or care for.

If you can't tell that you're not stuck here and you just want to continue on your progression, I imagine you may just quit out instead. Throughout the game up till now, the model of progression has been all over the place, so it's not really easy for the player to know whether to attempt the challenges to find out (like "normal").

There also seems to be a bug here about the character who gave you this task not recognizing that you've unfrozen everything, their dialog remains on asking you to unfreeze the others. But that's not a design issue per se, just something I got mildly frustrated with. (side note: since writing this, I noticed a frozen thing in other screenshots, which may have caused this but I can't check and I really don't feel like replaying 14 hours to find out.)

game designer's bench: Golf Story source: kotaku

detour: one off other-genre mechanics

A concept that games seem to have gotten better at over time, but for some reason Golf Story went for, is “Suddenly-A-Racing-Segment”. It's really lazy design to me, and feels like they had all these ideas and nothing to measure them against for whether they made sense.

game designer's bench: Golf Story

While I can imagine that a section dedicated to this mini game in particular would have worked pretty well in the Golf Story world, and would be welcomed by players that would enjoy it, it just doesn't fit well in the game as is. In the current game it feels bolted onto an unrelated section, it's isolated from anything else like it mechanically, and mainly serves to compound onto the other frustrations.

"What purpose does this serve, here?"

This entirely new mechanic introduced in this area only has a pretty tight time window to beat, and has several instant failure cases on the most obvious paths (hitting trees/rocks, you just explode). Since racing RC cars in tight corners - with drifting and high time penalty for not being precise - hasn't been a mechanic the player has had a chance to warm up to means it could easily take several tries. Even for an experienced player that likes racing games (like me), I think I got it in around 4 attempts due to the unfamiliarity of the track, the controls, and the mechanics. Afterward I was just confused as to why.

The difficulty of the challenge isn't really the issue, it's this "who is this for?" question that repeatedly comes up, why is this here, what does it serve in the game where it was placed.

And do I need to beat it to continue?
The frustration was piling up.

Pacing obfuscation

The other challenges in this area range from hunting for hidden things, putting or chipping through snow, lofting over a camera man (which has a sort of order of operations with the blacksmith), putting on ice, etc. They all made sense, some were trickier, some were trivial, some were annoying (the ore mechanic). They weren't consistent, but can you guess how many were tied to progression if you just wanted to move on?

After I did all of them, I was still stumped for a short period. The quest giver kept saying there was more... so I ignored that as a potential bug, and stepped back to methodically try everything again.

It was only then I then realized I could have progressed long ago, without doing any of these challenges! This wasn't JUST an issue of the progression not being well communicated to the player, but I viewed it as a brewing storm that had been growing over the whole game, where the inconsistencies piled on top of each other to frustrate, obfuscating everything.

I felt bad for the types of players that don't recognize bugs, or who aren't stubborn that would just clear all the challenges before asking "ok now what" like I did. I can imagine they may have felt stonewalled here pretty easily.

I was burned out by all these challenges, because they followed right after another longer sequence, and instead I just quit and didn't feel like returning for quite a while after that.

game designer's bench: Golf Story source: destructoid. I don't want to play many hours to grab screens cos I didn't know I'd write this.

Unfair challenges

Unfair is a weird word, but it's the right one for how some of the challenges in the game are constructed. This is the problem when you don't seem to understand what the game you're making is, so you don't (always) know how to craft interesting challenges for the player, so you fall on weird options that may feel terrible to a player.

Did you ever play an older game where enemy AI can just see you through walls, and for example shoot you through them, instantly ending your fun? This is something games seem to have solved a long time ago, yet unfair challenges from AI felt like a blast from the past in Golf Story.

In later challenges, someone else hits your first shot in a round of golf. You can guess how they do... They hit it into water, into trees, 1m off the tee, and just terribly, "on purpose", every single time. The AI is ridiculing you here, it's not a challenge. You're not asking the player to do anything, you're not testing their skill, their mind, their understanding of your game. You're just slapping them and saying “deal with it”.

If you wanted the player to start with a deficit in score, there are so many ways that don't just punish the player for no good reason and make them feel like crap. This is by far the most confusing design choice in the entire game for me.

"Who is this for?"

To make it worse, the opponent AI in these later ones is also hyper accurate, lands on every beneficial "hazard" on the entire course, and has no bad shots. The "bad" shots are "oh no I hit a tree, it just happened to bounce directly back onto the green a few centimetres from the hole".

This too mocks the player because it's so predictable. It's just the AI "cheating" via a thinly veiled pretense - they're just getting lucky. Even the character is named Lucky, which feels so heavy handed as a way to make this seem ok. That's pretty intentional design, which goes back to why it seems so confusing. There's design it's just in the wrong direction, like the game doesn't know what the player wants or likes so it ends up feeling terrible, but it's still designed. This one feels like inexperience to me.

A lack of design pillars

Good game design often has a set of pillars that you use to invalidate design choices that don't mesh with the type of game you're creating.

These are like the foundations you can use to ask if mechanics for your game make sense, like "does this make sense in this world we're building" and "does this match the types of players this game is for".

If you don't have a well defined view of what your game is, who it's for, what matters to the player, what the player is doing there and how to challenge them, you kinda end up all over the place. This is how Golf Story feels, like a random mix of ideas, some good and some pretty bad, with no strong sense of consistency or cohesion which would have been provided by design pillars.

It also means that you're easily tempted by padding to reach x hours of gameplay, because anything is valid. It hurts the game in my opinion!

game designer's bench: Golf Story

General inconsistency...

and design quirks. skip to the conclusion.

So many small things add up when the rest of the game is well made (and it is). I'll try to add suggestions from a design perspective, but so many of these repeat the same patterns that I just made a list instead.

  • You can't record video of the game for some reason?? The switch has it built in so it's odd choice. When I made dramatic shots... oh nobody will ever see it. Oh well!

  • Pacing is inconsistent. Going from long session to long session, or short session to short session, it just doesn't seem intentional about what you've just been doing, or are going to be doing next. Consider the player mental state, rest periods, ups and downs etc. Rewarding challenging sections with relaxing sequences, for example. There's no formula, but at least be intentional. The game has all the pieces of a really nice place to build pacing too, and sometimes the pacing is great, but grand scheme it feels like coincidence.

  • Challenges often have an obvious fail state, but have no option to quit. For example, if you do the mini golf challenge, if you mess up the second hole, you have to putt through seven other holes just to restart. It's terrible! This happens in several harder challenges on the pro course too. Just tedious. Don't waste the player's time.

  • Balance in the world is inconsistent. You can only find certain things late in the game, but they give you $0.50 - when other challenges are giving you over $200 at the time. Further demeans the 'reward' into a checklist.

  • Often unskippable camera pans and dialogue. Don't waste the player's time.

  • Overarching side quests are tied to the progress, and often told to the player via clues, so instead of letting the player find and discover things on their own, they're handed over. I was excited by the cachers hunting challenges, before I realized you have to wait to unlock each one by progress, and then it was beyond trivial because they tell you where it is. Some of them have a hot/cold radar. This felt like a missed opportunity.

  • Some challenges ask if you're ready, some don't, some launch you straight into very long sequences you can't quit from. Some launch you into a full 9 holes of golf you can't quit from, and some into segments of the game can't leave from. Maybe you just wanted to see what they were saying? NOPE. You're here now, whatever your intent was - oh well. Don't launch into unskippable sequences, don't force the player into things they can't back out of unless they know they're explicitly choosing to do that. At the very least, be consistent and don't disrespect the player intent.

  • And from above, some missions have "retire" in the menu, most don't. Gotta play through all holes just to restart or quit.

  • The inverse is also true, sometimes there's a challenge that takes 4 shots but gives you 10+ attempts. If you're any good at the game it and land them in the first 4, you have to pointlessly play through all 10 just to continue. This ties to the lack of challenge in some too, where you can't really miss, but still have to pointless play trivial shots over and over. Don't waste the players time.

  • Some sections feel like the designer was just pleased with the idea and then went overboard. There's a section where some people do a rap, it is soooo much longer than I feel necessary. Like, please just end it long. It's silly and fun at first, but ask "Who is this for?". Not the player... not after the first few minutes anyway.

  • Theming. The rap section ties into general overarching theme coherence... The world is full of strange and interesting ideas, and has some good world building going on (like the details on Lurker Valley being giant footprints - that's great. The ideas of golf on a beach, the haunted manor - all great). It's a bit all over the place but in a good way, and many of the themes and ideas fit just fine in the world. It's also funny and silly and charming.

    A lot of the themes though are just heavy handed, in both the writing and visuals. The sports announcers are insufferable, but have the most dialog in the game for example. Even the "scoundrels" theme with the bandanas feels odd here, what's the audience here, "who is this for?". This is mostly subjective though, and thankfully the game has a diverse cast of people types, despite some of these other overt stereotypes.

  • Dialog preambles before challenges can sometimes be several sentences, and you have to sit through them every single time. This piles on frustration because you know you're going to be coming back if you fail. Some dialog remembers and only prompts you yes/no, so it's another inconsistency. Don't waste the player's time. Just skip to the yes/no in all cases if you've already gone through, especially if it isn't a hint/reminder (some of them are reminders which is good design, but these aren't tied to yes/no states so they don't matter here).

  • Dialog can be sped up often, by using the Cancel button. Why the cancel button? To skip past dialog, you have to press B to skip text animation, and then A to continue, so you have to tap A and B alternating (B is cancel).

    My theory: As mentioned in the previous issue - challenges sometimes have yes/no prompt. If you're unlucky you'll hit "no" on the prompt when trying to skip dialog... That means another round through the dialog, slower, just to hit yes the next time. It can happen repeatedly if you're impatient or frustrated.

    The only reason I can think of this being done this way, is that people kept accidentally hitting yes, and then being pushed into long segments (like being stuck in a round of 9 holes with no quit). Switching the skip dialog button to the "no" option "fixes" that... but I don't know. Band-aids don't fix usability issues, use a short time delay to prevent mashing yes OR no, and allow both buttons to skip the dialog.

Golf Story is pretty good

It has a lot of charm, a lot of good moments, and is well made. It's really polished and the art is often really vivid and nice. There's a lot of neat ideas, things that reward the player and encourage exploring. A lot of it may be linked to progression and dialog but it still holds.

For what it is - an RPG around golf - it builds an interesting world, has a decent progression system that ties well to unlocking areas and feels good to make it through. The writing and theming is sometimes not my favourite but in context it's fine, and mechanically it brings some interesting ideas to a 2D golf game.

Hope you enjoyed the ramble!
(p.s These posts will get better formatted and better structured over time, and there'll be other game designers chiming in).

You can subscribe to these posts directly via the game design tag or the game designer's bench mailing list. I'll only ever send an email when I post one of these.

<![CDATA[game engines: using ALL the languages]]>In the 1.0/long term version of my engine, I designed the core runtime to expose it's API in such a way that it would be agnostic to a scripting language. This is a short post on how that looks, when you connect the dots.

This post needs a

https://notes.underscorediscovery.com/game-engines-using-all-the-languages/5d6b1463-260c-45f6-9697-24d587b989e6Mon, 20 Nov 2017 07:44:26 GMT

In the 1.0/long term version of my engine, I designed the core runtime to expose it's API in such a way that it would be agnostic to a scripting language. This is a short post on how that looks, when you connect the dots.

This post needs a thanks to a friend Jeff Ward who helped me with the dart embedding, and clarified some of my misconceptions/lack of clarity about embedding mono.

I've chosen wren for several reasons as the default language in my engine. That post includes a lot of rationale, but near the end points out that you'll be able to use any language later. I was validating some assumptions earlier today and figured hey, why not bind <x> - it'll be quick? And a few hours later.... x was not alone.

Turns out I could bind rust, c# (mono), c++, js, lua, dart, python and swift in less than a day. It's not the entire API, but the foundations are there (the rest can largely be generated). This also comes back to the data oriented API too, because things are all static functions and primitives it's a bunch easier.

Here's how the log looks when they're all loaded up:

game engines: using ALL the languages

Here's how the dependencies look after:

game engines: using ALL the languages

sometimes simple

I was really surprised how simple it was in some languages, like c# with mono can handle a c function pointer directly. This is great, because that's how the API is defined. This is true of rust and swift, they both have direct access to the endpoints. lua and js (via duktape.org) for example have generic function callbacks, where you unpack the args and forward them along.

This is the C# connection to the C API.

game engines: using ALL the languages

And then on the c# side:

game engines: using ALL the languages

sometimes frustrating

The dart sdk pulled down around 5.5gb of... stuff. It then built for a long while and the folder was around 6.5gb before I saw any usable files. I don't know why dart implies it's designed to be embedded, a lot of the header files in the embedding api reference internal header files, use unportable functions (_strdup) and more. It's wild.

Python has dependencies on a lot of implicit binaries. With cffi and cpython or pypy it has to reach the python runtime, the cffi runtime and who knows what else (in terms of standard lib?). Even the cffi docs complain the entire thing is a mess... I hate dependencies, and wouldn't want the end user to have to install python or anything. Maybe those can somehow be put alongside the binary all together, but I have no idea atm.

user plugin api

On the user end, the workflow should ideally be the same. They get a consistent interface to the engine API (idiomatic to the language to some extent) and they all feel similar.

Here's how it works in rust, c#, python (but you can imagine the rest, they're all very similar by design).

game engines: using ALL the languages

game engines: using ALL the languages

game engines: using ALL the languages

That's it for today

I'll go into more details in the future, and if you have questions feel free to send them my way.

<![CDATA[announcing 'errent' & album release]]>Today is another day to talk about things I've done since I was a kid, but haven't put much out there publicly! I've been playing and making music since I was young, but it's always been instruments and done live. Today I can say different.


My partner and I

https://notes.underscorediscovery.com/announcing-errent/9db9fb73-b169-41bc-ac77-300f6d52dc76Sun, 03 Sep 2017 00:46:49 GMT

Today is another day to talk about things I've done since I was a kid, but haven't put much out there publicly! I've been playing and making music since I was young, but it's always been instruments and done live. Today I can say different.

announcing 'errent' & album release


My partner and I both play a lot of different instruments (she even has a degree in music!) but when we moved to Canada we had to leave a lot of them behind, so it was a good time to try my hand at making some digital music a little more seriously.

For me, games drew me in because of their connection to all the different artistic outlets that I have and enjoy, so it's natural that I had always been making music for games (my own ones). I also typically find it hard to create when it's not for something, like I find it difficult to make music for no reason. Or to write for no reason. Or art.

announcing 'errent' & album release

operator overload soundtrack

Fortunately I had a good friend Benn using my game engine to make a neat puzzle game called Operator Overload - (you can wishlist it on Steam). We were talking about the music for it at some point and we decided to try our hand at the soundtrack for the game. Finally a specific task to make music for! It ended up taking us way longer than it should have unfortunately due to various life things, but we did manage to finish it eventually.

announcing 'errent' & album release

Putting the music in the game was a little more challenging than I anticipated because I was also trying to make the songs in ... chunks. This way I could play the tracks in game with an extended duration by randomizing pieces in set orders, so that it isn't nearly as monotonous or predictable. While this does have it's flaws obviously it ended up working out well for background music.


Since I make my own music, my wife makes her own music, and we also make music together, we decided to have a sort of umbrella name for our collective work.
Errent is our artist name, a 'detailed dichotomist duo' we call it.

And you can now buy our first album on bandcamp!

We hope you like it, and we hope you'll also check out the game when it's out. Follow me on twitter and say hi, and definitely follow us on errent.bandcamp.com as we have more heading that way.

announcing 'errent' & album release

<![CDATA[Sky Rogue 1.0 (I did a thing!)]]>Sky Rogue is a fun fast paced rogue-lite flight simulator that oozes with style. I knew the developer for some time and enjoyed playing the game, but was also fortunate enough to have the opportunity to do some writing for it as well! The release of V1.0 is out

https://notes.underscorediscovery.com/sky-rogue-1-0-i-did-a-thing/e05e5770-cad9-457a-afb6-2e0ab5156b90Thu, 24 Aug 2017 23:10:10 GMT

Sky Rogue is a fun fast paced rogue-lite flight simulator that oozes with style. I knew the developer for some time and enjoyed playing the game, but was also fortunate enough to have the opportunity to do some writing for it as well! The release of V1.0 is out today too.

Sky Rogue 1.0 (I did a thing!)

I've been writing since as long as I can remember but this was the first time I decided to put myself out there, and try to write for something specific. Kenny was kind (brave?) enough to give me the opportunity to put a shipped title in my (writing) portfolio and I'm pretty happy with the outcome (so far). It was interesting to work on, as there's a bunch of lore that isn't surfaced (yet?) but a lot of it can be found in the aeropedia in game.

I'll probably write more about the process, as I had a lot of fun with it, and it'll be up here in the very near future on this blog, you can follow me on twitter to find out when.

Sky Rogue 1.0 (I did a thing!)

You can view the rad 1.0 trailer below and buy the game from:





<![CDATA[OBJ parser: easy parse time triangulation]]>For some reason whenever I wrote a quick obj parser, I never bothered to think about the case where the faces in the file had more than 3 points. It was easier in the moment to just triangulate the meshes before loading them in the 3D app. In practice on

https://notes.underscorediscovery.com/obj-parser-easy-parse-time-triangulation/b99f2d0b-1ea7-42f2-aaea-a3808c47ecf9Thu, 05 Jan 2017 01:50:01 GMT

For some reason whenever I wrote a quick obj parser, I never bothered to think about the case where the faces in the file had more than 3 points. It was easier in the moment to just triangulate the meshes before loading them in the 3D app. In practice on a bigger project, with bigger scenes and lightmaps and all sorts this became a bit of a pain.

Since I was writing a quick obj parser again, I decided to think about it for more than a few minutes and since I didn't see too many easily found results on doing this: I figured I'd share what I implemented for future reference. The only thing you have to tweak is how you parse the f lines.

This solution may be obvious to some and that's fine!

Note that this assumes you want to parse the mesh details as triangle primitives, like GL_TRIANGLES or similar. This does NOT require using triangle fan primitives.

The solution

Parse the face points as if it was a triangle fan!

The details

All that means is they share a common vertex.
We can use the first vertex (0) of the face, and connect each of the points after that back to it.

OBJ parser: easy parse time triangulation

This is the basis for our easy triangulation. The points are almost always coplanar and should generally be convex but do be aware of what happens when they're not. This solution also applies to any other mesh formats that follow similar coplanar rules and stores faces of course.

If we imagine a simple quad, in our OBJ file we might have this line:

f 1/1/1 4/2/1 3/3/1 2/4/1

Using the above logic we can parse the face by hand/on paper/in mind as:

triangle one:  
[1, 1, 1],    [4, 2, 1],    [3, 3, 1]
triangle two:  
[1, 1, 1],    [3, 3, 1],    [2, 4, 1]

So the logic is for each point: connect itself & the next point back to the first point. We can do this in a very simple pseudoish for loop:

var points = split line by ' ', discard the first item ('f')  
var triangle_indices = []  
for(i in 1 ... points.count-1) {  
    tri_corner0 = points[0]
    tri_corner1 = points[i]
    tri_corner2 = points[i + 1]
    triangle_indices.push([corner1, corner2, corner3])

This logic applies the same if there are just 3 points, since it will loop from 1 to 2, adding a single triangle with the correct points!


That's all there is to it, now you can throw most meshes into the loader without any trouble, and the second part of obj loading (converting the indices into vertices) doesn't change.

Yay for better workflow!

<![CDATA[c++11 constexpr fnv1a compile time hash]]>I've been working with some c++ lately and had previously been using static hash values for strings (similar to this from the Bitsquid blog) but the one thing that bothered me was the lack of ability to use them in switch statements, where I often want to use them. With

https://notes.underscorediscovery.com/constexpr-fnv1a/04a7cb06-9437-4629-a2b1-16cfa3d7e2b4Wed, 19 Oct 2016 10:14:55 GMTI've been working with some c++ lately and had previously been using static hash values for strings (similar to this from the Bitsquid blog) but the one thing that bothered me was the lack of ability to use them in switch statements, where I often want to use them. With constexpr in c++11, I can.

I've been talking a bit with Alan Wolfe (@Atrix256) and he has been posting a good series of exploring code vs data, and compile time evaluation on his blog. You should read it, if that interests you.

I had been meaning to convert my fnv1a hash functions into constexpr but haven't had enough reason to yet, but the recent posts from Alan spurred me on to just do it, and it was surprisingly straight forward. I found a few really old examples of people trying it but for some reason they were all a mess and wrapped in classes...

Since I had to go digging to find a nice simple version of fnv1a originally (especially a 64 bit one), here are the implementations of the hash function I am using below along with the constexpr version. The license is public domain or an equivalent (a link would be nice so others may find it, but not necessary).

See the assembly output on Compiler Explorer.
Gist on Github

If you have any thoughts, feel free to send them my way:

runtime version

constexpr version

other uses

I shared this recently as another use case of hashes at compile time:

<![CDATA[Drifter 0.6.9 to 0.6.13 released]]>Drifter updates have been weekly so I collated the last few updates into one post. The updates are live on Steam and the Humble store.

Weekly releases continue, and we're aiming for one last update in the 0.6.x range since 0.7.0 is nearly done.

Add it

https://notes.underscorediscovery.com/drifter-0-6-9-to-0-6-13-released/77f583b2-9e71-4fd1-a810-455bb35f2bbcSun, 11 Sep 2016 07:39:00 GMT

Drifter updates have been weekly so I collated the last few updates into one post. The updates are live on Steam and the Humble store.

Weekly releases continue, and we're aiming for one last update in the 0.6.x range since 0.7.0 is nearly done.

Add it to your Steam wishlist if you haven't, review it if you're inclined. Thanks!

You can read the full announcements here.

• 0.6.9
• 0.6.10
• 0.6.11
• 0.6.12
• 0.6.13

Drifter 0.6.9 to 0.6.13 released Drifter 0.6.9 to 0.6.13 released Drifter 0.6.9 to 0.6.13 released Drifter 0.6.9 to 0.6.13 released Drifter 0.6.9 to 0.6.13 released

The store widgets to buy it are behind "read more", for your convenience.


<![CDATA[HTO 06 “kd”]]>◎ HTO project archives
     ○ ë̤̰́̄ͪntry 06 – “kd”

https://notes.underscorediscovery.com/hto-06-kd/fb2ef149-4cef-4b48-88e8-a03544b7033cSun, 21 Aug 2016 12:37:28 GMT

◎ HTO project archives
     ○ ë̤̰́̄ͪntry 06 – “kd”

HTO 06 “kd”

<![CDATA[HTO 05 “kn”]]>◎ HTO project archives
     ○ ë̤̰́̄ͪntry 05 – “kn”

https://notes.underscorediscovery.com/hto-05-kn/8bef5973-a3a2-4f17-9f26-7ad1de4dae12Sun, 21 Aug 2016 12:36:37 GMT

◎ HTO project archives
     ○ ë̤̰́̄ͪntry 05 – “kn”

HTO 05 “kn”

<![CDATA[HTO 04 “kh”]]>◎ HTO project archives
     ○ ë̤̰́̄ͪntry 04 – “kh”

https://notes.underscorediscovery.com/hto-04-kh/27986ee7-504f-4197-941a-7709379aa4b6Sun, 21 Aug 2016 12:35:11 GMT

◎ HTO project archives
     ○ ë̤̰́̄ͪntry 04 – “kh”

HTO 04 “kh”

<![CDATA[HTO 03 “ka”]]>◎ HTO project archives
     ○ ë̤̰́̄ͪntry 03 – “ka”

https://notes.underscorediscovery.com/hto-03-ka/9c7d33e7-775a-4c70-b543-1deb039e90a3Sun, 21 Aug 2016 12:34:19 GMT

◎ HTO project archives
     ○ ë̤̰́̄ͪntry 03 – “ka”

HTO 03 “ka”

<![CDATA[HTO 02 “ki”]]>◎ HTO project archives
     ○ ë̤̰́̄ͪntry 02 – “ki”

https://notes.underscorediscovery.com/hto-02-ki/61149927-bf78-4fa7-96af-75fc24f68e0eMon, 08 Aug 2016 18:14:42 GMT

◎ HTO project archives
     ○ ë̤̰́̄ͪntry 02 – “ki”

HTO 02 “ki”

<![CDATA[HTO 01 “kx”]]>◎ HTO project archives
     ○ entry 01 – “kx”


https://notes.underscorediscovery.com/hto-01/a99ddcdd-2e4e-442e-b603-c3bb868f30eeMon, 08 Aug 2016 18:13:41 GMT

◎ HTO project archives
     ○ entry 01 – “kx”

HTO 01 “kx”