Textual objectification

When a developer doesn’t update his devblog for a whole nine months but keeps working on his game all that time, you just know the end result is going to be something amazing, right? Well hold onto your hats – why you have multiple hats I don’t know – because here is the result of all my secret labour. Right here, right now:

 

Yeah.

You can probably see why I didn’t bother updating this blog now. I’ve been working on Tig, my compiled programming language, all this time, and programming languages just aren’t that exciting to blog about. Nor do they make for exciting videos. I didn’t even realise how amazing I was being until one day, out of curiosity, I turned on my text editor’s code-styling option – the setting that colourises for clarity. And wham! My bland, middle-class-white-boy code turned into this:

TigCode

I know! It’s like something you see scrolling up someone’s monitor in Mr Robot, right?

That was when it hit me: oh my God I’ve actually created a programming language.

That’s not C++ you’re looking at there, or whatever bobbins GameMaker uses. That’s Tig. That stuff is read by my compiler, turned into machine-independent bytecode, then run in-game to produce the video you saw above. Codewise, I’ve done something pretty incredible. For an English Lit student.

Yet when people ask me how the game’s going and I try to explain Tig to them, a sort of glazed, polite-but-where’s-nearest-exit look appears in their eyes. I can’t really blame them. Programming is hard and boring to explain, programming compiled programming languages doubly so. Indulge me in this quick BBC Bitesize summary and we’ll never speak of it again.

It’s an Object-Oriented Programming language
OOPs tie together related code and data in virtual objects that message each other. This is very handy for game design, where you’re basically making a world full of virtual objects that interact. Such as crates. In Tig, you make a crate by writing:

CGameObj crate has name “crate”, description “A standard wooden crate for use in games.”,
weight = 10;

This says “make an object derived from CGameObj and give it a property called ‘name’ set to the text ‘crate’, a property called ‘description’ set to the text ‘A standard wooden crate…’ and a property called ‘weight’ set to the integer 10. CGameObj is another, much more complicated Tig object that handles all the default game code for in-game items, such as printing the description text when you examine them. And this is the clever bit: because our crate is derived from CGameObj it will inherit all that functionality automatically. You don’t have to write another word.

Suppose you want the crate to shatter when it’s hit. The game calls an item’s ‘onHit’ property if it receives damage, but the CGameObj default onHit response is to do nothing. So we write this:

CShatterable has onHit() { print “The ” + name + ” shatters into pieces!”;
destroy self; };

Now if you derive our crate from CShatterable as well as from CGameObj, CShatterable will hijack onHit. The result: a fragile box that destroys itself on receiving damage, and tells the player this has happened. But the really clever bit is that now you can attach CShatterable to any item to get the same effect, whether it’s a Ming vase or a mastodon.

Want an exploding crate or mastodon? Write this:

CExplosive has onHit() { print “The ” + name + ” explodes in a fireball!”;
destroy self;
player.onHit(100); };

Notice how the exploding object will now use the player’s bespoke onHit property to give them splash damage.

Once you’ve coded a few useful template objects, you can create in-game items with quite complicated behaviour simply by combining them. This should pay big dividends later in the development cycle.

It creates its own hypertext
Interactive fiction is not cool. One of the reasons for this is that in an age of virtual-reality spaceships, you still have to laboriously type what you want to do in an IF game. I’ve tried to offset this a little by using hypertext, so you don’t type, you just click.

The clever bit isn’t the hypertext. The clever bit is that Tig will mostly hyper that text for you. If you write a room description that includes the text “…there is a narrow passage to the east”, Tig will understand that ‘east’ is a direction, and if you can go east from this room it will turn the word ‘east’ in that sentence into hypertext that will take you east when you click on it. If you write a room description that says “an old piano moulders in the corner” and you’ve coded a complicated piano for the player to interact with, Tig knows to make the word ‘piano’ hypertext and connect it to your piano code. Most of the hypertext you can see in that video – just about – is being created and removed on the fly by Tig.

So there you go. All this took a long time and an awful lot of work. One day it may yet end up in an actual game. Until then, I’ll try to code something less geeky for the next blog entry. See you in another nine months!

 

 

Advertisements

Of cats and cake

This has been a successful month, but not very graphically so, so you’ll just have to take my word for it. I created my own programming language, Tig, which is what Ghostworld will mostly be written in. It consists of a compiler, a virtual machine to run the compiled program on, and the language grammar itself. A very simple program written in Tig might look like this:

event robotTea { 
 "The robot abruptly turned around and glided away into the back room. I noticed that it had left its cream cake on the table.";
 option "I hurried after it." backRoom;
 option "I stealthily helped myself to another slice." stealCake;
 option "I remained seated." remain;
};

