Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/safrmo/boardgame-utils
Utilities for boardgame.io games
https://github.com/safrmo/boardgame-utils
boardgame boardgame-io
Last synced: 18 days ago
JSON representation
Utilities for boardgame.io games
- Host: GitHub
- URL: https://github.com/safrmo/boardgame-utils
- Owner: SaFrMo
- Created: 2019-11-21T13:18:11.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2023-05-07T08:28:46.000Z (over 1 year ago)
- Last Synced: 2024-10-11T05:11:05.327Z (about 1 month ago)
- Topics: boardgame, boardgame-io
- Language: JavaScript
- Size: 119 KB
- Stars: 4
- Watchers: 2
- Forks: 0
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
Utilities to make development in [boardgame.io](https://boardgame.io/) easier.
`npm install boardgame-utils`
You can then import any of the named modules below.
1. Cards
1. [buildDeck](#buildDeck)
1. [deck](#deck)
1. Grid
1. [buildGrid](#buildGrid)
1. [getCell](#getCell)
1. [getCoordsFromIndex](#getCoordsFromIndex)
1. [getIndexFromCoords](#getIndexFromCoords)
1. Vue
1. [Vue mixin](#mixin)
1. [Vue plugin](#plugin)
1. Misc
1. [Misc Notes](#misc-notes)## Cards
### buildDeck
`import { buildDeck } from 'boardgame-utils'`
Function to build a deck with options. Cards in the deck are objects in the same format as those in the [deck](#deck) function.
```
// defaults shown
buildDeck({
low: 1, // lowest rank, inclusive
high: 13, // highest rank, inclusive
suits: ['hearts', 'diamonds', 'clubs', 'spades'] // each suit will receive
})// build a deck of only red face cards
buildDeck({
low: 11,
high: 13,
suits: ['hearts', 'diamonds']
})
```### deck
`import { deck } from 'boardgame-utils'`
A standard 52-card, 4-suit deck. Contains ranks from 1-13 inclusive and suits `['hearts', 'diamonds', 'clubs', 'spades']`. Each card exists as an object with a `rank` and `suit` property - for example:
```
// ace of spades
{
rank: 1,
suit: 'spades'
}// king of hearts
{
rank: 13,
suit: 'hearts'
}
```It's left to the developer to handle face cards and aces high/low.
## Grid
### getCell
```js
import { grid } from 'boardgame-utils'
const { getCell } = gridgetCell({
x,
y,
board = [],
width = 10
})
```Get coordinates `(x, y)` from one-dimensional array `board`, given that board's `width`. For example, on a 3x3 board:
```
const board = [
0, 1, 2,
3, 4, 5,
6, 7, 8
]getCell(1, 1, board, 3) // = 4
getCell(2, 2, board, 3) // = 8
```### getCoordsFromIndex
```js
import { grid } from 'boardgame-utils'
const { getCoordsFromIndex } = gridgetCoordsFromIndex(index, (width = 10))
```Get `{ x, y }` coordinates from a given `index` on a board with the given `width`. For example, on a 3x3 board:
```
const board = [
0, 1, 2,
3, 4, 5,
6, 7, 8
]getCoordsFromIndex(4, 3) // = { x: 1, y: 1 }
getCoordsFromIndex(8, 3) // = { x: 2, y: 2 }
```### getIndexFromCoords
```js
import { grid } from 'boardgame-utils'
const { getIndexFromCoords } = gridgetIndexFromCoords({ x, y }, (width = 10))
```Get index from given index `{ x, y }` coordinates on a board with the given `width`. For example, on a 3x3 board:
```
const board = [
0, 1, 2,
3, 4, 5,
6, 7, 8
]getIndexFromCoords({x: 1, y: 1}, 3) // = 4
getIndexFromCoords({x: 2, y: 2}, 3) // = 8
```### taxicabDistance
```js
import { grid } from 'boardgame-utils'
const { taxicabDistance } = gridtaxicabDistance(a, b)
```Get [taxicab distance](https://en.wikipedia.org/wiki/Taxicab_geometry) from two vector2s For example:
```
const board = [
0, 1, 2,
3, 4, 5,
6, 7, 8
]taxicabDistance({x: 0, y: 0}, {x: 1, y: 1}) // = 2
```### taxicabDistanceFromIndices
```js
import { grid } from 'boardgame-utils'
const { taxicabDistanceFromIndices } = gridtaxicabDistanceFromIndices(a, b, (width = 10))
```Get [taxicab distance](https://en.wikipedia.org/wiki/Taxicab_geometry) from two indices given a board of width `width`. For example:
```
const board = [
0, 1, 2,
3, 4, 5,
6, 7, 8
]taxicabDistanceFromIndices(0, 4, 3) // = 4
taxicabDistanceFromIndices(1, 4, 3) // = 1
```## Vue
### mixin
`import { mixin } from 'boardgame-utils'`
A Vue mixin to handle setting up a boardgame.io client. This is suitable for small-scale games - larger ones should use the Vue [plugin](#plugin) below.
```
{
data: {
// the initialized boardgame.io client
client: null,// the options to pass to the client
options: null,// whether to automatically set up client on mounted().
setupClient: true
},
methods: {
// runs before the client is initialized
beforeClientInit(){},// initializes and saves the boardgame.io client
// run automatically if setupClient == true
initClient(){},// run after client is initialized and started
onClientReady(){}
},
computed: {
// current game state, null if not initialized
G,// current game ctx, null if not initialized
ctx
}
}
```An example setup in a Vue single-file component:
```html
Play {{ card }}
import { mixin as boardgameMixin } from 'boardgame-utils'
// options to pass to client (https://boardgame.io/documentation/#/api/Client?id=usage)
import options from './your-game-options'export default {
mixins: [boardgameMixin],
data() {
return {
// use options imported above
options: options,// example cards
cards: [1, 2, 3]
}
},
methods: {
beforeClientInit() {
// make sure we turn on the debug window
this.options.debug = true
},playCard(card) {
// plays 1, 2, or 3
// assumes we've defined a move called `playCard` in our game (https://boardgame.io/documentation/#/README?id=moves)
this.client.moves.playCard(card)
}
}
}```
### plugin
A Vue plugin to handle boardgame.io + Vue boilerplate.
To register:
```js
import Vue from 'vue'
import { plugin as boardgamePlugin } from 'boardgame-utils'
// client options per https://boardgame.io/documentation/#/api/Client
import options from 'your-game-options'
// the plugin registers a vuex module called `boardgame` to handle state manipulation, so you'll also need to have your Vuex store ready to use
import store from 'your-vuex-store'Vue.use(boardgamePlugin, {
// client options (required)
options: options,
// Vuex store (required)
store: store,
// whether or not to initialize the client immediately (optional, default: true)
initClient: true
})
```The plugin adds the following in Vuex:
- Store:
- `G` - G from boardgame.io state
- `ctx` - ctx from boardgame.io state
- Mutations:- `commit('UPDATE_STORE')` - Updates the store's G and ctx to match the state of the game. Used internally and does not take any arguments.
_Since boardgame.io uses [Proxied](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) G and ctx objects, `UPDATE_STORE` is called to update the store's deep clones of those G and ctx objects. This keeps boardgame.io's internal state self-contained and the Vuex store reactive._
- Actions:
- `dispatch('INIT_CLIENT', { options : {}})` - Creates a boardgame.io client with the given options. Called automatically unless `initClient` is set to `false`
- `dispatch('PLAY_MOVE', { move: 'moveName', options: {} })` - Runs a boardgame.io move with the (optional) given options.
- `dispatch('RESET_GAME')` - Reset the game to its starting state.
- `dispatch('RUN_CLIENT_METHOD', { method: 'methodName', options: {} })` - Runs a method on `client`. For example, to reset the game, you could dispatch `('RUN_CLIENT_METHOD', {method: 'reset'})` (although resetting using the `RESET_GAME` action is recommended).
- `dispatch('RUN_EVENT', { event: 'eventName', options: {} })` - Runs a boardgame.io [event](https://boardgame.io/documentation/#/events) with the (optional) given options.The plugin also adds the following global mixin:
```js
{
computed: {
G() {
// alias for this.$store.state.boardgame.G
},
ctx() {
// alias for this.$store.state.boardgame.ctx
}
}
}
```## Misc notes
### Recommended boardgame.io workflow
1. Prep `lib/game` dir
1. Files:
- `index.js` passes args to pass to `options`
- `phases.js` contains phases to pass to `index`, including 1 `start: true` phase
- `moves.js` contains all moves to pass to `phases`### Misc tips
- Don't modify G nested properties (like `G.enemies[0].hp - 10`) directly in Vue events - call moves that include an index so the framework can do so (like `` in Vue and `(index, amount) => G.enemies[index].hp -= amount` in the relevant phase).