Backshot Tactics - A Multiplayer Game for js13kGames
Tags: javascript, css, gamedev, js13k
Published: 2019-10-03 16:52:30

---
title: Backshot Tactics - A Multiplayer Game for js13kGames
published: true
description: The journey about the js13kGames entry Backshot Tactics
tags: javascript, css, gamedev, js13k
cover_image: https://thepracticaldev.s3.amazonaws.com/i/0688q7yuoayttmw2m23o.png
---

### The Competition

This game was made for [js13kGames](https://js13kgames.com/), a JavaScript coding competition for HTML5 Game Developers. The fun part is the file size limit set to 13 kilobytes. Theme for 2019 was _back_.

### The Initial Idea

Since I enjoy play multiplayer and competitive games, the initial idea was to create a multiplayer online 1vs1 tactical game, inspired by [Teamfight Tactics](https://na.leagueoflegends.com/en/featured/events/teamfight-tactics) 

![tft](https://multiplayer.net-cdn.it/thumbs/images/2019/07/02/teamfight-tactics-02_jpg_1400x0_q85.jpg)

Even if the final result is a completely different game as you can see

![the initial splash screen](https://thepracticaldev.s3.amazonaws.com/i/ihmjoqqw8pqnpl8pz63n.png)

![the ingame view](https://thepracticaldev.s3.amazonaws.com/i/0688q7yuoayttmw2m23o.png)

### The Process

It was way too complex to do everything in 13kb and in the spare time I had, so I started removing features from the initial idea:
- Removed different characters, they are all equal (no different sprites / UI to create)
- The characters are placed on the field from the beginning (no drag and drop to implement)
- Removed armor, weapons and character classes (less code and complexity)


### The Prototype
With less features I could write a prototype in almost 6 hours, and I demonstrated it in Berlin at the [JS13kGames 2019 hackday](https://ebaytech.berlin/js13kgames-a-review-c10cbe9a39e3) alongside with other awesome devs

{% twitter 1163823307264679940 %}

## The Evolution
In the initial prototype two players had just to pick their characters at the beginning and then they were fighting automatically, I've found it boring and probably complex for players to understand what's going on.

So I've changed the gameplay: It became a turn based game, each turn the player chose the character to activate and he moves in a predefined direction then he attacks an opponent.

Other changes I made:
- The character always attack the nearest opponent
- The damage is calculated based on the characters distance
- if the character is hit from the __back side__ the damage is much higher
- "Characters" became "Ships" :)

Then I polished the UI, added mobile support, and added a ranking based on the [Elo rating system](https://en.wikipedia.org/wiki/Elo_rating_system) {% twitter 1166747182583767040 %}

Then the final rules became clear

- Pick phase: select your **4** ships on the grid.
- Play phase: When your turn come, you can **activate** a ship
  - It moves in the active direction (the highlighted arrow below the ship) by **4** cells (when it reach the border the ship wraps on the opposite side)
  - It shots the nearest opponent damaging him by **distance between them * 3** (bullets don't wrap the field)
  - If the opponent is hit on the **back side** the damage is **tripled**
- Kill all the enemy ships to win

### The 13kb limit

13kb (zipped) seems not much space, but it is a lot if you don't use assets and libraries (or just very small ones like those [listed here](https://js13kgames.github.io/resources/)) there is lot of room to write code. That's why for my game there was no images, only a font and an external library to make sound effects (jsfxr).

Here listed all the game files in the submitted version (minified, unzipped):
![List of all the game files](https://thepracticaldev.s3.amazonaws.com/i/rc9ihk0cuijmbhv3qwve.png)

### Competitive game
I wanted make a game _easy to play_ but _hard to master_, it's easy to start playing the game, you have just to click on ships, you can do it without thinking, you can also win plying like this. But it's hard to master, only with practice you can understand which ships are better to pick and which moves to do.

Also I wanted make a game without randomness during the game.
There is an initial random setup when the ships and directions are created and placed on the field before the game starts, but then the game is completely drove by player choices. (only in one case there is randomness involved: when two or more ships are at same distance, the one to shot is chosen randomly, but I plan to remove this behaviour and pick the ship with less HP instead)


### Technical details

The game was made for Desktop, Mobile and Server categories using the [js13kServer sandbox](https://github.com/js13kGames/js13kserver/), it works on Firefox, Chrome, Safari, Opera, and _probably_ on all modern browsers.

Web Sockets are used to send events between the two clients and the server who manage the Game logic.

The client is HTML, CSS and JS based, no canvas involved, I already used this approach in my previous game [Spacefield League](https://js13kgames.com/entries/spacefield-league).

Client side all the dimensions are relative to the viewport, so the interface scales well on all kind of screens, thanks to [viewport relative units](https://developer.mozilla.org/en-US/docs/Web/CSS/length#Viewport-percentage_lengths), [rem units](https://developer.mozilla.org/en-US/docs/Web/CSS/length#rem), percentages and CSS custom properties.
All animations are made via CSS transitions.

```css
.field {
  --field-size: 90vmin;
  height: var(--field-size);
  width: var(--field-size);
  /* --h and --w are set via js based on server game state */
  --cell-h: calc(var(--field-size) / var(--h));
  --cell-w: calc(var(--field-size) / var(--w));
  background-color: var(--black);
  background-size: var(--cell-w) var(--cell-h);
  /* ... */
}

.field > * {
  position: absolute;
  top: 0;
  left: 0;
  height: var(--cell-h);
  width: var(--cell-w);
  /* again --x and --y are set via js based on server game state, see the next js snippet */
  transform: translateX(calc(var(--cell-w) * var(--x))) translateY(calc(var(--cell-h) * var(--y))) scale(var(--scale, 1));
  /* ... */
}
```

```javascript
socket.on('new-pos', (e) => {
  let c = field.querySelector('#' + e.char.id);
  /* ... */
  c.style.setProperty('--x', positionX);
  c.style.setProperty('--y', positionY);
  /* ... */
});

```

Ships are DIVs clipped via `clip-path`
```css
.char .body {
  clip-path: polygon(0% 0%, 50% 0%, 100% 0%, 50% 100%);
}
```

There is a single Game class who manage the game state.
There are also some tests to be sure the game logic is working
```javascript
const game = new Game();

/* ... */

(async function play() {
  while(game.state === 'play') {

    // get the id of the current turn player
    let pid = game.players[game.turn % 2].id;

    // pick a random available player character
    let cid = pick(game.chars.filter(c => c.owner === pid && c.hp > 0)).id;

    // move that character
    await game.move(pid, cid);
  }

  // at a certain point the game should end
  assert.ok(game.state === 'game-over');
  
  console.log('Game test OK');
})();
```

### Future Plans
- Improve the game thanks to all the feedbacks from experts and other competition's participants
- Add a real login
- Add a turn timer
- Manage disconnections / re-connections
- Progressive web app and port on other platforms (like messenger instant games or mobile stores)
- Remove randomness on shots when more ships are at same distance
- Web monetisation

**Links**
[JS13KGames](https://js13kgames.com/)
[Entry page](https://js13kgames.com/entries/backshot-tactics)
[GitHub repository](https://github.com/salvan13/backshot-tactics)
[Play the game!](https://backshot-tactics.herokuapp.com/)

{% twitter 1171735059084337154 %}

### Results

The result was so good and unexpected

Overall: 19th place
Mobile: 5th place
Server: 1st place

{% twitter 1180479097455157248 %}