Skip to content

Commit b013693

Browse files
authored
Merge pull request #50 from gibsonsmog/feature/beforeCollide
add onCollideStart and onEnterStart
2 parents 1b987da + b4643d3 commit b013693

6 files changed

Lines changed: 75 additions & 5 deletions

File tree

apps/examples/src/hello-world/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ const game = createGame({
3030
...66...
3131
`,
3232
dialog: 'Hello adventurer!',
33+
onCollide() {
34+
console.log('You have collided with the cell!')
35+
},
36+
onCollideStart() {
37+
console.log('You have previously collided with the cell!')
38+
},
3339
},
3440
},
3541
map: `

packages/odyc/src/gameLoop.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,21 @@ class GameLoop<T extends string> {
4444
if (this.#isCellOnworld(to.value)) {
4545
const cell = this.#gameState.cells.getCellAt(...to.value)
4646

47-
if (!cell.solid) {
47+
if (cell.solid) {
48+
await this.#gameState.cells.getEvent(...to.value, 'onCollideStart')?.()
49+
} else {
4850
await this.#gameState.cells.getEvent(...from.value, 'onLeave')?.()
4951
this.#gameState.player.position = to.value
52+
await this.#gameState.cells.getEvent(...to.value, 'onEnterStart')?.()
5053
}
5154

5255
this.#playSound(cell)
5356
await this.#openDialog(cell)
5457

55-
if (cell.solid)
56-
await this.#gameState.cells.getEvent(...to.value, 'onCollide')?.()
57-
else await this.#gameState.cells.getEvent(...to.value, 'onEnter')?.()
58+
await this.#gameState.cells.getEvent(
59+
...to.value,
60+
cell.solid ? 'onCollide' : 'onEnter',
61+
)?.()
5862
}
5963

6064
for (const cell of this.#gameState.cells.get()) {

packages/odyc/src/gameState/cells.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,9 @@ export class Cells<T extends string> {
163163
y: number,
164164
eventKey:
165165
| 'onCollide'
166+
| 'onCollideStart'
166167
| 'onEnter'
168+
| 'onEnterStart'
167169
| 'onLeave'
168170
| 'onScreenLeave'
169171
| 'onScreenEnter'
@@ -247,6 +249,8 @@ export class Cells<T extends string> {
247249
visible: template.visible !== false,
248250
foreground: template.foreground === true,
249251
onCollide: template.onCollide,
252+
onCollideStart: template.onCollideStart,
253+
onEnterStart: template.onEnterStart,
250254
onEnter: template.onEnter,
251255
onLeave: template.onLeave,
252256
onScreenEnter: template.onScreenEnter,

packages/odyc/src/gameState/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ export type CellState<T extends string> = {
4545
position: [number, number]
4646
/** Called when player tries to move into this cell's position */
4747
onCollide?: (target: CellFacade<T>) => any
48+
/** Called after player collides with this cell */
49+
onCollideStart?: (target: CellFacade<T>) => any
50+
/** Call when a player begins to enter a cell, before dialog and sounds */
51+
onEnterStart?: (target: CellFacade<T>) => any
4852
/** Called when player moves into this cell's position */
4953
onEnter?: (target: CellFacade<T>) => any
5054
/** Called when player leaves this cell's position */
@@ -70,6 +74,8 @@ export type CellParams = Partial<
7074
| 'symbol'
7175
| 'position'
7276
| 'onCollide'
77+
| 'onCollideStart'
78+
| 'onEnterStart'
7379
| 'onEnter'
7480
| 'onLeave'
7581
| 'onScreenEnter'

tests/odyc-e2e/functional/move-cell/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ const state = {
55
turnSpy: null as any,
66
enterSpy: null as any,
77
collideSpy: null as any,
8+
onCollideStartSpy: null as any,
89
}
910

1011
export const init = () => {
1112
state.turnSpy = vi.fn()
1213
state.enterSpy = vi.fn()
1314
state.collideSpy = vi.fn()
14-
15+
state.onCollideStartSpy = vi.fn()
1516
const game = createGame({
1617
templates: {
1718
x: {
@@ -21,6 +22,7 @@ export const init = () => {
2122
onTurn: state.turnSpy,
2223
onEnter: state.enterSpy,
2324
onCollide: state.collideSpy,
25+
onCollideStart: state.onCollideStartSpy,
2426
},
2527
y: {
2628
sprite: 2,
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { expect, test, describe, vi } from 'vitest'
2+
import { createGame } from 'odyc'
3+
import { userEvent } from '@vitest/browser/context'
4+
5+
describe('onCollide and onCollideStart events', () => {
6+
test('should call onCollide when player collides with a cell', async () => {
7+
const collideSpy = vi.fn()
8+
const game = createGame({
9+
player: {
10+
position: [0, 1],
11+
},
12+
templates: {
13+
x: {
14+
onCollide: collideSpy,
15+
},
16+
},
17+
map:
18+
`
19+
x.
20+
..
21+
`,
22+
})
23+
expect(collideSpy).not.toHaveBeenCalled()
24+
await userEvent.keyboard('[ArrowUp]')
25+
expect(collideSpy).toHaveBeenCalled()
26+
})
27+
test('should call onCollideStart when player collides with a cell for the first time', async () => {
28+
const collideStartSpy = vi.fn()
29+
const game = createGame({
30+
templates: {
31+
x: {
32+
onCollideStart: collideStartSpy,
33+
},
34+
},
35+
map:
36+
`
37+
x.
38+
..
39+
`,
40+
})
41+
expect(collideStartSpy).not.toHaveBeenCalled()
42+
// slightly more complex route for funsies
43+
await userEvent.keyboard('[ArrowRight]')
44+
await userEvent.keyboard('[ArrowUp]')
45+
await userEvent.keyboard('[ArrowLeft]')
46+
expect(collideStartSpy).toHaveBeenCalled()
47+
})
48+
})

0 commit comments

Comments
 (0)