08 Mar 2017
Early update, this time, as I’m off to the UK for a wedding. Because of that – and because I’m meeting up with a friend
who’s helping me with some concept art – it’s been a race-to-make-a-face since my last post.
The second iteration of the test level is basically done. As I said, it’s super chunky and super low-poly, but it looks a lot better than my
first iteration. And I can get very dark areas, as well as very light areas. Pretty important for a Quake-a-like.
Although this scene is essentially outdoor, I don’t actually think I’ll do that in many of the levels. My plan for most of it is
to do something darker and not as well lit, but for the purposes of a test I just wanted to see if I could do both. So I’ve aped a bit of the
Quake 1 start thing, and done an imaginary “intro” level.
There’s a lot wrong with it; the scale is on the, er, large side – but the minute you start rocket jumping that’s less of a problem – there’s a lack of secondary motion – wibbly grass, lights swaying, stuff like that –
and hardly any props to dress the scene. Although the colours work for me, a bit more detail would definitely help.
I’m not too bothered about all this atm, the main function
of the test was to find a workflow that’s quick enough to let me bang out [reasonably] good looking geometry, and the lack of texturing definitely helps that. I’ve
gone from zero to a level I can run around, in 8 days. And half that time’s been trying to understand lighting. Nearly all the missing things
will happen over time and I can dress the scenes with more props as and when I make them. It’s how I worked the environment in Lumo.
I’m still toying with the idea of bevelling the larger geometry pieces as
the extra edges would play in the light. Nintendo do this all the time in Mario and Zelda, so it might be worth a test…
Anyway. After the mild depression at going down the wrong path and throwing out a couple of week’s work, this whole exercise turned out to be super useful. The untextured “matte” look forced me to work out how the baked lighting is applied, especially
when the various shadow schemes are thrown into the mix. There’s no where to hide so setting this up was a lot of trial and error, not helped by the
fact that my lighting build-quality was set to “preview” for God knows how long. That flushed out lots of stupid things, but derp. Fucking idiot, etc.
The Modo side of things has been great, although it took me a long time to uvunwrap for clean bakes. Initially I was just ignoring it, letting the UE importer
generate the lightmaps and then wondering why I had dirty big splotches everywhere. Then I started adding a second UV channel in the model to mitigate,
which gives some control over how the model parts are split. But the real-trick, which it took me a couple of days to clock-on to, is making sure edges/verts
are clamped to texel boundaries. In Modo this is trivial, you can set the UVGrid to 1/64, and then use the snapping tool to make sure that edges/verts are all
nice and clean. It’s a bit handraulic, but if done right, a one shot deal. I think.
I still have some light-bleeding in parts of the level, but this is either where I’ve not added an edge to the wall (one model) where it meets the floors
(a different model), or have a polygon that extrudes through the wall, so catches the light and the dark. The second issue is just me not knowing what I was
doing at the start and then being too lazy to go back in and fix it. You can see it on the window frames.
I’ve also had a good play around with Cascade, and although I don’t feel as confident with it as Unity’s particle system, I’m able to do the basics. The same
can be pretty much said for the material editor. I’m hoping to pick stuff up via osmosis and concentrate on the big things for the foreseeable.
Code-wise, I don’t think I’ve had any problems. I’ve even started doing a few things – the on screen messages for example – in Blueprints. Quick and dirty is,
as Quick and Dirty does, and all that.
I’ve stuck a little video of all this up on You Tube. It should go without saying that the Quake 1 sound effects won’t be there for long, and everything is liable
to change. It’s heading in the right direction, though.
Click screenies to enbiggen.
24 Feb 2017
Oops, I missed a week and the devlog is late. Sorry! Game Dev and all that. Shipping late’s what we do…
I put off posting as I was hopeful that I’d have something nice to show, but things haven’t quite worked out as planned:
I added a damage effect – the “damage beans” – on the screen edges to indicate that the player’s been hurt. It’s a simple post-process overlay, but with a normal map added you get a nice distortion of the
screen as it fades in and out. Standard stuff for the most part. Except I have two versions, one that’s a blood-splat, and one that’s a nice high-res picture of actual baked beans. :D
I’ve also had a quick play with the audio system in UE4. My natural inclination is to integrate FMOD, but I’m hearing from fellow developers on Mastodon that UE4’s system is pretty good, and from the quick tests
it might well be. Audio attenuation and geometry occlusion definite seem to work, which could be enough for what I need.
But for the last 10 days or so I’ve been playing around with look and feel tests.
This skybox got me into a lot of trouble.
My intention with Next Game is to do everything quite low-poly and avoid as much texturing as possible. One reason for that is to look different, but texturing and modelling
take time, and time/money aren’t something that I have a lot of. If I have to get into texturing then I’d probably go for something old-school, like Gibhard or Strafe, but for obvious reasons I’d like to avoid that.
I think every man and his dog will be doing that style in a year or two…
Unfortunately having a super realistic skybox lead me down a path where geometry got a bit too complex, and things rapidly looked incongruous when flat-shaded with high quality lighting. Basically, I couldn’t get it to look good unless it was
extremely high-contrast. Which was unplayable. Although, I did spend a day flirting with an entirely black-and-white grading that I might go back to for some levels.
Anyway, I’ve thrown away all that work. All the geometry modelled so far, the test level, the greybox, all the materials and all the textures. That stung a bit.
This week I started again, but from a better footing: I chose a nice, harmonious, palette, and put a simple gradient in the sky-box. The palette is very limited: four base colours, four shades of each colour, and a gradient from top to bottom of each colour. I’ll
most likely add to that over time, but for now this is working well.
UV-unwrapping can be done extremely quickly. Anything single colour can just be atlas unwrapped and pushed over the appropriate shade in the texture, while things with gradients just need a little
more attention to align them properly. Because the palette is fixed, everything sits in the scene, and with some lightmass settings tweaked I’m getting really rich colour gradients, colour bounces being picked up and
deep shadows. It looks better, basically. It’s also super colourful, to the point of being cartoony – far too much for this game – but I find it easier to turn everything up to 11 and then slowly dial it in over time. (Early screenshots of Lumo are
practically black because I was shooting for a Scooby-Doo vibe. The final game looks nothing like it…)
What needs sorting out now is the correct scale for things. My character moves extremely quickly, and rocket jumps go for miles. This will take a bit of two-and-fro, but that’s next week’s mission. At the minute everything’s a little too big but I find it quite endearing. Iterate, iterate.
Still train-coding my way through this and the big news is, the tile map editor that I said I’d never write is basically done. It’s missing the ability to create re-usable brushes from placed tiles, so I might go back and add that at some point, but bar some tidying up and
deciding on the save format it’s doing what I’ll need. This threw up a couple of interesting things.
I was about to delve into the murk of C’s directory and file-handling, which is annoyingly different depending on the platform, but decided to have a quick search through Github to see what was already out there, and came across this little gem: Tinydir,
While testing the tilemap editor I thought I’d throw in some massive numbers to see how it performed. Turns out things started crawling pretty quickly, which was er, a shock. After pushing it through Richard Mitton’s Very Sleepy
the hot spot seemed to be in how I’m populating the VBOs, which again, was a bit of a surprise. This was supposed to be an optimised version of what I’d written a few years back on iOS…
For some reason I was only getting ~8k sprites per frame. I was expecting quite a few more. The culprit was this line:
mTransform = mTranslate * mRotation * mScale;
Pretty standard stuff, this is just creating the translation matrix which I’m pushing all my vertices through before copying the result into the VBO. (Yes, at some point I should just do all that into the shader…) I’ve done this before and had much better performance,
except then I was using my own math class, and this time I’m using OpenGL Math. I figured it’d be better to pass off the optimisation and maintenance of my maths stuff to, well, people that know some maths.
So I dug into the operator * overload:
GLM_FUNC_QUALIFIER tmat4x4<T, P> operator*(tmat4x4<T, P> const & m1, tmat4x4<T, P> const & m2)
typename tmat4x4<T, P>::col_type const SrcA0 = m1;
typename tmat4x4<T, P>::col_type const SrcA1 = m1;
typename tmat4x4<T, P>::col_type const SrcA2 = m1;
typename tmat4x4<T, P>::col_type const SrcA3 = m1;
typename tmat4x4<T, P>::col_type const SrcB0 = m2;
typename tmat4x4<T, P>::col_type const SrcB1 = m2;
typename tmat4x4<T, P>::col_type const SrcB2 = m2;
typename tmat4x4<T, P>::col_type const SrcB3 = m2;
tmat4x4<T, P> Result(uninitialize);
Result = SrcA0 * SrcB0 + SrcA1 * SrcB0 + SrcA2 * SrcB0 + SrcA3 * SrcB0;
Result = SrcA0 * SrcB1 + SrcA1 * SrcB1 + SrcA2 * SrcB1 + SrcA3 * SrcB1;
Result = SrcA0 * SrcB2 + SrcA1 * SrcB2 + SrcA2 * SrcB2 + SrcA3 * SrcB2;
Result = SrcA0 * SrcB3 + SrcA1 * SrcB3 + SrcA2 * SrcB3 + SrcA3 * SrcB3;
Ow. That’s creating a lot of vec4 variables over the course of a few thousand sprites.
I admit, I’m learning GLM as I go, and maybe there’re some functions to do mat4 multiplications in place but the docs make my nose bleed, and to be honest I couldn’t be arsed to trawl through it all.
So instead of using a glm::mat4, my matrix is now a simple array, allocated at the start of the function, that only contains the scale and rotation. I can push the sprite corners through this
and add the translation, and remove a lot of obviously zero multiplications from the process.
vBL.x = (vBL_Pos->x * s_mTransMat) + (vBL_Pos->y * s_mTransMat) + vPos->x;
vBL.y = (vBL_Pos->y * s_mTransMat) + (vBL_Pos->y * s_mTransMat) + vPos->y;
vBL.z = vPos->z;
This is fine for 2D stuff, which is all I intend to use this engine for.
And the result? About a 15x speed-up. In fact, I get exactly the same number of sprites out of a single thread on my X1 laptop, as I do on my big fat devrig: ~150k @ 60fps.
I’ll probably look to multi-thread this once the physics engine and fmod have been integrated, but for now it’s more than good enough for a little shoot-em-up.
The moral of the story: Future Gareth, you should probably look into how to use GLM properly.
03 Feb 2017
It’s been a mad-cap couple of weeks. Here’s what I’ve been up to:
Yesterday I pushed out version 1.17.2, to fix issues found with wireless Xbone pads running on Windows 7. Thanks go out to
Patrick Hogan — the developer of InControl, a nice cross platform input library for Unity that I can recommend, available here — for sparing the time to test around the issue and provide a fix.
In addition to taking on the new version of InControl, I’ve also moved over to XInput, so — in theory — joypad support should be a
little more robust on Windows going forward. (Crosses Fingers)
This build also fixes a possible bug with joypad “submit” actions not being registered by the pause screen UI, as well as turning
off Unity’s bullshit “automatic” navigation option on some of the button layouts. Honestly, fuck that UI system.
I’ve been doing a bit of train / weekend coding, so this has moved forward:
- Finished off the Input system. You can now poll mouse and up to four joypads. Previously it only handled attach/dettach events.
- Added some keystate handling for specific inputs in editor modes (keyboard shortcuts, basically)
- Added a bunch of helper functions to quickly get sprites from texture pages
- Got the Tile Map editor to the point where you can select and place tiles, freely, or snapped to a grid
Next job is to store that in something I can spit out and reload that’ll be the basis of the level data. I’ll probably do a very thin
Command pattern wrapper over this so I can support unlimited Undo/Redo as well.
I’ve been all over the shop with this the last couple of weeks:
- Finished off the weapon-types code and added weapon pickups
- Player can now be killed, either through damage or falling out of the world
- Player respawns properly
- Added Ammo to the HUD
- Added decals, and spent a morning drawing swears on walls
- Added a new “Pain Room” to the test room, for traps and damage/stat tweaking
- Dipped my toe into Cascade, UE4’s particle system, and made some effects for pickups
- Started on a shotgun model for the first person view
- Added some new models for the ammunition pickpus
The last item in that list has been my main diversion since the last post.
I know that I’m going to be doing a fair amount of modelling on this project so I’m still slowly schooling myself on workflows. For this, I decided
to do some fairly high poly models of the pickup items and then bake them down to a low poly cage. Like everything, once I worked out how to
do it, it’s reasonably straight forward, but it took a day or so to really get it working.
Building low poly cages seems to be a bit of an art, depending on the sorts of shapes you want, but after a lot of attempts I was able to bake AO and
normals in Modo that looked pretty clean on the low poly asset, and came out clearly in-engine. I’m far from an expert at this, but it’s something I
wanted to have in the toolbox even if I don’t use it very often.
I also spent a day or two messing about with Substance Painter. The “rent to own” model really appeals to me, as well as fitting in my budget, so I
jumped on that. It’s a little unstable on my rig - I’ve had 4 or 5 really messy crashes - but when it’s working, it’s great. I doubt I’ll delve too
deeply into the materials for this game, but anything that speeds up texturing is going to be worth the effort learning.
Now that Vine is dead I’ve started posting screenshots and little vids onto my Instagram account. You can keep an eye-out, here.
Also, there’s been a big migration of developers from Twitter onto Mastodon.social. If you’re a twitter user then I don’t really need to explain why this
is happening, but if not and you’re interested in a low traffic, Nazi-free open source Twitter-alike then Mastodon is worth
checking out. I’m @korruptor as usual.
28 Jan 2017
I’m interrupting normal blogging service to give a shout out to Visual Studio Code, on Linux. I
was put onto it by one of my students, and I’ve been running it for the last week as a daily driver when
train-coding. And it’s great.
Normally I use Emacs or Vim, depending on the mood, and I have done for years, but both of them require a
fair bit of setup, and I’ve always got a second terminal open for compilation / launching
Visual Studio Code, while not quite as nice as either of those from the text editing pov, is easily on a
par with something like Sublime Text, but with a special party trick: it integrates extremely well with GCC & GDB.
You can setup a problem parser, which will grep gcc’s output, allowing you to quickly jump to compilation errors, and
it’ll launch GDB and act as a front-end, allowing you to hover-inspect variables and do all the things you’d
expect from a larger IDE.
And it’s nippy. Surprisingly nippy. In fact, for C/C++ programming, this has quickly become my go-to editor
on Linux. I can heartily recommend it.
If there’s one nitpick, it’s the lack of horizontal splits. Something Visual Studio seems to be partially
allergic to, as well. But other than that, if you’re a Linux coder and you want some of the trappings of an
IDE, without installing something shit like Eclipse, or slow and lethargic like QT Creator, VS Code is well
worth checking out.
And I can’t believe I’m saying that.
20 Jan 2017
Bar teaching, the last two weeks have been entirely focused on Next Game, so I’ve managed to get quite a lot done.
Character movement is essentially ‘finished’. It’s pretty nippy - Quake 1 fast, in fact - but it feels nice and responsive. At least to me . Rocket Jumps will be featuring heavily, so spending the time to play around with this in order to get the height and distance nailed, was essential. Changes from here-on will just be tiny number tweaks, so I’m at the point now where I feel safe to begin whiteboxing levels.
The player’s inventory management is also working. You can cycle through weapons, pick up armour and health, as well as take damage. Armour modifiers still need to be added but I know exactly how these will operate.
UE’s weapon and projectile systems took a while to figure out, but I do now have 3 basic types that should cover everything I intend to use:
- Projectile based: rocket launcher / nail gun, stuff like that.
- Instant shot: Pistols
- Instant multi-shot: Shotguns.
Weapons have individual fire rates, can spawn splash damage areas and their damage can attenuate over distance. The only thing you might expect that’s missing - especially if you play something like COD - is projectile penetration. I’m toying with the idea of adding this, but right now my guess is that it’ll be pretty useless within the sort of levels that I intend to create.
None of the weapons have been properly setup atm, as that’s something I’ll do once some NPCs are in. I need moving targets to shoot at!
I’ve also had a crash course in the localisation system, configuring animation blueprints, playing audio and have dipped my toe into Cascade again.
For the most part the last two weeks have been really productive, but I’ve been badly burned by a couple of things. One of the worst was discovering that UE4 types get garbage-collected quite aggressively. If, say, you have a TArray of elements but don’t add the UPROPERTY() macro above their definition, then at some point they’ll disappear from under you. It took me a few hours to work out exactly what was causing the crash and why, as it was appearing fairly randomly - and taking the editor out with it - but like everything, it’s completely obvious once you spot it.
I’ve also learned the hard way that Play In Editor - PIE - masks a certain type of class initialisation bug. Stupidly, I had a set of FText variables defined outside the class (they were static char arrays at first) which compiled perfectly fine, and even ran in the editor, but cooked builds would immediately crash. It took me a couple of hours to realise that it wasn’t my Anti Virus, or some auto-build failure, but UE4 barfing when trying to initialise the variable before the engine had started up. This was happening before the splash screen was appearing, so I wasn’t even getting a log to help… Again, totally obvious once you spot it.
I probably lost a day bug hunting this stuff, so I’m a little behind where I wanted to be this week - ammo pickups are half done, and weapon pickups haven’t been started - but I’m basically at the point where I can play around with some look and feel tests, and maybe start white-boxing some spaces to run around in. I’m also growing in confidence with the engine and my ability to at least fix my own fuck-ups, so it’s probably a net win…
I’ve added a little video to You Tube for those who want a peek (see the top of this post). It should go without saying that none of the assets in this are final, or even likely to appear in-game. It’s bits and bobs from Lumo and UE4’s example assets, that I’ve thrown together. Although I did lose a good chunk of time over Xmas playing with the lighting and post, just to see how it worked ;D
The music is by Steve Birch, from the album Wonderland, that’ll be released by Joof sometime in Feb.