Link
https://jacob-aberdevine.itch.io/dream-express
About
This game was a personal project that I designed and programmed entirely by myself. After three weeks of work, I had a clear idea, a working prototype, and a Game Design Document (GDD). At that point, I asked my friends from our game development science club if they would be interested in helping with the game’s assets.
In the end, I gathered a team of four, who did an incredible job—thanks to them, the game became something truly worth being proud of!
Quality Assurance
In the final stages of development, I led a game testing phase with 12 people, introducing a structured feedback roadmap.
Over two weeks, we worked in a continuous feedback loop: testers reported every detail on our forum, which I then organized into a document. For each issue, I wrote two summaries:
- A description of the issue based on reports.
- A possible solution, sometimes suggested by testers.
Once I implemented a fix, I added a third summary:
- How the issue was resolved.
After addressing all reported issues for a version, we marked it as the next version and repeated the process.
Gathering Data and Analysis
To address game balance, I implemented a data collection system that records key statistics after each run, including:
- Time taken to clear each room
- Chosen upgrades
- Whether the run was successful
- The game version
The code formats this data as a dictionary and sends a request to a Google Form I created.
var urlform = "the google forms url"
var headers = ["Content-Type: application/x-www-form-urlencoded"]
var http = HTTPClient.new()
func send_data():
var data = {
"entry.1595604209" : "1.7.0",
"entry.2034915935" : Global.room_times,
"entry.1548282031" : pickrate,
"entry.643402334" : winrate
}
var pool_headers = PoolStringArray(headers)
data = http.query_string_from_dict(data)
var result = $HTTPRequest.request(urlform, pool_headers, false, HTTPClient.METHOD_POST, data)
After submission, a function verifies and prints whether the request was successful.
func _on_HTTPRequest_request_completed(_result, response_code, _headers, _body):
print("Response code:", response_code)
if response_code == 200:
print("Form submission successful.")
else:
print("Failed to submit form.")
I then connected Google Forms to Google Sheets, allowing for easy organization and analysis of the data.
Balancing Approach
I introduced a Power metric for each enemy type, representing their relative strength based on health, damage, and average defeat time. To model power scaling, I experimented with graphs and derived the formula:
$$P=2+n^{0.7}$$where \(n\) is the room index and \(P\) is the estimated total Power for that room.
Using this formula, I designed each room with a consistent difficulty curve. Once sufficient data was collected, I calculated average win rates and completion times per room, allowing me to fine-tune enemy distribution.
Each room has two variations, designed to feature different enemies and layouts while maintaining similar difficulty. To analyze this, I organized the data visually:
- Each room is assigned a distinct color, with two columns representing its variations.
- Each row corresponds to a submitted run, and the cells display the time taken to clear each room.
- Completed rooms are slightly darkened, making it easier to spot where most runs tend to end.