Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Milestone 5 #12

Merged
merged 42 commits into from
Apr 3, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
c9716c5
fix gh-pages asset loading
smileynet Feb 25, 2023
f8528b7
update name and favicon
smileynet Feb 26, 2023
8523cd5
fix asset loading for gh-pages
smileynet Feb 26, 2023
3e482fb
update readme
smileynet Feb 26, 2023
d369342
ractor actions
smileynet Feb 26, 2023
67ab753
add css editor settings
smileynet Feb 26, 2023
d5117b3
fix css style
smileynet Feb 26, 2023
3903620
refactor putout suggested changes
smileynet Feb 26, 2023
4843012
update project settings to add react & redux
smileynet Feb 26, 2023
6aa1835
add react as entry point
smileynet Feb 26, 2023
43c29c8
add App unit test
smileynet Feb 26, 2023
1777723
fix Directions type
smileynet Feb 27, 2023
22f6f6b
remove unused performAction method
smileynet Feb 27, 2023
c8f2b02
fix interactable direction reference
smileynet Feb 27, 2023
1ffef7a
refactor thing tests to interactable
smileynet Feb 27, 2023
e933e16
remove thing test
smileynet Feb 27, 2023
6fa325c
add react settings
smileynet Feb 27, 2023
f59cc4d
remove gh-pages
smileynet Feb 27, 2023
6964bcd
remove unused imports
smileynet Feb 27, 2023
7ae081d
fix jest tests
smileynet Feb 27, 2023
9e507fc
remove cypress
smileynet Feb 27, 2023
c709a00
config updates
smileynet Mar 4, 2023
f1eaff3
add player healthbar
smileynet Mar 4, 2023
e872e51
Add healthBar to object on player focus.
smileynet Mar 4, 2023
fd11bae
Add healthBar to object on player focus.
smileynet Mar 4, 2023
d54ba9c
Code cleanup - Fix #6 #7
smileynet Mar 4, 2023
20650fe
Code cleanup - Fix #6 #7
smileynet Mar 4, 2023
17ec584
Merge remote-tracking branch 'origin/milestone-5' into milestone-5
smileynet Mar 4, 2023
da1a740
add broken and destroyed cases to feature test
smileynet Mar 4, 2023
58c4f7a
refactor with even more composition
smileynet Mar 5, 2023
99683de
Update tests
smileynet Mar 5, 2023
36fbcbc
refactor event bus with logging
smileynet Mar 5, 2023
d743374
add multi-directional movement
smileynet Mar 5, 2023
9b0e3e3
Added extensive debugging system with toggles.
smileynet Mar 5, 2023
066a353
Fix health constructor
smileynet Mar 6, 2023
65ce756
Fix health constructor
smileynet Mar 6, 2023
f7391ae
fix universe interactable deletion, refactor playerControl and Action…
smileynet Mar 7, 2023
ecba055
fix universe interactable deletion, refactor playerControl and Action…
smileynet Mar 7, 2023
1f68554
fix healthBar movement
smileynet Mar 8, 2023
9ebbae5
Closing milestone 5
smileynet Mar 8, 2023
bcf25ec
Merge branch 'main' into milestone-5
smileynet Mar 8, 2023
6ee9557
build fixes
smileynet Mar 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Update tests
Signed-off-by: Sam Biggins <sambiggins@gmail.com>
  • Loading branch information
smileynet committed Mar 5, 2023
commit 99683ded0d6da6f7eeba95d0ac17767de420b103
9 changes: 6 additions & 3 deletions src/components/attack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export class Attack implements IComponent {
this._amount = amount;
}

private _target?: string | undefined;
private _target = 'none';

