Skip to content

Commit

Permalink
Added UI state and some design
Browse files Browse the repository at this point in the history
  • Loading branch information
ivancea committed Sep 17, 2024
1 parent 1756411 commit a9f1297
Show file tree
Hide file tree
Showing 10 changed files with 411 additions and 166 deletions.
8 changes: 7 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
# How to contribute

## Before contributing, keep in mind:

- This app is still in **early development stage**
- Somewhat big changes may be done without notice, as the code grows and needs to be reorganized
- Features may be added in no specific order
- For those reasons, the existing issues are not organized in time, and may have hidden dependencies with other issues

## Working on an issue

To avoid conflicts in this stage, and to avoid frustration or wasting time:

- Comment on the issues you want to work on, and wait for confirmation. Ask for specific details, as issues are not explained in depth.
<br/>It _may or may not_ be planned to be done yet, and it _may_ be just an idea without real product definition
- Work on it and submit a PR. If there are visual changes, consider adding a screenshot
Expand All @@ -19,15 +22,18 @@ To avoid conflicts in this stage, and to avoid frustration or wasting time:
> <br/><br/> 🕒 We are all human, and we all make mistakes. This is just a reminder to avoid opening low-effort PRs that waste collaborators time.
### Understanding issues: Labels

There are some sets of labels you will see in the issues, usually one of each:

- `:<component>`: Labels that define which components are mainly related with the issue
- `!<work-status>`: Labels that define whether the issue can be assigned, if it's not ready yet, if it's a private issue, etc.
<br/>If an issue lacks this label, use your best judgement. It may have been forgotten, or it may be too convoluted to define.
- `<other>`: Labels that define the kind of issue (bug, enhancement...). There may be other unrelated topics too

## How to report a bug

The short answer is: You don't! Unless it's some kind of uncaught exception you found in there.
In which case feel free to open an issue, and tag it with the "bug" label, with the full stack trace, an explanation of what happen and, if possible, a reproduction method.
In which case feel free to open an issue, and tag it with the "bug" label, with the full stack trace, an explanation of what happen and, if possible, a reproduction method.

As the project is still in an early stage, there will be multiple bugs. Some will have an issue open, and some won't.
Unfortunately, the project evolves at a relatively slow pace, and some weird interactions may be _allowed_.
73 changes: 40 additions & 33 deletions client/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,46 @@
<!-- Webpack automatic injection of tags enabled -->
</head>
<body>
<div
id="room-selection-form"
style="display: flex; flex-direction: row; gap: 1em"
>
<span>
<label for="username">Username</label>
<input
id="username"
name="username"
type="text"
placeholder="Username"
/>
</span>
<span>
<label for="input-mode">Input mode</label>
<select id="input-mode" name="input-mode"></select>
</span>
<span>
<label for="weapon">Weapon</label>
<select id="weapon" name="weapon"></select>
</span>
<span>
<label for="bots">Bots</label>
<input id="bots" name="bots" type="checkbox" checked />
</span>
<span>
<label for="debug-mode">Debug</label>
<input id="debug-mode" name="debug-mode" type="checkbox" />
</span>
<span>
<button id="room-selection-form-submit" type="button">Join room</button>
</span>
</div>
<noscript>Hammerfight.io requires JavaScript to be enabled.</noscript>

<template id="form-template">
<div id="room-selection-form">
<h1>Hammerfight.io</h1>
<div class="form-fields">
<span>
<label for="username">Username</label>
<input
id="username"
name="username"
type="text"
placeholder="Username"
/>
</span>
<span>
<label for="input-mode">Input mode</label>
<select id="input-mode" name="input-mode"></select>
</span>
<span>
<label for="weapon">Weapon</label>
<select id="weapon" name="weapon"></select>
</span>
<span>
<label for="bots">Bots</label>
<input id="bots" name="bots" type="checkbox" checked />
</span>
<span>
<label for="debug-mode">Debug</label>
<input id="debug-mode" name="debug-mode" type="checkbox" />
</span>
<span class="submit">
<button id="room-selection-form-submit" type="button">
Join room
</button>
</span>
</div>
</div>
</template>

