Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 16 additions & 12 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# Installs dependencies, type-checks, runs the unit tests and builds the app
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs

name: Node.js CI

on:
push:
branches: [ "main" ]
branches: ["main"]
pull_request:
branches: [ "main" ]
branches: ["main"]

jobs:
build:

runs-on: ubuntu-latest

strategy:
Expand All @@ -20,11 +19,16 @@ jobs:
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/

steps:
- uses: actions/checkout@v6
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm run test
- uses: actions/checkout@v6
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- name: Type check
run: npm run type-check
- name: Unit tests
run: npm run test
- name: Build
run: npm run build-only
5 changes: 3 additions & 2 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"tabWidth": 2,
"useTabs": false,
"semi" :false,
"singleQuote": true
"semi": false,
"singleQuote": true,
"printWidth": 100
}
134 changes: 109 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,129 @@
# GameLifeCounter

Is a basic life counter for games,
it can handle two persons at the same time.

[App](https://albertlast.github.io/GameLifeCounter/)

Keeping holding the - or + area to jump 10 steps

You can use the setting menu to switch to fullscreen.
When android with chromebase browser is used,
you can also disable the screensaver (enable wakelock).

Support pwa -> can be installed locally on supported devices.

![App](doc/App.png)

## Requirments

Only a webserver to delifer the js files is needed,
the website runs full on client side.

## Project Setup
A life counter for board and card games that runs entirely in the browser.

[Open the app](https://albertlast.github.io/GameLifeCounter/)

<img src="doc/App.webp" alt="Two player table in the Pulse theme" width="320">

## Features

- **2 to 6 players.** Picking the player count asks how the table is seated,
and the table behind the chooser updates as you pick:
- _Facing_ (default) puts players along the top and bottom edge facing each
other, the way the two player table works. Life totals and the -/+ buttons
read horizontally for everybody.
- _Sides_ turns the same table a quarter turn for players sitting along the
left and right edge.
- _Same side_ stacks every seat upright, for when nobody sits opposite.

Each seat is rotated towards the edge its player sits at, so nobody reads
their life total upside down.

- **Tap and hold.** A tap changes the life total by one step, holding a button
keeps applying the big step until you let go. Recent changes are summed up
and shown above the total ("-7") before fading away.
- **Game presets.** Standard (20), Commander (40 with poison), Energy (poison
and energy counters), Duel 8000 (steps of 50) and a neutral board-game
counter. The starting life total can be adjusted freely.
- **Two themes.** _Pulse_ keeps the original edge-to-edge colour blocks with
oversized numerals; _Arena_ puts floating player cards on a dark stage.
- **Player identity.** Each seat has its own name and colour.
- **Table tools.** Dice (coin, d4–d100), a match timer and a random
first-player picker, all reachable from the hub in the middle of the table.
- **Installable and offline.** The app is a PWA and keeps its state in local
storage, including the life totals and colours of the previous version.
- **Screen options.** Fullscreen and, where the browser supports it, a wake
lock that stops the screen from sleeping mid-game.

## Screenshots

<table>
<tr>
<td width="50%" valign="top">
<img src="doc/players-six.webp" alt="Six player table with names, poison counters and the match timer" width="100%">
<sub><b>Six players, Commander preset.</b> Named seats, poison counters
and the match timer running along the top.</sub>
</td>
<td width="50%" valign="top">
<img src="doc/theme-arena.webp" alt="Four player table in the Arena theme" width="100%">
<sub><b>Arena theme.</b> Floating player cards on a dark stage, here with
poison and energy counters.</sub>
</td>
</tr>
<tr>
<td width="50%" valign="top">
<img src="doc/layout-chooser.webp" alt="Table layout chooser with the table visible behind it" width="100%">
<sub><b>Layout chooser.</b> Opens right after the player count; each
option is drawn for your table and the table behind updates as you pick.</sub>
</td>
<td width="50%" valign="top">
<img src="doc/layout-sides.webp" alt="Four player table with the sides layout" width="100%">
<sub><b>Sides layout.</b> The same table turned a quarter turn for
players sitting along the left and right edge.</sub>
</td>
</tr>
</table>

<table>
<tr>
<td width="33%" valign="top">
<img src="doc/settings.webp" alt="Settings sheet" width="100%">
<sub><b>Settings.</b> Players, preset, starting life, theme, names and
colours.</sub>
</td>
<td width="33%" valign="top">
<img src="doc/dice.webp" alt="Dice sheet showing a d20 roll" width="100%">
<sub><b>Dice.</b> Coin and d4 to d100, with the recent rolls kept.</sub>
</td>
<td width="33%" valign="top">
<img src="doc/starter.webp" alt="Random first player announcement" width="100%">
<sub><b>Random first player.</b> Announced in that player's colour; the
crown stays on their seat.</sub>
</td>
</tr>
</table>

## Requirements

Only a webserver to deliver the static files; the app runs fully client side.

## Project setup

```sh
npm install
```

### Compile and Hot-Reload for Development
### Compile and hot-reload for development

```sh
npm run dev
```

### Type-Check, Compile and Minify for Production
### Type-check, compile and minify for production

```sh
npm run build
```

### Run Unit Tests with [Vitest](https://vitest.dev/)
### Run the unit tests with [Vitest](https://vitest.dev/)

```sh
npm run test:unit
npm run test # single run
npm run test:unit # watch mode
npm run test:coverage # with coverage report
```

## Project structure

| Path | Contents |
| ------------------------------ | --------------------------------------------------------------- |
| `src/game/` | Game state, presets, seat layouts and persistence |
| `src/theme/` | Theme catalogue and the binding to `<html data-theme>` |
| `src/composables/` | Hold-to-repeat, pending delta, dice, timer, fullscreen/wakelock |
| `src/components/` | Vue components |
| `src/assets/styles/tokens.css` | Design tokens; a theme only overrides this block |

Adding a theme means adding an entry to `src/theme/themes.ts` and a
`[data-theme='…']` token block — components read colours and sizes from
variables only.
Binary file removed doc/App.png
Binary file not shown.
Binary file added doc/App.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/dice.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/layout-chooser.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/layout-sides.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/players-six.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/settings.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/starter.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/theme-arena.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions env.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/// <reference types="vite/client" />
/// <reference types="vite-plugin-pwa/vue" />
27 changes: 21 additions & 6 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<meta name="theme-color" content="#111014" />
<meta
name="description"
content="Life counter for board and card games — 2 to 6 players, presets, dice and a match timer. Works offline."
/>
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta property="og:title" content="Game Life Counter for board games" />
<meta property="og:url" content="https://albertlast.github.io/GameLifeCounter/" />
<meta property="og:description" content="States of you life points" />
<meta property="og:image" content="https://albertlast.github.io/GameLifeCounter/icons/heart.png" />
<meta
property="og:description"
content="Track life totals for 2 to 6 players, with presets, counters, dice and a match timer."
/>
<meta
property="og:image"
content="https://albertlast.github.io/GameLifeCounter/icons/heart.png"
/>
<meta property="og:image:width" content="512" />
<meta property="og:image:height" content="512" />
<meta property="og:type" content="website" />
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="./favicon.ico" />
<link rel="apple-touch-icon" href="./icons/heart.png" />
<title>Game Life Counter</title>
</head>
<body>
Expand Down
40 changes: 19 additions & 21 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 9 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
{
"name": "gamelifecounter",
"version": "0.0.0",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "run-p type-check build-only",
"preview": "vite preview",
"test:unit": "vitest --environment jsdom --root src/",
"build-only": "vite build",
"type-check": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false",
"test": "npm run build-only"
"preview": "vite preview",
"type-check": "vue-tsc --build",
"test": "vitest run",
"test:unit": "vitest",
"test:coverage": "vitest run --coverage",
"format": "prettier --write \"{src,.}/**/*.{ts,vue,css,json,html}\""
},
"dependencies": {
"@radial-color-picker/vue-color-picker": "^6.0.0",
"vue": "^3.5.27"
},
"devDependencies": {
Expand All @@ -27,11 +28,12 @@
"jsdom": "^27.4.0",
"npm-run-all": "^4.1.5",
"postcss": "^8.5.3",
"prettier": "^3.4.2",
"tailwindcss": "^4.1.10",
"typescript": "^5.8.2",
"vite": "^7.3.1",
"vite-plugin-pwa": "^1.1.0",
"vitest": "^4.0.16",
"vue-tsc": "^2.2.10"
}
}
}
Loading