Alan Edwardes

Cloud Software, Game Dev & IoT
  • About
  • Projects
  • Blog
  • material
  • game
  • file
  • pico
  • image
  • level
  • framebuffer
  • sensor
  • stream
  • light
  • data
  • application
  • estranged
  • pi
  • layer
  • s3
  • engine
  • unreal
  • command
  • raspberry
  • byte
  • texture
  • cloudfront
  • code
  • video

Posts in 2026

  • Anti-Aliased MicroPython Fonts with a Few Kilobytes of Memory on 8 of Mar
  • Driving SPI Displays with Vanilla MicroPython on 6 of Mar

Posts in 2025

  • Drawing Images Quickly with PicoGraphics and MicroPython on 28 of Jun
  • Replicating the iOS Lock Screen Temperature Gauge on 17 of Jun
  • Streaming Video to a Pico 1 with MicroPython on 8 of Jun

Posts in 2024

  • Update News Presentation Markup for Games on 6 of Oct
  • Remembering USB Devices in VMware ESXi on 13 of Sep
  • Automatically Mounting USB Disks on Ubuntu on 12 of Sep
  • Raspberry Pi Pico HTTP Admin Dashboard on 12 of Aug
  • Raspberry Pi Pico Ionising Radiation Sensor on 7 of Aug
  • Loki and Grafana for Logs on 17 of May
  • Optimising Rocket Chat Content Delivery with CloudFront on 27 of Apr
  • Raspberry Pi Pico W WiFi Resiliency on 17 of Mar
  • Raspberry Pi Pico Carbon Dioxide Sensor on 7 of Mar
  • Using a New Hard Disk on Ubuntu on 2 of Feb
  • 10 Year Anniversary of Estranged on 16 of Jan

Posts in 2023

  • Raspberry Pi Pico Home Assistant Motion & Temperature Sensor on 12 of Nov
  • Racing Tasks in C♯ on 8 of Oct
  • Using Material Layers in UE5 on 23 of Sep
  • Running Rocket Chat on an Intel Celron CPU in 2023 on 25 of Mar
  • Running Rocket Chat on a Raspberry Pi in 2023 on 15 of Mar
  • Fixing UE5 Actors Disappearing when Building Lighting on 1 of Jan
  • Fixing UE5 Level Sequence Assertion on 1 of Jan

Posts in 2022

  • Raspberry Pi with Docker on 30 of Dec
  • Fixing UE5 Chaos Events at Runtime on 27 of Dec
  • Scam Warning on 26 of Nov
  • Casting Video to VLC via Home Assistant on 20 of Nov
  • Advanced Git LFS and Jenkins on 16 of Nov
  • Baking Ambient Occlusion using Blender on 2 of Oct
  • Live GivEnergy PV Inverter Data in Home Assistant on 10 of Apr
  • Useful ffmpeg Recipes on 31 of Jan
  • Force Refresh Rocket.Chat Snap SSL Certificate via Caddy on 29 of Jan

Posts in 2021

  • Pushing to Public AWS Container Registry with GitHub Actions on 23 of May
  • Graphing Sensor Data from a Raspberry Pi with Grafana on 22 of May
  • Create Meshes from Height Maps using Blender on 16 of May
  • Recording Camera Animations for UE4 with a Phone on 15 of May
  • The Art of Mirror's Edge on 11 of Apr
  • Serving Static Websites Using Lambda@Edge on 20 of Mar
  • Thread Safe Random in C♯ on 16 of Mar
  • Spotting Fake Indie Game Key Requests on 11 of Mar
  • Jenkins Library for Unreal Engine 4 on 13 of Feb
  • Three Approaches to Readable Materials in First Person Games on 7 of Feb
  • Cheap Synthetic Monitoring with AWS Lambda on 24 of Jan

Posts in 2020

  • Generating Mipmaps for Render Targets in UE4 on 24 of Dec
  • Routing DNS over HTTPS Using Raspberry Pi on 6 of Oct
  • Tips for Building Games with Unreal Engine 4 on 3 of Oct
  • Serving Localised Assets from S3 Using Lambda@Edge on 17 of May

Posts in 2019

  • Automating macOS Notarization for UE4 on 23 of Nov