<div id="game"></div>
<div
style="
Expand Down
53 changes: 5 additions & 48 deletions client/index.ts
Original file line number Diff line number Diff line change
@@ -1,54 +1,11 @@
import { capitalize } from "lodash-es";
import { WEAPON_TYPES, WeaponType } from "../common/types/weapon";
import {
availableInputHandlers,
InputHandlerId,
} from "./input/input-handler-catalog";
import { joinRoom } from "./socket-io";
import "./styles/index.scss";
import { runStateMachine } from "./ui-manager/ui-manager";
import { FormUiState } from "./ui-manager/ui-state.form";

function main() {
// Get controls
const usernameInput = document.getElementById("username") as HTMLInputElement;
const inputModeInput = document.getElementById(
"input-mode",
) as HTMLSelectElement;
const weaponInput = document.getElementById("weapon") as HTMLSelectElement;
const botsInput = document.getElementById("bots") as HTMLInputElement;
const debugModeInput = document.getElementById(
"debug-mode",
) as HTMLInputElement;

// Initialize controls
inputModeInput.innerHTML = "";
for (const inputHandler of availableInputHandlers) {
const option = document.createElement("option");
option.value = inputHandler.id;
option.text = inputHandler.getName();
inputModeInput.add(option);
}
weaponInput.innerHTML = "";
for (const weaponType of WEAPON_TYPES) {
const option = document.createElement("option");
option.value = weaponType;
option.text = capitalize(weaponType);
weaponInput.add(option);
}

// On start
document
.getElementById("room-selection-form-submit")
?.addEventListener("click", (event) => {
event.preventDefault();

const username = usernameInput.value;
const inputHandlerId = inputModeInput.value as InputHandlerId;
const weapon = weaponInput.value as WeaponType;
const bots = botsInput.checked;
const debugMode = debugModeInput.checked;

joinRoom(username, inputHandlerId, weapon, bots, debugMode);
});
runStateMachine(new FormUiState()).catch((error: unknown) => {
console.error("Error running UI state machine", error);
});
}

window.addEventListener("DOMContentLoaded", main);
84 changes: 0 additions & 84 deletions client/socket-io.ts

This file was deleted.

3 changes: 3 additions & 0 deletions client/styles/index.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@import "ui-state.form";

body {
width: 100vw;
height: 100vh;
Expand All @@ -12,6 +14,7 @@ body {
flex-grow: 1;
min-height: 0;
justify-content: center;
align-items: center;
user-select: none;

& > svg {
Expand Down
34 changes: 34 additions & 0 deletions client/styles/ui-state.form.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#room-selection-form {
display: flex;
flex-direction: column;
gap: 16px;
height: fit-content;

padding: 40px;
border: 1px solid #225c09;
border-radius: 5px;
background-color: #48be11;
box-shadow: 0 0 10px rgba(77, 117, 39, 0.1);

& > h1 {
margin: 0;
margin-bottom: 16px;
}

& > .form-fields {
display: flex;
flex-direction: column;
gap: 8px;

& > span {
display: flex;
flex-direction: row;
align-items: center;
gap: 8px;
}

& > .submit {
justify-content: center;
}
}
}
24 changes: 24 additions & 0 deletions client/ui-manager/ui-manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { UiState } from "./ui-state";

/**
* Entry point of the UI state machine.
*
* This function will run the UI, which works as a simple state machine,
* going from one state to another, where each state represents a different screen of the UI.
*/
export async function runStateMachine(initialState: UiState) {
let currentState = initialState;

// Infinite loop with a safe limit of iterations
for (let i = 0; i < 1_000_000; i++) {
const newState = await currentState.enter();

if (newState !== currentState) {
await currentState.exit();
}

currentState = newState;
}

console.error("UI state machine exceeded maximum number of iterations");
}
Loading

0 comments on commit a9f1297

Please sign in to comment.