Making a Speedrun Timer: Prologue
Kev the Dev
Posted on March 27, 2023
Introduction π
Since 2015, I've been a part of the speedrunning community by running a game called Banjo Kazooie on the Nintendo 64. A common tool used amongst the community is a speedrun timer known as LiveSplit. While this timer is already a phenomenal tool, I figured I would make my own as part of a fun passion project and write a dev blog series about it!
Requirements:
In terms of requirements for this project, I'll say there won't be many initially. Since it's purely a passion project, I'll keep it simple to start with and add new functionality over time as I see fit.
To start I think we'll just need:
A Stopwatch β±οΈ
A accurate stopwatch timer with hours, minutes, seconds, and milliseconds displayed back to the user. Special care is needed around accuracy, as we want to make sure the correct times can be reported when submitting a time for a speedrun.
Event Triggers β‘
We'll need event triggers for "start", "pause", "reset", "split", and "undo split". These events will be triggered by button press or key press. It's likely that we'll need to add more events but this will get us started.
Split Tracking π
We need a way to keep track of splits and appropriate split data like the name, best time for that split, split history, etc. After all, what good would this timer be without splits?
Import/Export Functionality πΎ
Not only do we need to track our splits, but we need to be able to import and export split data to keep the application portable and accessible on multiple platforms and multiple users.
A Customizable Interface π¨π§βπ¨
One of the biggest complaints I have about LiveSplit is its lack of interface customization. I shouldn't say lack because it's actually pretty customizable, but I feel as though the interface leaves a lot to be desired. It feels like EVERY timer looks the same barring different color schemes, and what you can do with the space you're given feels very limited. If you attempt to use horizontal splits it just becomes a nightmare. Therefore, I want to see if we can create a highly customizable and sleek user interface for displaying speedrun data.
A Creative Mindset! π§ π‘
A creative mindset to have the ability to add unique functionality whenever and idea pops in the brain. This is where YOU, the community, can also contribute! Feel free to message me or comment with any features you'd like to see on a speedrun timer!
Tech Stack π§βπ»
I debated for some time on whether or not I wanted to make this a command line app, a desktop GUI app, or a web app. Ultimately I decided to go with a PWA built in Vue due to the accessibility and portability of the browser. Building an app with Vue will allow us to make our interface highly customizable and utilize Vue's amazing developer experience to build our application in an efficient manner πͺ.
At this point in the project, I'm not sure if we'll end up needing a backend (as that insinuates costπ²) but if we do, we'll cross that bridge when we get to it. Potential technologies we could use on the backend include GoLang, Python, or C# (.NET) with probably some sort of serverless database. These are just backend technologies I'm familiar with and are quick to get up and running.
Project Setup π§
Vite
To setup our new Vue + PWA application we'll need to start by creating our project directory structure. To do this we will be using vite to create our initial application and take out things we don't need and add in the components needed to make our application PWA compliant.
First we'll run: npm create vite@latest
Vue
After that we'll fill out the necessary prompts to get our vanilla JavaScript Vue 3 application up and running and remove all components (only the HelloWorld component should exist) and assets (icons, .svg, .png, etc).
PWA Compliance
Next we need to make our application PWA compliant so we can download it as an application from the browser. To make this easy on ourselves we will be using an npm package called vite-plugin-pwa which will take care of a lot of the setup.
Install with: npm i vite-plugin-pwa -D
However, that won't be all. We need to modify our project's vite.config.js
and index.html
files with the appropriate information and references to icons. I won't go into too much detail on how or why to do this but you can read the documentation here on what you need to get started.
Here's what I've written in my files:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="favicon" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Speedrun Timer</title>
<meta name="description" content="A highly customizable speedrun timer">
<link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180">
<link rel="mask-icon" href="favicon" color="#FFFFFF">
<meta name="theme-color" content="#ffffff">
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
vite.config.js
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import { VitePWA } from "vite-plugin-pwa";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
VitePWA({
registerType: "autoUpdate",
devOptions: {
enabled: true,
},
manifest: {
name: 'Speedrun Timer',
short_name: 'STA',
description: 'A highly customizable speedrun timer app',
theme_color: '#ffffff',
icons: [
{
src: 'logo-192x192.png',
sizes: '192x192',
type: 'image/png'
},
{
src: 'logo-512x512.png',
sizes: '512x512',
type: 'image/png'
}
]
}
}),
],
});
Once that's done we should be good to get started on our project! In the next chapter of this series we'll begin building out this application and start coding.
Follow Along π€³
I'm completely new to writing dev blogs, so take it easy one me! I've wanted to write a dev blog for a long time so I'm excited to see how it goes!
If you'd like to follow along, be sure give me a follow on here, my socials, and the GitHub Repository for this project!
Posted on March 27, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.