Posts in 2018

  • ISO Country Code to Unicode Flag in C♯ and JavaScript on 22 of Jul
  • Serverless Git LFS for Game Development on 6 of Jan
  • Adding Custom Map Checks in UE4 on 3 of Jan

Posts in 2017

  • Building and Deploying a React App Using AWS Lambda on 24 of Dec
  • Git HTTP Username and Password in Environment Variables on 22 of Dec
  • Capturing and Uploading Screenshots in UE4 on 20 of Dec
  • Using Capsule Shadows on Large Objects in UE4 on 8 of Dec
Featured: 10 Year Anniversary of Estranged
Featured: Using Material Layers in UE5
Featured: Create Meshes from Height Maps using Blender

Anti-Aliased MicroPython Fonts with a Few Kilobytes of Memory

📅 8 March 2026 🔖 iot ⏲️ 8 minutes to read

If you've been following the other posts on this project, the previous entry covered how I replaced PicoGraphics with a custom framebuffer stack that drives SPI displays using vanilla MicroPython. With the display layer working, I needed a way to actually draw text.

The built-in framebuf module includes a minimal 8x8 pixel font, which is functional but too coarse for a real information display. I wanted proportional, anti-aliased text rendered from proper font files, and that meant implementing a BMFont loader (bmfont.py).

Continue Reading »

Driving SPI Displays with Vanilla MicroPython

📅 6 March 2026 🔖 iot ⏲️ 7 minutes to read

If you've been following the other posts, you'll know that I've been building an information display for my home using a Raspberry Pi Pico and MicroPython. The previous post on drawing images with PicoGraphics covered how to render raw framebuffer images efficiently using Pimoroni's custom MicroPython fork.

Since then, I've moved away from PicoGraphics entirely and replaced it with a custom framebuffer, a drawing class, and display drivers that work with vanilla MicroPython. I wanted to learn more about driving SPI displays directly, and to have a codebase that runs on any board MicroPython supports without needing a specific firmware build.

Continue Reading »

Drawing Images Quickly with PicoGraphics and MicroPython

📅 28 June 2025 🔖 iot ⏲️ 3 minutes to read

If you've been following the other posts, you'll know that I managed to get Streaming Video to a Pico 1 with MicroPython at 5FPS. This post builds on the streaming video implementaiton to answer a more practical question - how you render images to the screen quickly and efficiently with PicoGraphics? The image we'll be rendering is insulam.rgb565be.

There are some methods listed in the PicoGraphics documentation using Sprites, JPEG and PNG. However, what I don't like about these techniques is that they all load the image into memory, and they don't provide a way to clear that memory. If you have a long-lived application which cycles through different screens with different images, then you're going to run out of RAM (especially on the Raspberry Pi Pico 1 or 2).

Continue Reading »

Replicating the iOS Lock Screen Temperature Gauge

📅 17 June 2025 🔖 iot ⏲️ 2 minutes to read

I have always liked the iOS lock screen temperature gauge, as it allows you to see the current, minimum and maximum temperature at a glance, including a visual to show you how close you are to the extremes. It's a continuation of Apple's skeuomorphism, given it resembles a real thermostat but is also quite stylised.

This is an HTML canvas version of this element, drawn using circles and some basic trigonometry (see how it scales to full screen). I optimised for simplicity to allow me to port it over to a drawing library for MicroPython to draw it with a Raspberry Pi Pico. More on that later.

Continue Reading »

Streaming Video to a Pico 1 with MicroPython

📅 8 June 2025 🔖 iot ⏲️ 6 minutes to read

I've been doing a bit of graphics experimentation recently with a Pimoroni Pico Display Pack 2.0 attached to a Raspberry Pi Pico W (with the RP2040 microcontroller). I got interested in rendering sprites, and decided to see how quickly you can actually get pixels on screen. This lead me to exploring the different framebuffer formats, and how to get bytes from the network onto the screen with MicroPython.

Continue Reading »

Update News Presentation Markup for Games

📅 6 October 2024 🔖 game-development ⏲️ 4 minutes to read

During the development of Estranged: The Departure, I needed a way to bring update news posts into the main game menu, to allow players at a glance to see "what's new". Below is the final result - responsive, scrollable, native news UI which optionally links out to a browser.

Continue Reading »