get target() {
return this._target;
Expand All @@ -26,8 +26,11 @@ export class Attack implements IComponent {

public subscribe(eventBus: EventBus) {
this._eventBus = eventBus;
this._eventBus.subscribe('performAttack', this.performAttack);
this._eventBus.subscribe('focusChanged', this.focusChanged);
this._eventBus.subscribe(
'performAttack',
this.performAttack.bind(this)
);
this._eventBus.subscribe('focusChanged', this.focusChanged.bind(this));
}

public destroy() {
Expand Down
20 changes: 13 additions & 7 deletions src/components/health.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ export class Health implements IComponent {
private readonly _brokenThreshold: number;
private _eventBus!: EventBus;

constructor(amount: number, maxHealth: number, brokenThreshold: number) {
constructor(
amount: number,
maxHealth: number,
brokenThreshold = 1
) {
this._amount = amount;
this._maxHealth = maxHealth;
this._brokenThreshold = brokenThreshold;
Expand All @@ -28,13 +32,14 @@ export class Health implements IComponent {
this._amount = amount;
this._eventBus.publish('healthChanged', this._amount);
if (this._amount <= 0) {
this.destroy();
log.info(`Object is destroyed`);
this._eventBus.publish('destroyed', this.amount);
}
if (this._amount < this._brokenThreshold) {
if (this._amount <= this._brokenThreshold && !this._isBroken) {
this._isBroken = true;
this._eventBus.publish('broken', this._amount);
log.info(`Object is broken`); // TODO: move logging to subscriber
} else {
} else if (this._amount >= this._brokenThreshold && this._isBroken) {
this._isBroken = false;
this._eventBus.publish('fixed', this._amount);
log.info(`Object is no longer broken`);
Expand All @@ -53,16 +58,17 @@ export class Health implements IComponent {

public subscribe(eventBus: EventBus) {
this._eventBus = eventBus;
this._eventBus.subscribe('takeDamage', this.handleTakeDamage);
this._eventBus.subscribe(
'takeDamage',
this.handleTakeDamage.bind(this)
);
}

public update() {
// do nothing
}

public destroy() {
this._eventBus.publish('destroyed', this.amount);
log.info(`Object is destroyed`);
this.unsubscribe();
}

Expand Down
7 changes: 5 additions & 2 deletions src/components/healthBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ export class HealthBarComponent implements IComponent {

public subscribe(eventBus: EventBus) {
this._eventBus = eventBus;
this._eventBus.subscribe('healthChanged', this.updateHealth);
this._eventBus.subscribe('positionChanged', this.updatePosition);
this._eventBus.subscribe('healthChanged', this.updateHealth.bind(this));
this._eventBus.subscribe(
'positionChanged',
this.updatePosition.bind(this)
);
}

public updateHealth(amount: number): void {
Expand Down
4 changes: 2 additions & 2 deletions src/components/movement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export class Movement implements IComponent {

public subscribe(eventBus: EventBus) {
this._eventBus = eventBus;
this._eventBus.subscribe('move', this.handleMove);
this._eventBus.subscribe('stop', this.handleStop);
this._eventBus.subscribe('move', this.handleMove.bind(this));
this._eventBus.subscribe('stop', this.handleStop.bind(this));
}

handleStop() {
Expand Down
5 changes: 4 additions & 1 deletion src/components/sprite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ export class Sprite implements IComponent {

public subscribe(eventBus: EventBus) {
this._eventBus = eventBus;
this._eventBus.subscribe('spriteShouldUpdate', this.handleSpriteUpdate);
this._eventBus.subscribe(
'spriteShouldUpdate',
this.handleSpriteUpdate.bind(this)
);
}

public setPlayerSpriteProperties() {
Expand Down
18 changes: 0 additions & 18 deletions src/components/thing.ts

This file was deleted.

8 changes: 4 additions & 4 deletions src/entities/actor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ export class Actor extends Interactable {
);
this.universeEventBus.subscribe(
'attackRequested',
this.handleAttackRequested
this.handleAttackRequested.bind(this)
);
this.universeEventBus.subscribe('move', this.handleMove);
this.universeEventBus.subscribe('stop', this.handleStop);
this.universeEventBus.subscribe('move', this.handleMove.bind(this));
this.universeEventBus.subscribe('stop', this.handleStop.bind(this));
}

private handleAttackRequested(interactableId: string) {
if (interactableId === this.id) {
if (interactableId === this._id) {
this.interactableEventBus.publish(
'performAttack',
this.universeEventBus
Expand Down
5 changes: 4 additions & 1 deletion src/entities/interactable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ export class Interactable {
'attackPerformed',
this.handleAttackPerformed
);
this.interactableEventBus.subscribe('destroyed', this.destroy);
this.interactableEventBus.subscribe(
'destroyed',
this.destroy.bind(this)
);
this.interactableEventBus.subscribe(
'componentDirty',
this.markComponentDirty
Expand Down
11 changes: 5 additions & 6 deletions test/features/player-interaction.feature
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ Feature: Basic player interaction
When the player attacks the bench <times> times
Then the bench should have a healthBar
Then the bench should have <health> health left
Then the <texture> texture should show on the bench
Then the bench should be <destroyed> destroyed
Then the bench should be <state>

Examples:
| times | health | texture | destroyed |
| 1 | 2 | bench | not |
| 2 | 1 | bench-broken | not |
| 3 | 0 | undefined | |
| times | health | state |
| 1 | 2 | fine |
| 2 | 1 | broken |
| 3 | 0 | destroyed |
74 changes: 17 additions & 57 deletions test/features/steps/interaction.steps.ts
Original file line number Diff line number Diff line change
@@ -1,55 +1,17 @@
import { defineFeature, loadFeature } from 'jest-cucumber';
import { Actor, Interactable } from '@src/entities';
import { GameScene } from '@src/scenes/gameScene';
import { gameConfig } from '@src/phaserGame';
import Phaser from 'phaser';
import GameConfig = Phaser.Types.Core.GameConfig;

const mockBenchSprite = {
setTexture: jest
.fn()
.mockImplementation(function (
this: Phaser.Physics.Arcade.Sprite,
key: string
) {
this.texture = { key };
}),
texture: {},
scene: {},
destroy: jest.fn()
} as unknown as Phaser.Physics.Arcade.Sprite;
jest.mock('@src/ui', () => ({
HealthBar: jest.fn().mockImplementation(() => {
return {
setHealth: jest.fn(),
updatePosition: jest.fn(),
destroy: jest.fn()
};
})
}));
import { EventBus } from '@src/systems';
import { Health, HealthBarComponent } from '@src/components';

const feature = loadFeature('test/features/player-interaction.feature');
defineFeature(feature, (test) => {
let player: Actor;
let bench: Interactable;
let scene: GameScene;
let phaser: Phaser.Game;

beforeAll(async () => {
phaser = new Phaser.Game(gameConfig as GameConfig);
scene = phaser.scene.getScene('GameScene');
await scene.create();
});

beforeEach(async () => {
jest.clearAllMocks();
const universeEventBus = scene.universe.eventBus;

const universeEventBus = new EventBus();
player = new Actor('player', universeEventBus);
bench = new Interactable('bench', universeEventBus);
mockBenchSprite.setTexture('bench');
mockBenchSprite.scene = scene;
bench.setSprite(mockBenchSprite);
});

test('A player attacking a bench', ({ given, when, then }) => {
Expand All @@ -62,26 +24,24 @@ defineFeature(feature, (test) => {
}
});
then('the bench should have a healthBar', () => {
const healthBar = bench.getComponent('HealthBarComponent');
expect(bench.healthBar).not.toBeNull();
});
then(/^the bench should have (.*) health left$/, (arg0: string) => {
expect(bench.thing.health).toBe(parseInt(arg0));
const healthBar = bench.getComponent(HealthBarComponent);
expect(healthBar).not.toBeNull();
});
then(/^the (.*) texture should show on the bench$/, (arg0: string) => {
if (arg0 === 'undefined') {
expect(bench.sprite?.texture.key).toBeUndefined();
then(/^the bench should have (\d+) health left$/, (amount) => {
const num = parseInt(amount);
const health = bench.getComponent(Health);
if (num > 0) {
expect(health?.amount).toBe(num);
} else {
expect(bench.sprite?.texture.key).toBe(arg0);
expect(health).toBeUndefined();
}
});
then(/^the bench should be (.*) destroyed$/, (arg0) => {
if (arg0 === 'not') {
expect(bench.thing.health).toBeGreaterThan(0);
expect(bench.sprite).not.toBeNull();
} else {
expect(bench.thing.health).toBe(0);
expect(bench.sprite).toBeUndefined();
then(/^the bench should be (.*)$/, (arg0) => {
const health = bench.getComponent(Health);
if (arg0 === 'destroyed') {
expect(health).toBeUndefined();
} else if (arg0 === 'not destroyed') {
expect(health).toBeDefined();
}
});
});
Expand Down
23 changes: 13 additions & 10 deletions test/unit/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,24 @@
import ReactDOM from 'react-dom';
import App from '../../src/App';
import '../../src/phaserGame';
import { render } from '@testing-library/react';
import { act, render } from '@testing-library/react';
import '@testing-library/jest-dom';

jest.mock('../../src/phaserGame', () => jest.fn());

describe('App', () => {
it('matches the snapshot', () => {
const app = render(<App />);
it('matches the snapshot', () => {
const app = render(<App />);

expect(app).toMatchSnapshot();
});
expect(app).toMatchSnapshot();
});

it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});
it('renders without crashing', () => {
const div = document.createElement('div');
act(() => {
ReactDOM.render(<App />, div);
});
ReactDOM.unmountComponentAtNode(div);
expect(div.innerHTML).toBe('');
});
});
35 changes: 0 additions & 35 deletions test/unit/interactable.spec.ts

This file was deleted.