https://github.com/manuelhenke/2048-webcomponent
2048 as a WebComponent
https://github.com/manuelhenke/2048-webcomponent
2048 2048-clone 2048-game css game lit-element lit-html typescript webcomponent webpack
Last synced: 6 months ago
JSON representation
2048 as a WebComponent
- Host: GitHub
- URL: https://github.com/manuelhenke/2048-webcomponent
- Owner: manuelhenke
- License: mit
- Created: 2024-01-18T20:54:20.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-04-12T00:10:25.000Z (about 2 years ago)
- Last Synced: 2025-09-13T17:36:06.254Z (10 months ago)
- Topics: 2048, 2048-clone, 2048-game, css, game, lit-element, lit-html, typescript, webcomponent, webpack
- Language: TypeScript
- Homepage: https://henkebyte.com/2048
- Size: 3.75 MB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 11
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# 2048-webcomponent
[](https://github.com/manuelhenke/2048-webcomponent/actions/workflows/ci.yml)
[](https://github.com/manuelhenke/2048-webcomponent/actions/workflows/codeql-analysis.yml)
[](./LICENSE)
[](https://www.npmjs.com/package/2048-webcomponent)
This is **2048** as a **WebComponent**. Once you integrate it as described further, the game just follows the standard rules. To make a move, just use the arrow keys or swipe.
## Getting Started
Install the package via `npm` or `yarn` and deliver the script to the user.
This can be done via `import`, `require` or just inserting a `script` tag.
```shell
npm i 2048-webcomponent
```
```shell
yarn add 2048-webcomponent
```
## Attributes
| Param | Type | Description | Default |
| -------------------------- | -------- | -------------------------------------------------------------------------------- | ------- |
| `columns` | `number` | Amount of columns of the board. | `4` |
| `rows` | `number` | Amount of rows of the board. | `4` |
| `swipe-distance-threshold` | `number` | Amount of pixels required to trigger a swipe. | `50` |
| `restart-selector` | `string` | If present, attaches a click event listener to the element to trigger a restart. | |
## Events
By default, each event contains the current game state in `event.detail.game`. To discourage cheating, no events should be logged in the browser console.
| Name | Type | Cancelable | Description | `detail` |
| ---------------- | --------------- | ------------------ | ----------------------- | ------------------------------------------------------------------------------------------------------------ |
| `2048:game-won` | `GameWonEvent` | :x: | User just won the game |
- `positions`: `Positions` current game state
| `2048:game-lost` | `GameLostEvent` | :x: | User just lost the game |
- `positions`: `Positions` current game state
| `2048:move` | `MoveEvent` | :white_check_mark: | User made a move |
- `positions`: `Positions` current game state
- `direction`: `Direction` direction of the move
| `2048:score` | `ScoreEvent` | :x: | Score has been updated |
- `positions`: `Positions` current game state
- `oldScore`: `number \| undefined` old score
- `delta`: `number \| undefined` difference between old and new score
- `newScore`: `number` current score
## Usage
### Basic usage
Just a basic 9x9 / 10 Mines 2048 game. Further examples can be **combined**.
```html
import '2048-webcomponent';
// Alternatives:
// import '2048-webcomponent/custom-element';
// import '2048-webcomponent/custom-element.min';
```
### Custom tag name
Define your own custom tag name
```html
import { Game } from '2048-webcomponent/game-2048';
// Alternative:
// import { Game } from '2048-webcomponent/game-2048.min';
window.customElements.define('custom-game-2048', Game);
```
### Provide a restart button
Provide a selector where a "click"-event will be attached to, to restart the game.
```html
Restart!
import '2048-webcomponent';
```
### Trigger Restart via JavaScript
Write custom logic to restart the game.
```html
Restart with Confirm!
import '2048-webcomponent';
window.addEventListener('DOMContentLoaded', () => {
const game = document.querySelector('#game');
document.querySelector('#restart-game-button-confirm').addEventListener('click', (event) => {
event.preventDefault();
if (window.confirm('Are you sure, that you want to restart the game?')) {
game.restartGame();
}
});
});
```
### Custom win/lose event listener
Attach an EventListener for the win/lose events.
```html
import '2048-webcomponent';
window.addEventListener('DOMContentLoaded', () => {
const game = document.querySelector('#game');
game.addEventListener('game-won', () => {
console.log('win');
});
game.addEventListener('game-lost', () => {
console.log('lose');
});
});
```
### Different initial game configurations
Of course you can provide different configurations for the game.
```html
import '2048-webcomponent';
```
## Example
Try it out at [CodePen](https://codepen.io/manuelhenke/pen/ExoPKLZ).

## TypeScript
The whole package is written in TypeScript and therefore provides a strongly typed system via the `core` export of the package:
```html
```
```typescript
// some-file.ts
import '2048-webcomponent/custom-element';
import { FieldInteractionEvent, FieldInteractionType } from '2048-webcomponent/core';
import type { Game } from '2048-webcomponent/core';
const game = document.querySelector('#game') as Game;
game.addEventListener('2048:field-interaction', (event: FieldInteractionEvent) => {
const { interaction } = event.detail;
switch (interaction.type) {
case FieldInteractionType.Unveiled:
console.log('Revealed field value:', interaction.value);
break;
case FieldInteractionType.FlagAction:
case FieldInteractionType.QuestionMarkAction:
console.log('Performed action:', interaction.action);
break;
}
});
```
## Engine
The engine can be used as a standalone library (`commonjs` and `esm`) via the `engine` export of the package. This enables the usage of the engine in every application (server- or client-side).
```javascript
import { Direction } from '2048-webcomponent/core';
import { Engine } from '2048-webcomponent/engine';
const engine = new Engine();
engine.createBoard(3, 3);
engine.move(Direction.Up);
if (engine.isGameOver) {
// Restarts the game with the initial configuration
engine.restart();
}
```
```javascript
const { Engine } = require('2048-webcomponent/engine');
const engine = new Engine();
// ...
```
## License
[MIT License](./LICENSE)