Skip to content

Commit

Permalink
feat(game): mouse editable board
Browse files Browse the repository at this point in the history
  • Loading branch information
erenard committed Mar 4, 2024
1 parent fa6e61f commit 4d0a946
Show file tree
Hide file tree
Showing 12 changed files with 92 additions and 5 deletions.
9 changes: 9 additions & 0 deletions app/app.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,13 @@ describe('AppVue', () => {
expect(game.step).toHaveBeenCalledTimes(1)
})
})

describe('moving the mouse with left button pressed in the viewport', () => {
beforeEach(async () => {
await wrapper.find('div').trigger('mousemove', { x: 0, y: 0, buttons: 1 })
})
test('should call game.mouseDown', () => {
expect(game.addCellAtPixel).toHaveBeenCalledTimes(1)
})
})
})
8 changes: 7 additions & 1 deletion app/app.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<template>
<Layout>
<template #default>
<div ref="viewport" />
<div
ref="viewport"
@mousemove="handleMouseMove"
/>
</template>
<template #ui>
<div class="box">
Expand Down Expand Up @@ -80,6 +83,9 @@ export default {
this.switchRunning()
},
methods: {
handleMouseMove (mouseEvent) {
if (mouseEvent.buttons === 1) game.addCellAtPixel(mouseEvent.offsetX, mouseEvent.offsetY)
},
stepAnimate () {
game.step()
},
Expand Down
1 change: 1 addition & 0 deletions app/game/__mocks__/game.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Board from '../board.js'

export default function Game () {
const obj = {
addCellAtPixel: jest.fn(),
step: jest.fn(),
setViewportMock: jest.fn(),
getBoardMock: jest.fn(),
Expand Down
5 changes: 5 additions & 0 deletions app/game/__tests__/board.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,9 @@ describe('Board', () => {
expect(new Board().pixelHeight).toEqual(800)
})
})
describe('pixelToCellCoordinates', () => {
test('should convert pixel coordinates to cell coordinates', () => {
expect(new Board().pixelToCellCoordinates(100, 100)).toEqual([50, 50])
})
})
})
11 changes: 11 additions & 0 deletions app/game/__tests__/game.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,15 @@ describe('Game', () => {
expect(game._animation.mainLoop).toHaveBeenCalledTimes(1)
})
})
describe('addCellAtPixel method', () => {
beforeEach(() => {
game._grid.resurectCell = jest.fn()
game._renderer = { render: jest.fn() }
game.addCellAtPixel({ x: 0, y: 0 })
})
test('should call grid.addCellAtPixel', () => {
expect(game._grid.resurectCell).toHaveBeenCalledTimes(1)
expect(game._renderer.render).toHaveBeenCalledTimes(1)
})
})
})
11 changes: 10 additions & 1 deletion app/game/__tests__/grid-utils.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, beforeEach, test, expect } from '@jest/globals'

import { random, clear, indexToXy, xyToIndex } from '../grid-utils.js'
import { random, clear, indexToXy, xyToIndex, resurect } from '../grid-utils.js'

import {
getState,
Expand Down Expand Up @@ -59,4 +59,13 @@ describe('Grid utils', () => {
expect(indexToXy(gridLength, gridSide, 0 + gridSide * 3)).toEqual({ x: 0, y: 3 })
})
})
describe('resurectCell ()', () => {
test('should resurect cell', () => {
cells[0] = setState(cells[0], 0)
cells[1] = setState(cells[1], 0)
resurect(cells, 0)
expect(getState(cells[0])).toEqual(1)
expect(getState(cells[1])).toEqual(0)
})
})
})
11 changes: 10 additions & 1 deletion app/game/__tests__/grid.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, beforeEach, afterEach, test, expect, jest } from '@jest/globals'
import { random, clear, indexToXy, xyToIndex } from '../grid-utils.js'
import { random, clear, indexToXy, xyToIndex, resurect } from '../grid-utils.js'

import Grid from '../grid'
import Rules from '../rules'
Expand Down Expand Up @@ -58,4 +58,13 @@ describe.each([
expect(xyToIndex).toBeCalledWith(grid.length, grid.sizeX, 2, 2)
})
})
describe('resurectCell ()', () => {
test('should call resurect with instance parameters', () => {
const grid = new GridImplementation({ gridWidth: gridSide, gridHeight: gridSide }, new Rules())
xyToIndex.mockReturnValue(4)
grid.resurectCell(2, 2)
expect(xyToIndex).toBeCalledWith(grid.length, grid.sizeX, 2, 2)
expect(resurect).toBeCalledWith(grid.cells, 4)
})
})
})
14 changes: 14 additions & 0 deletions app/game/board.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,18 @@ export default class Board {
get pixelHeight () {
return this.gridHeight * this.cellRadius
}

/**
* Convert pixel coordinates to cell coordinates.
*
* @param {number} x - Mouse x coordinate in pixels, relative to the board.
* @param {number} y - Mouse y coordinate in pixels, relative to the board.
* @returns {[number, number]} - Cell coordinates.
*/
pixelToCellCoordinates (x, y) {
return [
Math.floor(x / this.cellRadius),
Math.floor(y / this.cellRadius)
]
}
}
16 changes: 16 additions & 0 deletions app/game/game.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,22 @@ export default class Game {
this._animation.mainLoop()
}

/**
* Add a cell to the grid.
*
* @param {number} x - Mouse x coordinate in pixels, relative to the viewport element.
* @param {number} y - Mouse y coordinate in pixels, relative to the viewport element.
*/
addCellAtPixel (x, y) {
this._grid.resurectCell(...this._board.pixelToCellCoordinates(x, y))
this._renderer.render()
}

/**
* Set the viewport.
*
* @param {Element} viewport - Viewport DOM element.
*/
// eslint-disable-next-line accessor-pairs
set viewport (viewport) {
this._viewport = viewport
Expand Down
4 changes: 4 additions & 0 deletions app/game/grid-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,7 @@ export function indexToXy (length, sizeX, i) {
export function xyToIndex (length, sizeX, x, y) {
return (sizeX * y + x) % length
}

export function resurect (cells, i) {
cells[i] = setState(cells[i], 1)
}
1 change: 0 additions & 1 deletion app/game/grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ const defaultName = typeof SharedArrayBuffer !== 'undefined' ? 'one-worker' : 'n
const Grid = {

load: async function (name = defaultName) {
console.log(`Load ${name} grid.`)
implementation = await import(`./grids/grid-${name}`)
},

Expand Down
6 changes: 5 additions & 1 deletion app/game/grids/abstract-grid.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import update from '../grid-updater.js'
import { random, clear, indexToXy, xyToIndex } from '../grid-utils.js'
import { random, clear, indexToXy, xyToIndex, resurect } from '../grid-utils.js'

/**
* Implements the game algorithm.
Expand Down Expand Up @@ -49,4 +49,8 @@ export default class {
xyToIndex (x, y) {
return xyToIndex(this.length, this.sizeX, x, y)
}

resurectCell (x, y) {
resurect(this.cells, this.xyToIndex(x, y))
}
}

0 comments on commit 4d0a946

Please sign in to comment.