Skip to content

Commit a720b63

Browse files
committed
Working IsIdle, IsWalking and IsAttackingWithClub
- animations offset not working yet - animation settings are not yet dynamically set.
1 parent 553fdc6 commit a720b63

36 files changed

+557
-6424
lines changed

README.md

+27-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,33 @@
1-
# glhf
1+
glhf
2+
====
3+
4+
![glhf.js](./docs/logo.png)
5+
26
> Game library for 2d games written in Typescript. \
37
> GL HF stands for "Good luck, have fun!"
48
5-
### Boostrapping a game
9+
10+
## Packages
11+
12+
* [glhf-assets](./packages/glhf-assets) - Helper to load assets files (JSON, Images).
13+
* [glhf-bitmask](./packages/glhf-bitmask) - Bitmask library for fast bitwise operations.
14+
* [glfh-component](./packages/glhf-component) - Generic opinionated ECS Components.
15+
* [glhf-ecs](./packages/glhf-ecs) - ECS Library that implements the following classes Entity, Component, System, Query, World
16+
* [glhf-fsm](./packages/glhf-fsm) - Finite State Machine implementation.
17+
* [glhf-input](./packages/glhf-input) - Implementation of inputs like Keyboard, Mouse and Controller.
18+
* [glhf-renderer](./packages/glhf-renderer) - Rendering UI and Canvas utilities.
19+
20+
## Demo
21+
22+
* [glhf-demo](./packages/glhf-demo) - A demo of a 2d game implementation using glhf.js library
23+
24+
## Development
25+
26+
Library is currently under development. \
27+
You can see the progress by following me at https://www.youtube.com/@SerbanTV \
28+
Catch me on the [Discord server](https://discord.gg/Vur9NaF) to discuss stuff about game dev, ECS, etc.
29+
30+
## Bootstrapping a game (wip)
631

732
```ts
833
import {map, state, keyboard, viewport, camera, start} from "@glhf/engine";

docs/logo.png

23.8 KB
Loading

packages/glhf-component/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
"scripts": {
77
"test": "echo \"Error: no test specified\" && exit 1"
88
},
9-
"author": "",
10-
"license": "ISC"
9+
"author": "Serban Ghita",
10+
"license": "MIT"
1111
}

packages/glhf-component/src/Direction.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ export enum Directions {
44
NONE, LEFT, RIGHT, UP, DOWN
55
}
66

7-
export interface IDirectionProps {
7+
export type DirectionProps = {
88
x: Directions.LEFT | Directions.RIGHT | Directions.NONE
9-
y: Directions.UP | Directions.DOWN | Directions.NONE
9+
y: Directions.UP | Directions.DOWN | Directions.NONE,
10+
literal: 'up' | 'down' | 'left' | 'right' | ''
1011
}
1112

1213
export default class Direction extends Component {
13-
constructor(public properties: IDirectionProps) {
14+
constructor(public properties: DirectionProps) {
1415
super(properties);
1516
}
1617
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import Component from "../../../glhf-ecs/src/Component";
2+
3+
interface CurrentStateProps {
4+
stateName: string;
5+
}
6+
7+
export default class CurrentState extends Component {
8+
constructor(public properties: CurrentStateProps) {
9+
super(properties);
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import Component from "../../../glhf-ecs/src/Component";
2+
import {StateStatus} from "../state/state-status";
3+
import {extend} from "../utils";
4+
5+
interface IsAttackingWithClubProps {
6+
stateName: string;
7+
animationStateName: string;
8+
animationTick: number;
9+
tick: number;
10+
status: StateStatus;
11+
[key: string]: any;
12+
}
13+
14+
export default class IsAttackingWithClub extends Component {
15+
constructor(public properties: IsAttackingWithClubProps) {
16+
super(properties);
17+
18+
this.init(properties);
19+
}
20+
21+
public init(properties: IsAttackingWithClubProps) {
22+
const defaultProps = {
23+
stateName: 'club_attack_one',
24+
animationStateName: 'club_attack_one_down',
25+
animationTick: 0,
26+
tick: 0,
27+
status: StateStatus.NOT_STARTED
28+
};
29+
30+
this.properties = extend(defaultProps, properties);
31+
}
32+
}
+23-5
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,32 @@
11
import Component from "../../../glhf-ecs/src/Component";
2+
import {StateStatus} from "../state/state-status";
3+
import {extend} from "../utils";
24

3-
interface IsIdleState {
4-
state: string;
5-
animationState: string;
6-
stateTick: number;
5+
interface IsIdleProps {
6+
stateName: string;
7+
animationStateName: string;
78
animationTick: number;
9+
tick: number;
10+
status: StateStatus;
11+
[key: string]: any;
812
}
913

1014
export default class IsIdle extends Component {
11-
constructor(public properties: IsIdleState) {
15+
constructor(public properties: IsIdleProps) {
1216
super(properties);
17+
18+
this.init(properties);
19+
}
20+
21+
public init(properties: IsIdleProps) {
22+
const defaultProps = {
23+
stateName: 'idle',
24+
animationStateName: 'idle_down',
25+
animationTick: 0,
26+
tick: 0,
27+
status: StateStatus.NOT_STARTED
28+
};
29+
30+
this.properties = extend(defaultProps, properties);
1331
}
1432
}
+23-5
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,32 @@
11
import Component from "../../../glhf-ecs/src/Component";
2+
import {StateStatus} from "../state/state-status";
3+
import {extend} from "../utils";
24

3-
interface IsWalkingState {
4-
state: string;
5-
animationState: string;
6-
stateTick: number;
5+
interface IsWalkingProps {
6+
stateName: string;
7+
animationStateName: string;
78
animationTick: number;
9+
tick: number;
10+
status: StateStatus;
11+
[key: string]: any;
812
}
913

1014
export default class IsWalking extends Component {
11-
constructor(public properties: IsWalkingState) {
15+
constructor(public properties: IsWalkingProps) {
1216
super(properties);
17+
18+
this.init(properties);
19+
}
20+
21+
public init(properties: IsWalkingProps) {
22+
const defaultProps = {
23+
stateName: 'walking',
24+
animationStateName: 'walk_down',
25+
animationTick: 0,
26+
tick: 0,
27+
status: StateStatus.NOT_STARTED
28+
};
29+
30+
this.properties = extend(defaultProps, properties);
1331
}
1432
}

packages/glhf-demo/src/index.ts

+45-53
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import ComponentRegistry from "../../glhf-ecs/src/ComponentRegistry";
2-
import Entity from "../../glhf-ecs/src/Entity";
32
import World from "../../glhf-ecs/src/World";
43
import Body from "../../glhf-component/src/Body";
54
import Position from "../../glhf-component/src/Position";
@@ -15,12 +14,13 @@ import {default as KeyboardInput, InputActions} from "../../glhf-input/src/Keybo
1514
import PlayerKeyboardSystem from "./system/PlayerKeyboardSystem";
1615
import RenderSystem from "./system/RenderSystem";
1716
import PreRenderSystem from "./system/PreRenderSystem";
18-
import {PlayerState} from "./component/PlayerState";
1917
import IsIdle from "./component/IsIdle";
2018
import IsWalking from "./component/IsWalking";
2119
import IdleSystem from "./system/IdleSystem";
2220
import WalkingSystem from "./system/WalkingSystem";
23-
import StateSystem from "./system/StateSystem";
21+
import CurrentState from "./component/CurrentState";
22+
import IsAttackingWithClub from "./component/IsAttackingWithClub";
23+
import AttackingWithClubSystem from "./system/AttackingWithClubSystem";
2424

2525
// 0. Create the UI and canvas.
2626
const $wrapper = createWrapperElement('game-wrapper', 640, 480);
@@ -45,24 +45,24 @@ input.bindKey('w', InputActions.MOVE_UP);
4545
input.bindKey('s', InputActions.MOVE_DOWN);
4646
input.bindKey('a', InputActions.MOVE_LEFT);
4747
input.bindKey('d', InputActions.MOVE_RIGHT);
48-
input.bindKey('q', InputActions.ACTION_1);
48+
input.bindKey(' ', InputActions.ACTION_1);
4949
input.listen();
5050

51-
// Register all "Components".
52-
const reg = ComponentRegistry.getInstance();
53-
reg.registerComponent(Body);
54-
reg.registerComponent(Position);
55-
reg.registerComponent(Direction);
56-
reg.registerComponent(Keyboard);
57-
reg.registerComponent(Renderable);
58-
reg.registerComponent(SpriteSheet);
59-
reg.registerComponent(IsIdle);
60-
reg.registerComponent(IsWalking);
61-
reg.registerComponent(State);
62-
6351
// Create the current "World" (scene).
6452
const world = new World();
6553

54+
// Register all "Components".
55+
world.registerComponent(Body)
56+
.registerComponent(Position)
57+
.registerComponent(Direction)
58+
.registerComponent(Keyboard)
59+
.registerComponent(Renderable)
60+
.registerComponent(SpriteSheet)
61+
.registerComponent(IsIdle)
62+
.registerComponent(IsWalking)
63+
.registerComponent(IsAttackingWithClub)
64+
.registerComponent(CurrentState);
65+
6666
world.createEntity("dino")
6767
.addComponent(Body, { width: 10, height: 20 });
6868

@@ -72,12 +72,6 @@ world.createEntity("player")
7272
.addComponent(Direction, { x: Directions.NONE, y: Directions.NONE })
7373
.addComponent(Keyboard, { up: "w", down: "s", left: "a", right: "d" })
7474
.addComponent(Renderable)
75-
.addComponent(IsIdle, {
76-
state: 'idle',
77-
animationState: 'idle_up',
78-
stateTick: 0,
79-
animationTick: 0
80-
})
8175
.addComponent(SpriteSheet, {
8276
name: 'kil',
8377
offset_x: 128,
@@ -87,36 +81,34 @@ world.createEntity("player")
8781
animations: new Map(),
8882
animationCurrentFrame: '',
8983
animationDefaultFrame: '',
90-
}).addComponent(State, {
91-
state: PlayerState.idle,
92-
stateTick: 0,
93-
animationState: kilDefaultAnimationFrameName,
94-
animationTick: 0
95-
});
96-
97-
98-
world.createQuery("renderable", { all: [Renderable, SpriteSheet, Position] });
99-
world.createQuery("keyboard", { all: [Keyboard] });
100-
world.createQuery("idle", {all: [IsIdle]});
101-
world.createQuery("walking", {all: [IsWalking]});
102-
103-
104-
// Pre-loop system run.
105-
const preRenderSystem = new PreRenderSystem(world.getQuery("renderable"));
106-
preRenderSystem.update(0);
107-
const inputSystem = new PlayerKeyboardSystem(world.getQuery("keyboard"), input);
108-
const idleSystem = new IdleSystem(world.getQuery("idle"));
109-
const walkingSystem = new WalkingSystem(world.getQuery("walking"));
110-
const renderSystem = new RenderSystem(world.getQuery("renderable"), $foreground);
111-
const stateSystem = new StateSystem(world.getQuery("renderable")); // @todo: Make this work on all entities.
112-
84+
}).addComponent(IsIdle, {
85+
animationStateName: kilDefaultAnimationFrameName,
86+
}).addComponent(CurrentState, { stateName: 'IsIdle' })
87+
88+
world.createQuery("keyboard-query", { all: [Keyboard] });
89+
world.createQuery("idle-query", {all: [IsIdle]});
90+
world.createQuery("walking-query", {all: [IsWalking]});
91+
world.createQuery("attacking-with-club-query", {all: [IsAttackingWithClub]});
92+
world.createQuery("renderable-query", { all: [Renderable, SpriteSheet, Position] });
93+
94+
world.registerSystem("pre-render-system", PreRenderSystem)
95+
.registerSystem("input-system", PlayerKeyboardSystem)
96+
.registerSystem("idle-system", IdleSystem)
97+
.registerSystem("walking-system", WalkingSystem)
98+
.registerSystem("attacking-with-club-system", AttackingWithClubSystem)
99+
.registerSystem("render-system", RenderSystem);
100+
101+
world.createSystem("pre-render-system", "renderable-query")
102+
.createSystem("input-system", "keyboard-query", input)
103+
.createSystem("idle-system", "idle-query")
104+
.createSystem("walking-system", "walking-query")
105+
.createSystem("attacking-with-club-system", "attacking-with-club-query")
106+
.createSystem("render-system", "renderable-query", $foreground)
107+
108+
world.getSystem("pre-render-system").update(0);
113109

114110
const loop = (now: DOMHighResTimeStamp) => {
115-
inputSystem.update(now);
116-
idleSystem.update(now);
117-
walkingSystem.update(now);
118-
stateSystem.update(now);
119-
renderSystem.update(now);
111+
world.systems.forEach(system => system.update(now));
120112

121113
window.requestAnimationFrame(loop);
122114
};
@@ -125,8 +117,8 @@ window.requestAnimationFrame(loop);
125117

126118

127119
// @ts-ignore
128-
// window['engine'] = {
129-
// 'q': q
130-
// };
120+
window['engine'] = {
121+
world
122+
};
131123

132124

packages/glhf-demo/src/component/PlayerState.ts packages/glhf-demo/src/state/player-animation-states.ts

-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
export const enum PlayerState {
2-
idle = 'idle',
3-
walk = 'walk',
4-
club_attack = 'club_attack'
5-
}
6-
71
export const enum PlayerAnimationState {
82
"idle" = "idle",
93
"walk_left" = "walk_left",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export const enum PlayerState {
2+
idle = 'idle',
3+
walk = 'walk',
4+
club_attack = 'club_attack'
5+
}
6+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export enum StateStatus {
2+
NOT_STARTED = 0,
3+
STARTED = 1,
4+
FINISHED = 2
5+
}

0 commit comments

Comments
 (0)