Raspberry Pi Pico HTTP Admin Dashboard

📅 12 August 2024, updated 12 September 2024 🔖 iot ⏲️ 1 minute to read

A simple way to deploy code to a Raspberry Pi Pico involves plugging the device into a USB port and uploading the code using a tool like Thonny. However, when the Pico is set up somewhere, in an enclosure with peripherals attached to it, a remote management solution is better.

Continue Reading »

Raspberry Pi Pico Ionising Radiation Sensor

📅 7 August 2024, updated 13 August 2024 🔖 iot ⏲️ 2 minutes to read

I'm recording CO2 levels, motion, temperature, humidity and atmospheric pressure, so what's left to detect? Ambient ionising radiation, of course! ☢️ As with the other Raspberry Pi Pico sensors, this one will report back to Home Assistant to allow plotting the radiation over time in μSv/h (microsieverts per hour).

Continue Reading »

Loki and Grafana for Logs

📅 17 May 2024 🔖 cloud-software ⏲️ 2 minutes to read

I wanted to aggregate logs from a few different servers I'm responsible for; some in the cloud, some on my own network. Since it's all personal stuff, I didn't want to pay for Splunk or similar to do the ingestion/log aggregation, so opted for Grafana Loki as a self-hosted solution.

Continue Reading »

Optimising Rocket Chat Content Delivery with CloudFront

📅 27 April 2024, updated 3 May 2024 🔖 cloud-software ⏲️ 6 minutes to read

It's recommended to use Rocket Chat with either Amazon S3 or Google Cloud Storage to store uploaded files. However when downloading files stored with these solutions, there is typically a redirect to the blob store to actually obtain the data. This post discusses how to eliminate intermediate redirects and leverage edge caching using Amazon CloudFront.

Continue Reading »

Raspberry Pi Pico Carbon Dioxide Sensor

📅 7 March 2024 🔖 iot ⏲️ 1 minute to read

