Skip to content

Commit

Permalink
Player movement implemented.
Browse files Browse the repository at this point in the history
  • Loading branch information
avinashv committed Jul 4, 2023
1 parent 1656148 commit a6507af
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 6 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Built using Typescript and [Malwoden](https://malwoden.com), partially following

This repository is participating in the 2023 edition of the [RoguelikeDev event](https://www.reddit.com/r/roguelikedev/comments/14kz7al/roguelikedev_does_the_complete_roguelike_tutorial/), running from 4 July 2023 till 22 August 2023.

### Week 1 - 4 July 2023 - Setup, drawing an @, and moving around
### [Week 1](https://www.reddit.com/r/roguelikedev/comments/14q58js/roguelikedev_does_the_complete_roguelike_tutorial/) - 4 July 2023 - Setup, drawing an @, and moving around

- Getting this done a bit in advance because I know I am going to be busy over this year's sprint!
- The Malwoden tutorial doesn't really spend any time explaining how to set up the development environment--it just asks for some files to be copy/pasted. I've used `vite` for packaging and am just using the `vanilla-ts` template.
Expand All @@ -21,6 +21,8 @@ This repository is participating in the 2023 edition of the [RoguelikeDev event]
- A lot of logic keeps being shoved into the `main.ts` file and I am expecting a serious refactor down the road.
- Malwoden itself seems to get out of the way--I enjoy this.
- The ECS system is simple but seems sufficient--compared to Rust's `specs` or `legion` this feels much better for a beginner.
- Lots of mistakes in the tutorial--in Chapter 3, for example, the entire input handling code is missing imports and declarations.
- I prefered implementing game states in `game-states.ts` as an enum to reference.

### Week 2 - 11 July 2023 - The object system and generating your first map

Expand Down Expand Up @@ -52,7 +54,7 @@ Your hometown is suffering from a cataclysm of monters. You have been tasked wit

### MVP

- [ ] Player can walk around
- [x] Player can walk around
- [ ] Create a basic procedural dungeon map
- [ ] Player has field-of-view
- [ ] Spawn monsters
Expand Down
7 changes: 7 additions & 0 deletions src/game-states.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* Possible game states
*/
export enum GameStates {
INIT,
PLAYER_TURN,
}
61 changes: 57 additions & 4 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Terminal, Color } from 'malwoden';
import { Terminal, Color, Input, Vector2 } from 'malwoden';
import { World, Entity } from 'ecsy';

import * as Components from './components';
import * as Systems from './systems';
import { GameStates } from './game-states';

/**
* The main game engine.
Expand All @@ -19,6 +20,9 @@ export class Game {
lastTime: number;

player: Entity;
input = new Input.KeyboardHandler();

gameState: GameStates;

constructor() {
this.world = new World();
Expand All @@ -27,6 +31,8 @@ export class Game {

this.registerECS();
this.player = this.initWorld();

this.gameState = GameStates.INIT;
}

/**
Expand Down Expand Up @@ -78,23 +84,70 @@ export class Game {
* @param delta Time passed since last tick
* @param time Current time
*/
tick(delta: number, time: number) {
async tick(delta: number, time: number) {
// PLAYER_TURN
if (this.gameState == GameStates.PLAYER_TURN) {
// handle player input
const key = await this.input.waitForKeyDown();

// create an actions map of potential keypresses
const actions = new Map<number, () => void>();
actions.set(Input.KeyCode.LeftArrow, () =>
tryMoveEntity(this.player, { x: -1, y: 0 })
);
actions.set(Input.KeyCode.RightArrow, () =>
tryMoveEntity(this.player, { x: 1, y: 0 })
);
actions.set(Input.KeyCode.UpArrow, () =>
tryMoveEntity(this.player, { x: 0, y: -1 })
);
actions.set(Input.KeyCode.DownArrow, () =>
tryMoveEntity(this.player, { x: 0, y: 1 })
);

// if the keypair in the map matches an input key, run the command
const command = actions.get(key);
if (command) command();
}

// execute game systems
this.world.execute(delta, time);

if (this.gameState == GameStates.INIT) {
this.gameState = GameStates.PLAYER_TURN;
}
}

/**
* The engine's bootstrap function. Sets up the main game loop and runs it.
*/
run() {
async run() {
const time = performance.now();
const delta = time - this.lastTime;

this.tick(delta, this.lastTime);
await this.tick(delta, this.lastTime);

window.requestAnimationFrame(this.run.bind(this));
}
}

/**
* Attempts to move an Entity in position.
* @param entity Entity with a Position component
* @param delta Movement vector delta
*/
function tryMoveEntity(entity: Entity, delta: Vector2) {
const position = entity.getMutableComponent(Components.Position);

if (!position) {
console.warn('WARNING: Can\'t move an entity without a Position!');
return;
}

position.x += delta.x;
position.y += delta.y;
}

// Modify the Window to include the Game object.
declare global {
interface Window {
Expand Down

0 comments on commit a6507af

Please sign in to comment.