event backRoom {
 "The robot was just settling into an armchair as I arrived. ""Where is my cake?"" it demanded.";
 option "I apologised profusely." killed;
 option """Fetch your own damn cake."" I told it." killed;
};

event stealCake {
 "Just as I was tucking in, the robot returned. ""CAKETHIEF!"" it grated, and tore me limb from limb.";
 option "I allowed my ghost to float somewhat implausibly back in time to our first meeting..." robotTea;
 option "I decided to call it a day." quit;
};

event remain {
 "After a long time the robot returned, and cut itself another slice of cake.";
 option "I smiled nervously." robotTea;
};

event killed {
 "Alas, I had underestimated my host. ""BAD GUEST!"" it grated, and tore me limb from limb.";
 option "I allowed my ghost to float somewhat implausibly back in time to our first meeting..." robotTea;
 option "I decided to call it a day." quit;
};

event quit {
 "The end.";
 end;
};

If you compiled that source code and ran it on the virtual machine, you could interact with it like so:

The robot abruptly turned around and glided away into the back room. I noticed that it had left its cream cake on the table.
1: I hurried after it.
2: I stealthily helped myself to another slice.
3: I remained seated.

?1
The robot was just settling into an armchair as I arrived. “Where is my cake?” it demanded.
1: I apologised profusely.
2: “Fetch your own damn cake.” I told it. 

?2
Alas, I had underestimated my host. “BAD GUEST!” it grated, and tore me limb from limb.
1: I allowed my ghost to float somewhat implausibly back in time to our first meeting…
2: I decided to call it a day.

As you can see, Tig makes it easy to write branching narrative games. But it can already do a lot more. You can make player options execute code statements, such as “robot.temper = ‘piqued’;”. You can create objects simply by writing “object cake has description ‘A daunting confection of mascarpone and sponge’, weight = 20;”. Many more powerful features will follow.

Writing your own programming language is no easy task – why go to such trouble? One reason is that it’s a basic rule of good programming that you separate your code and your data. In the case of a platform game, for example, your code is the bit that handles input, graphics, and so forth, and the data is the level. You could mix all the level data in with your code, but it would result in a gigantic, unwieldy morass of numbers and C++ statements, and every time you wanted to change a single brick in one of your levels you would have to hack around in that monstrosity and then recompile the whole thing. Keep code and data separate, and all you have to do is write one clean function that does a thing when it encounters a brick, and you’re free to create and tinker with as many brick-based levels as you want in your level editor.

OK, so this argument gets stretched a teensy bit in the case of Ghostworld, because my game is a work of interactive fiction and so its data has to include code of its own – but, shut up, because the same principles still apply. A text-based, interactive game’s script is its data, and designing any game in its own dedicated, user-friendly language is far easier than trying to hard-code it in C++, or Unity or GameMaker for that matter.

The other reason I’m writing my own programming language is this guy:

Tig

Tig and Cas were our first cats, and Tig was the first to die, in 2008. It came out of nowhere, it wasn’t fair, and when he was gone I really missed that little guy. To amuse myself, and to keep his memory alive in some way, I decided to call the programming language I had just started to create back then ‘Tig’. I found the intricacies of language creation fascinating, and it became a wildly ambitious project, boasting dynamic typing, multiple inheritance, and much more. Alas, I was not a great coder in those days, and it was all built on messy, amateur, poorly thought-out C++. Improving it became harder and harder, until in the end I just quietly stopped, but I always felt a little pang of guilt for not doing right by my mog.

When I decided to make this game, I quickly decided that it needed its own scripting language, and I knew immediately what that language would be based on and what it would be called. I made myself start from scratch, but that first attempt helped hugely: I knew what worked and what didn’t, but most importantly this time around I knew how to code it properly, which is why this month has been a month of rock-solid progress. Thanks, little dude.

Strange fruit

October marks an exciting change in direction for the development of my game. Exciting if you’re the one who’s been writing the thing for the past five months, anyway. Less so for everyone else.

For a start, the game formerly known as ‘my game’ now has a tentative name. How does Ghostworld grab you? Yeah, I’m not too sure either, but it will do for now.

The bigger change is that I’m putting graphics development on the back burner for a while.

I had a six-month plan to produce a rough, playable game, where each month was dedicated to another part of the graphics engine. October was meant to be Make Buildings, and November Shadows and Water. But my game – sorry, Ghostworld – was always supposed to be a work of interactive fiction too, and I’ve been guilty of sidelining that. I started to feel a little uneasy a couple of weeks back, as I wrestled with recalcitrant fractal plants and realised I had a lot more work to do here, and also in a whole bunch of other graphics areas, before I would have anything that looked remotely like a game. Should I just plod on like this? And on, and on, and on?

The received wisdom is “no”. Derek Yu and some guy called Tom Francis both made playable prototypes of their games as quickly as possible, and then evolved them. A lot of other devs advocate the same approach. And it’s a lesson I’ve already learned over and over in fiction-writing: get a rough draft finished before you do anything else, as fast as you can, no matter how bad it is. If you stop to fix and polish bits, you lose momentum.

You don’t play with the graphics in my game. You play with the interactive fiction. If I want to make something playable, it’s the text side of things I have to get working first, as fast as I can. So that’s what I’m doing.

This will result in less graphically exciting blog posts, which is probably one of the subconscious reasons why I’ve been ignoring the IF stuff all this time. Another, I suspect, is that as long as I’m not working on the actual game, I don’t have to worry about how good that game is, or indeed how good I am at making games. I’ve been living with myself for some time now, you see, and I know how my mind works.

So here are some current screenshots of Bedquilt Land, just in case it’s a long time before I post any more:3DTest 2017-10-01 19-42-05-38.bmpScreenshot 2017-10-05 15.40.12Although the fractal tree improvement didn’t get very far, what I did achieve was to get trees and grass growing in more natural clusters, rather than uniform, unbroken swathes. So there’s that. And yes, my trees have square fruit now, shut up.

 

Committing trees-on

I think we can all agree that this looks pretty bloody amazing:

opener.png

That’s because this week I tackled something I’ve been wanting to explore for years: creating fractal trees. I’ve always been fascinated by fractal graphics, ever since the early days of grinding out the Mandlebrot Set pixel by pixel on a BBC Micro in a dizzying eight colours. And one branch – if you’ll pardon the expression – of fractal graphics is fractal trees. Using a few simple rules, recursively, it’s possible to create startlingly natural-looking vegetation. Once you know that, it’s very hard to look at plants and trees in the real world without noticing how they’re all made out of simple patterns recurring at different scales.

As I say, it’s something I’ve wanted to explore for years, but it’s only recently that I’ve had a platform on which to do so: my game engine. (Which I really should find a cooler name for than “my game engine”.) It turned out to be surprisingly easy to set up. In almost no time at all I had a little C++ class that made wireframe trees by recursively splitting branches into sub-branches, the sort of thing you’ve probably seen before:

Screenshot 2017-08-15 16.51.39

Then I added a function for creating solid 3D geometry, and got results like this:

Screenshot 2017-08-16 17.35.40

Finally, I added routines to temper the symmetry with randomisation, and a sample that had previously looked like a piece of broccoli turned into this:

Screenshot 2017-08-18 14.04.48

Isn’t that brilliant? And there are about 50 million more where that came from, because it’s all based on a random number seed. That’s what 740608 looks like, in case you were wondering.

I was so pleased with the result, and it was so near the end of the working week, that I almost left it there. But I just couldn’t resist seeing what would happen if I plugged my trees into the instanced drawing system I’d used to cover my procedural terrain with grass. Amazing scenes, that’s what happened. I’d totally forgotten that left to its own devices, my game engine colours every model differently, according to a simple algorithm for creating harmonic palette sequences. It’s like something out of The Magic Roundabout. Take a look.

How green was my valley

Screenshot 2017-08-11 11.39.18

…pretty f**king green, as it turns out.

Screenshot 2017-08-11 11.43.07

This is just a quick update to show what my terrain looks like when you replace comedy stand-in cubes with actual grass textures, which is what I spent this morning doing. The effect is amazing, if I say so myself. (And I do. “Amazing”. There you go.) I still can’t get over just how much stuff I can draw, and how fast, on today’s graphics hardware

The joke is, the finished game probably won’t even have grass in it. Or at least, not great rolling swards of it like this – I want it to look like an alien planet, not Middle-earth by way of New Zealand. But this was a great proof of concept.

Next task: making my grass sway gently in the breeze.

Screenshot 2017-08-11 11.52.43

…OK, the comedy stand-in coloured cubes were more fun. Let’s have the comedy stand-in coloured cubes again.

Instanced karma

This month is supposed to be about adding vegetation to my terrain. It started well, then went badly, and is now going well again. So that’s OK, I guess.

The good start was making a Poisson distribution function for grass. For a convincing 3D game landscape, your digital grass has to be spread out randomly but smoothly, and smoothly random is something computers are very bad at. If you just used an ordinary rand() function, it would end up an unrealistic mess of statistical gaps and clusters. Poisson distribution generates random points that are smoothly spread out, and I couldn’t have been more pleased with myself when I got that working.

Remind me again what pride comes before?

The next stage was to mould my 2D plane of smoothly distributed points over my 3D terrain. This is trickier than it sounds, because basically for each 2D point – and there are thousands and thousands of them – you have to sample all the vertical space they could occupy to find the surface of the terrain at that position. And you have to do it fast, because your player is waiting. Doing it fast means using shaders, and shaders can be a bugger to code.

I created a reference texture of my terrain’s height – a sort of snapshot from above – so that I could read the height values off of that as needed. And for some reason I could not read that damn texture back – I just got garbage or zeroes. I wasted the best part of week trying to find out why, because once I’d wasted a certain amount of time doing that I felt I had to keep going or I would have wasted even more time. The kicker is that I still don’t know: eventually I had to cut my loses and give up. Return on time invested: zero.

The good news is that I found a different solution, and a better one. I’m rather proud of it. I feed the points into a shader that samples the terrain at two different heights, and if the surface lies somewhere between them it calculates where by interpolation. The clever bit is that you do this about a dozen times, raising the sampling height each time and feeding the data it spits out back in as the next round of input. Your 2D points rise to the surface like bubbles in champagne.

Finally I could get onto the instancing, which is something I’ve been itching to try.

Instancing is where your graphics card saves you a massive amount of bandwidth by letting you draw the same model over and over again for almost no extra cost. If you ever wondered why games once couldn’t show you things like vast asteroid belts in Elite: Dangerous, and now they can, it’s because of instancing.

Making instanced grass can come later. After all my hard work mapping those evenly spread points to my terrain, I wanted to see how they looked. Answer: amazing. I knew instancing let you draw lots of the same thing at once really fast, but I was still amazed by just how many of that thing it would draw, without my badly unoptimised code even breaking a sweat.

If you ever wondered what seven hundred and thirty one thousand four hundred and sixty coloured cubes looks like, it looks like this:

Screenshot 2017-08-09 14.19.28

I had great fun running around what was suddenly a very busy landscape.

And then I had an idea. What would it look like if I turned off the landscape, and it was just cubes?

Answer: Even. More. Amazing:

 

 

A road trip in Dali country

After the previous month’s physics hell, July’s task was pretty much a holiday. A scenic journey with a dead Spanish surrealist artist doing the navigating.

For years and years now, long before I even started work on this engine, I’ve been fascinated by the idea of procedural terrain. Landscapes that just go on forever, without ever repeating. A whole, world-sized world inside your PC, that you could in theory spend the rest of your life wandering around, like some ice-bearded Edwardian explorer pointlessly mapping the endless wastes of the polar ice shelf. And all of it spun out of a small algorithm and a handful of numbers. “Wouldn’t it be great to make something like that myself one day,” I used to think.

Screenshot 2017-07-28 11.53.51

This was the month I finally got a taste of that. My scheduled task: “make playable terrain” – a vague goal for a vague concept, but I had some ideas.

One problem with procedural terrain is that it is naturally homogeneous: it may not repeat the same exact feature, but it will keep showing you the same kind of terrain, on and on. So once you’ve seen one area created by a particular algorithm, you’ve seen everything that algorithm has to offer. Exploring further becomes unrewarding, because everywhere looks like everywhere else. This was very much the problem with No Man’s Sky’s infinite worlds. In theory you had the dizzying prospect of a whole planet to explore; in reality, once you’d walked around the place for two minutes you’d seen everything you were ever going to see.

Another, subtler issue is that procedural terrain lacks drama. Good game terrain is normally handcrafted by a designer: you follow a preplanned route, the scenery changes to keep you engaged and to provoke particular moods. Epic vistas open up before you at the point when the designer wants you to feel epic. Procedural terrain, in comparison, can feel bland and meaningless.

Battling those twin challenges is going to be an ongoing project. This month’s task was all about finding and coding a small arsenal of techniques to bring to the fight: ways of making random landscapes interesting to be in. Things like Distant, Dramatic Mountains:

Screenshot 2017-07-28 10.19.17

In the finished game that flat, circular space will be where you play, and will have its own varied scenery. The Distant, Dramatic Mountains are simply there to give you something exciting to see on the horizon.

The real fun starts when you decide to throw in a little three-dimensional simplex noise to liven things up. Like so:

Screenshot 2017-07-29 11.32.17

Yeah, it’s kind of hard to see what’s going on in there, isn’t it it? But I think we can agree that it’s not boring. In fact, I ended up spending ages just wandering around that place, marvelling at its weird, Daliesque features and thinking “what hath God wrought?” God being me, in this instance.

A few snapshots:

Screenshot 2017-07-28 12.59.57Screenshot 2017-07-28 12.56.06Screenshot 2017-07-28 12.55.14Screenshot 2017-07-27 20.29.21Screenshot 2017-07-27 19.33.30Screenshot 2017-07-27 13.42.06

And that’s not the half of what I saw.