I decided to monitor the CO2 levels in my home office, and building on my previous Rasberry Pi Pico project I swapped out the BME280 Breakout with an SCD41 Breakout (and this time, a JST-SH cable so I didn't need to solder it):

This breakout is significantly more expensive than a temperature monitor, but it's a significantly more complex sensor (and includes temperature and humidity monitoring - so you essentially also get a BME280 chip without atmospheric pressure).

Continue Reading »

10 Year Anniversary of Estranged

📅 16 January 2024, updated 3 February 2024 🔖 game-development ⏲️ 1 minute to read

10 years ago today, Estranged: Act I was released. Since then, there have been well over a million unique players, with nearly 7k reviews and the title sits with a Steam rating of 93%.

Continue Reading »

Raspberry Pi Pico Home Assistant Motion & Temperature Sensor

📅 12 November 2023, updated 20 August 2024 🔖 iot ⏲️ 7 minutes to read

As an learning opportunity I wanted to see if I could create a temperature and motion sensor, running my own code on a hard-wired Raspberry Pi Pico, sending data via WiFi to Home Assistant.

The Raspberry Pi Pico W is a cheap board with two CPU cores, WiFi, 2MB of flash storage, and 264KB of RAM. It is capable of running Python code via MicroPython, which is what I wanted to use (rather than something like C).

Continue Reading »

Racing Tasks in C♯

📅 8 October 2023 🔖 c-sharp ⏲️ 2 minutes to read

In general, when running Tasks in C♯, you want to run one, or multiple in parallel, and continue executing code when they all complete (to process the result for example). The normal thing to do there is use Task.WhenAll.

Occasionally you might have a case where you want to run multiple tasks at once, and continue when one has completed (either by succeeding or failing). For that, you can use Task.WhenAny.

However: what if you wanted to execute a set of tasks, and not take the first completed one, but the first successful one? In other words, race the tasks, and if one of them falls over, they lose the race.

Continue Reading »

Using Material Layers in UE5

📅 23 September 2023 🔖 game-development ⏲️ 6 minutes to read

Material Layers are a feature of Unreal Engine 5 (and were actually present in 4.26). This feature allows you to build up modular material node graphs, then pick and chose bits you want when editing Material Instances - including choosing the order and how the layers are blended together.

The above screenshot showcases a layered approach to a plaster material, with multiple layers used to control the base textures, detail textures and to modify the base color.

Continue Reading »

Raspberry Pi with Docker

📅 30 December 2022, updated 8 March 2025 🔖 iot ⏲️ 3 minutes to read

I use Raspberry Pis to host services for my home network, with Docker to keep things manageable in containers. Each Pi has a USB SSD as its boot drive running Raspberry Pi OS.

There's often a bit of boilerplate I need to keep track of to set up a new one, so I am documenting all of the snippets here for my future self.

Continue Reading »

Fixing UE5 Chaos Events at Runtime

📅 27 December 2022 🔖 game-development ⏲️ 1 minute to read

This is the normal way to receive Chaos events in Unreal Engine 5.1.0, via the editor:

However, if you want to enable these events (OnChaosBreakEvent, OnChaosRemovalEvent, OnChaosCrumblingEvent) programatically without checking them in the editor, you need to do one of the following.

Continue Reading »

Scam Warning

📅 26 November 2022, updated 9 June 2023 🔖 game-development ⏲️ 2 minutes to read

There are one or more users impersonating me on Discord and other platforms in order to scam people.

If your Steam account has been stolen:

  1. Contact Steam Support directly at help.steampowered.com
  2. If the scammer contacted you via Discord, report the account to Discord Trust and Safety

Here are some simple tips to help identify scammers:

  • I will not communicate with you via Direct Messages on any platform
  • I am alanedwardes (previously Alan Edwardes#3608) on Discord, and only communicate via discord.gg/estranged and the Steam forums for the Estranged games
  • If you are added by a Discord profile with my name, it is an impersonator, and the account should be reported to Discord Trust and Safety via https://support.discord.com/hc/en-us/requests/new
  • If you are added by a Steam profile with my name, it is an impersonator, and the account should be reported to Steam Support via https://help.steampowered.com/en/faqs/view/4D07-D139-587C-2080
  • I do not work for Valve (Steam), and will never ask for account passwords, or money (I will not send a direct message to you in the first place)
  • See the contact page for a list of my official accounts.

I also posted similar messages to the Estranged: The Departure Steam Community, Estranged Discord and Twitter.

Continue Reading »

Casting Video to VLC via Home Assistant

📅 20 November 2022, updated 4 January 2023 🔖 iot ⏲️ 2 minutes to read

Home Assistant offers an integration with VLC via Telnet. It uses VLC's telnet capabilities to control it. However, the integration is geared towards VLC being run on the command line in headless mode, for audio only applications.

I had a different problem to solve: I have a Raspberry Pi running the VLC GUI on a full blown desktop, and want to be able to "cast" videos to it using the Media Player built into Home Assistant.

This essentially allows you to make the device running VLC with a screen attached a Chromecast-like media player, with the most powerful media player out there as its driver.

Continue Reading »

Advanced Git LFS and Jenkins

📅 16 November 2022 🔖 cloud-software ⏲️ 2 minutes to read

I use Jenkins to build Estranged, with Git + LFS.

Recently, I upgraded Git, LFS, and Jenkins, and things stopped working. The checkout strategy I use for Estranged is:

  1. Check out the Git repo, do not perform an LFS pull
  2. Set up Git LFS to use a shared LFS cache
  3. Set up Git LFS credentials to obtain objects not in the cache
  4. Perform the LFS pull

This stopped working when I upgraded the components involved. Read on for the retrospective write-up of the problems and how I fixed them.

Continue Reading »

Baking Ambient Occlusion using Blender

📅 2 October 2022 🔖 game-development ⏲️ 2 minutes to read

Ambient occlusion is the shadow caused by the mesh itself, so for example in the corners of the mesh. Here's a sample of a crate mesh with only its ambient occlusion texture visible:

Below is the crate mesh with the same ambient occlusion texture combined with the diffuse texture:

Continue Reading »

Live GivEnergy PV Inverter Data in Home Assistant

📅 10 April 2022, updated 30 December 2022 🔖 iot ⏲️ 2 minutes to read

I recently had solar panels installed, which included an inverter from GivEnergy.

If you want to analyse your usage, the GivEnergy portal allows you to do that, with graphs to explore the data over time. However, it has one big limitation: the data in the web portal is sent every 5 minutes from the inverter, meaning you can't get live data out of the system.

GivEnergy do publish a tool which you can run inside your home network, which will connect to the inverter over TCP, then forward any data it sends to an MQTT broker.

Continue Reading »

Useful ffmpeg Recipes

📅 31 January 2022, updated 2 October 2025 🔖 tools ⏲️ 2 minutes to read

A few ffmpeg commands I find useful, so I don't need to keep reading the documentation.

Contents

  1. [Convert to mp4]
  2. [Concatenate]
  3. [Speed Up]
  4. [Seek and Crop]
  5. [Resize]
  6. [Create Animated Gif]
  7. [Merge Audio into a Video with Audio]
  8. [Stream Video Device via TCP]
  9. [List Suported Formats for Device]

Continue Reading »

Force Refresh Rocket.Chat Snap SSL Certificate via Caddy

📅 29 January 2022 🔖 cloud-software ⏲️ 1 minute to read

I use Rocket.Chat installed via Snap on a Ubuntu VPS instance. The instance automatically manages its own SSL certificate via Caddy, using Let's Encrypt as the certificate issuer.

It has been working well for a few years, however today I opened up the web interface and was greeted by this error:

SEC_ERROR_REVOKED_CERTIFICATE

Fortunately I remembered the following email from Let's Encrypt, which I had completely ignored at the time:

Please immediately renew your TLS certificate(s) that were issued from Let's Encrypt using the TLS-ALPN-01 validation method and the following ACME registration (account) ID(s):

Continue Reading »

Pushing to Public AWS Container Registry with GitHub Actions

📅 23 May 2021 🔖 cloud-software ⏲️ 1 minute to read

I wanted to push a Docker container I use for some automation tasks to my own public container registry, because it would mean I didn't need to deal with authentication on the consuming end (since the code was public in GitHub anyway).

The Dockerfile is at the root of my repository, and steps prior build the code (in this case it's a C# application).

Continue Reading »

Graphing Sensor Data from a Raspberry Pi with Grafana

📅 22 May 2021, updated 30 December 2022 🔖 iot ⏲️ 4 minutes to read

For a weekend project I picked up an Enviro + Air Quality board with a particulate monitor. My goal was to start recording this data and feed it into Grafana for viewing.

The board itself, with the display showing temperature, humidity and pressure

The particulate graph as an example of the output

There's various other sensor data: temperature, pressure, humidity, light, gas and noise. I'm sampling the data every second and sending it to Graphite hosted in docker container on a Ubuntu VPS, which is consumed by Grafana.

Continue Reading »

Create Meshes from Height Maps using Blender

📅 16 May 2021 🔖 game-development ⏲️ 3 minutes to read

Here's an example mesh created by the technique I'll outline in this post, from a heightmap using Blender.

Height maps are textures which represent the height of geometry as a black and white image - black means "low" and white means "high".

Part of a pebble floor surface heightmap Š Epic Games

These heightmaps can be used in conjunction with a shading technique called tessellation, which subdivides geometry on the graphics card to increase the triangle density. A height map can then be applied to the surface to raise and lower the vertices of the generated triangles, and the result is a detailed surface.

Continue Reading »

Recording Camera Animations for UE4 with a Phone

📅 15 May 2021, updated 25 September 2023 🔖 game-development ⏲️ 2 minutes to read

Here's the final result in UE4, captured by me crawling around on the floor with my iPhone 8.

A camera sequence from one of my unannounced projects

I used the app VirtuCamera for iOS, which connects via WiFi to Blender or Maya and transmits the camera movements live for recording onto an animation track. It will also broadcast the viewport back to your device, meaning you can see your 3D environment on the phone's screen whilst recording the animation.

Continue Reading »

The Art of Mirror's Edge

📅 11 April 2021, updated 3 February 2024 🔖 game-art ⏲️ 3 minutes to read

One of my favourite games is Mirror's Edge (2008) because its art stands out above all else. I would not recommend it for its gameplay or story, but it has served as an inspiration for me in terms of environment art and level design.

This post takes a walk down memory lane into Mirror's Edge, with lossless 1440p screenshots taken straight from the Steam copy of the game (no processing). I also wanted an easy-accessible record of the level art for my own archives, since it's mostly a showcase of what great artists can achieve with standard rendering tech.

Cityscapes

Probably one of the most iconic features of the game are the broad cityscapes. These typically consist of rooftops with a lot of verticality provided by ledges and HVAC systems.

One thing that really sells these scenes for me is the scale of everything - the low-poly distant buildings blend right in with the detailed foreground. In addition light and shadow plays a big role, with buildings obscuring sunlight and objects on rooftops casting massive shadows.

Continue Reading »

Serving Static Websites Using Lambda@Edge

📅 20 March 2021, updated 4 April 2021 🔖 cloud-software ⏲️ 3 minutes to read

A typical approach to static websites on AWS involves a CloudFront distribution pointed at an S3 bucket.

One drawback to this approach is that in the event of a cache miss, CloudFront must retrieve the content from S3. If the bucket is in Ireland and the edge cache is in Australia, this will mean a round trip between those points.

In reality this latency isn't really a problem since it's only evident on a cache miss, but (more as as an experiment than anything else) I decided to write a proof of concept to serve static content entirely from the edge cache.

Continue Reading »

Thread Safe Random in C♯

📅 16 March 2021 🔖 c-sharp ⏲️ 1 minute to read

The C♯ class to generate random numbers, System.Random is not thread safe. If you share the same Random instance across threads things start to break.

Microsoft offer some solutions for this (for example locking), but if you just want to generate some random numbers and don't need them to follow a predictable stream, there are simpler (and safer) solutions.

Continue Reading »

Spotting Fake Indie Game Key Requests

📅 11 March 2021, updated 12 October 2021 🔖 game-development ⏲️ 2 minutes to read

If you're an indie game developer, you will very likely see key requests from bad actors trying to get game keys to sell. It's par for the course unfortunately, but it's increasingly difficult to distinguish genuine review requests from fake ones (especially when juggling a game release).

I recently released a game on Nintendo Switch after releasing it on Steam a year prior, and I noticed a big increase in how sophisticated the illegitimate requests were for the Switch release.

Continue Reading »

Jenkins Library for Unreal Engine 4

📅 13 February 2021 🔖 game-development ⏲️ 1 minute to read

For Estranged: The Departure, I released on Steam many hundreds of times, all at the push of a button using a tool called Jenkins.

At its core, Jenkins is a job scheduling system, where a job consists of some commands to run. You can define the job in the Jenkins interface or, as I prefer, in a Jenkinsfile which lives at the root of your source control repository.

I won't explain how to get a Jenkins server and attach a Windows build machine to it as there are better resources out there to explain that:

  • How to Install Jenkins on Ubuntu 20.04 | DigitalOcean
  • Jenkins Open Source Automation One-Click App | Marketplace | Linode
  • Step by step guide to set up master and agent machines on Windows

This post outlines the general-purpose Jenkins library I developed for Estranged. The library can be found here:

  • https://github.com/alanedwardes/Jenkins.UnrealEngine.Builder

Continue Reading »

Three Approaches to Readable Materials in First Person Games

📅 7 February 2021 🔖 game-development ⏲️ 4 minutes to read

In Estranged: Act I (2014) and Estranged: The Departure (2020) a lot of the storytelling was via newspapers and interactive screens, using different approaches in each game. In this post I will document those approaches and discuss the benefits and drawbacks of each.

  1. [Full-Screen Take Over]
  2. [First Person Camera]
  3. [Cut-Scene Camera]
  4. [Conclusion]

Continue Reading »

Cheap Synthetic Monitoring with AWS Lambda

📅 24 January 2021 🔖 cloud-software ⏲️ 1 minute to read

I have a few miscellaneous services which I host for various personal things; MediaWiki, Jenkins, Grafana, Rocket Chat, etc. These are usually hosted on VPS machines with Docker, which means a "one size fits all" monitoring solution is hard.

If I were operating as a business, I would just opt for an off-the-shelf synthetic monitoring solution with a support contract and call it done, but in a personal capacity I don't particularly want to pay.

I had a few criteria:

  • Cheap/free
  • Ability to write synthetic checks using HTTP requests (not a headless browser, that is a bit OTT)
  • Synthetic checks preferably in C#
  • Alerting via email for when the checks fail
  • Hosted redundantly & managed (e.g. AWS, not on a VPS)
  • Low/zero maintenance

Continue Reading »

Generating Mipmaps for Render Targets in UE4

📅 24 December 2020 🔖 game-development ⏲️ 1 minute to read

TLDR; use UTextureRenderTarget2D::UpdateResourceImmediate after updating your RT. Ensure you set bAutoGenerateMips to true on your render target instance.

When you create the RT, you pass it a UCanvasRenderTarget2D derived class; so you can blueprint this class and set bAutoGenerateMips on it in the editor, rather than doing this in code.

Continue Reading »

Routing DNS over HTTPS Using Raspberry Pi

📅 6 October 2020, updated 4 January 2023 🔖 iot ⏲️ 4 minutes to read

DNS is a protocol from the late 1980s, and today at its core DNS is still exactly the same. When it was conceived, there wasn't the same privacy focus as there is today, and one of the main drawbacks with the protocol is that queries and responses are not encrypted nor tamper proof when sent over the internet.

DNS over HTTPS is a newer take on the original DNS protocol, which routes queries over secure HTTP connections. While this is seeing some support (namely in Firefox and Windows 10), many devices on your network will continue to send DNS queries over UDP for years to come.

Continue Reading »

Tips for Building Games with Unreal Engine 4

📅 3 October 2020 🔖 game-development ⏲️ 19 minutes to read

I have released Estranged: The Departure on 3 platforms, Windows, macOS and Linux, and I will be bringing it to the Nintendo Switch and other platforms in the coming months.

This blog post covers my experiences as a solo developer, working with Unreal Engine since 2014 (without access to the UDN), and what to look out for if you are new to the engine.

I intend to keep this post updated (a living document).

Continue Reading »

Serving Localised Assets from S3 Using Lambda@Edge

📅 17 May 2020 🔖 cloud-software ⏲️ 3 minutes to read

Using Lambda@Edge, you can route users to different assets depending on their browser language, country or device (to name a few). In this post I am going to focus on the Accept-Language header, to detect the user's locale.

Demo

Example image served using this technique:

The text 'GB' for users visiting from the UK, 'US' from the US, 'CA' from Canada, 'EN' for other English speakers and 'GLOBAL' for anyone else.

Depending on your browser language, you will see:

  • "GB" for "English (United Kingdom)" (region-test.png.en-GB)
  • "US" for "English (United States)" (region-test.png.en-US)
  • "CA" for "English (Canada)" (region-test.png.en-CA)
  • "EN" for "English" (region-test.png.en)
  • "GLOBAL" if set to anything else (region-test.png)

Continue Reading »

Automating macOS Notarization for UE4

📅 23 November 2019 🔖 game-development ⏲️ 4 minutes to read

One of the trickier requirements introduced with macOS Catalina was the requirement that all applications must be notarized, for any kind of distribution.

Xcode does have tools to do this for you, but when you're building software that is bootstrapped by its own build process (such as a game), or you automate the build and deployment of your app, you need to use the custom workflow.

This post will discuss the entire notarization process for an Unreal Engine 4 game, but the process is the same for any app bundle.

Continue Reading »

ISO Country Code to Unicode Flag in C♯ and JavaScript

📅 22 July 2018, updated 15 March 2021 🔖 c-sharp ⏲️ 1 minute to read

The Unicode 6.0 spec defines Regional Indicator symbols, which includes a set of flags. Here are the founders of NATO, if your system supports the flag characters (Windows 10 doesn't yet):

🇧🇪 🇨🇦 🇩🇰 🇫🇷 🇮🇸 🇮🇹 🇱🇺 🇳🇱 🇳🇴 🇵🇹 🇬🇧 🇺🇸

To create a flag, take the country ISO code (for example GB), and offset it to the flags Unicode block.

Continue Reading »

Serverless Git LFS for Game Development

📅 6 January 2018, updated 1 August 2024 🔖 cloud-software ⏲️ 5 minutes to read

For Estranged, I needed a simple, cheap way of storing binary files. All solutions I tested required me to host a server, or me to pay someone to host a server. I wanted to avoid the flat fee for a constantly running server, and use something completely serverless with a pay-for-what-you-use model.

I settled on using a GitHub private git repository (free) and an LFS (large file storage) backend using Amazon Lambda, Amazon S3 and Amazon API Gateway. This write-up is a follow up to my older YouTube video covering the manual setup. This guide uses a template for a 1-click deployment of all resources mentioned in the video.

Continue Reading »

Adding Custom Map Checks in UE4

📅 3 January 2018 🔖 game-development ⏲️ 2 minutes to read

The map check function in UE4 offers level designers an insight into things that are going wrong inside their levels - for example a static mesh actor with no mesh.

Two errors in the Unreal Engine 4 map checker output, against two actors which have null static meshes.

You can also harness this power in your own project to run anything in the game world through a custom set of rules specific to your content.

For example, in Estranged, all surfaces in all levels need to have a physical material assigned to them.

This assignment has various functions, but most importantly dictates the footstep sound when the player walks on the material, and the bullet decal and particle effect to spawn when the surface is shot.

Continue Reading »

Building and Deploying a React App Using AWS Lambda

📅 24 December 2017 🔖 cloud-software ⏲️ 2 minutes to read

If you use React with a static frontend web app, the deployment steps may comprise of the following:

  • Run npm install
  • Run npm test
  • Run npm build
  • Deploy build folder to Amazon S3 & invalidate CDN cache

The first part of the build only requires node.js & npm, and the second part can be written in JavaScript too as a package.json script (I'll go into that more below).

Since node and npm are both available on Lambda, we can write a Lambda function invoked using a post-commit webhook (from GitHub or BitBucket), which builds and deploys the React application.

A few advantages to doing this:

  • You don't need any orchestration infrastructure (Jenkins) or cost overhead of BitBucket pipelines and similar solutions
  • Since the environment is completely managed, the only changes you may need to make are updating the Node.js runtime version as Amazon release newer versions
  • Access to the S3 bucket is controlled using IAM roles, no access key/secret

Continue Reading »

Git HTTP Username and Password in Environment Variables

📅 22 December 2017 🔖 cloud-software ⏲️ 1 minute to read

Sometimes when automating the use of the git command in scripts against GitHub or BitBucket, you may need to supply a username and password using environment variables.

One example is when using a Jenkinsfile groovy script in a Jenkins pipeline build, where you'd like to use credentials from the Jenkins credentials store.

Fortunately this is possible using a custom git credential helper, in this case a simple bash script (however you can use whatever language you like).

Credential Helper Shell Script

The shell script simply needs to echo a username and password back to git. The below script takes the $GIT_USERNAME and $GIT_PASSWORD environment variables, and prints them in a format git understands.

#!/bin/bash
echo username=$GIT_USERNAME
echo password=$GIT_PASSWORD

Save this as credential-helper.sh

Continue Reading »

Capturing and Uploading Screenshots in UE4

📅 20 December 2017 🔖 game-development ⏲️ 1 minute to read

For Estranged, I wanted the ability to capture the contents of the frame buffer, compress it, and upload it to a REST API. This allows users to attach screenshots to an in-game feedback window, to simplify the bug reporting process.

Unreal Engine 4 has APIs around all of those pieces, and in this post, I'll cover sticking them all together.

The full header and source file from the Estranged code is available as a GitHub gist. Below are the important excerpts.

Capturing a Screenshot

This is a two step process. First, you need to register a callback for when the screenshot is captured, then you request a screenshot:

void UEstScreenshotTaker::RequestScreenshot()
{
    GEngine->GameViewport->OnScreenshotCaptured().AddUObject(this, &UEstScreenshotTaker::AcceptScreenshot);
    FScreenshotRequest::RequestScreenshot(false); // False means don't include any UI
}

void UEstScreenshotTaker::AcceptScreenshot(int32 InSizeX, int32 InSizeY, const TArray<FColor>& InImageData)
{
    // See below
}

Continue Reading »

Using Capsule Shadows on Large Objects in UE4

📅 8 December 2017, updated 26 November 2022 🔖 game-development ⏲️ 1 minute to read

Capsule shadows are a great feature of Unreal Engine as they allow characters to cast soft shadows even with a game which relies on only static lighting.

The Last of Us 1 used this to great effect, as levels had a lot of areas which didn't receive dynamic lighting, and characters still felt grounded in the world using the capsule shadow technique (below).

Continue Reading »

Æ

© 2026 Alan Edwardes