Skip to content

Commit

Permalink
feat: add basic single square movement on button press
Browse files Browse the repository at this point in the history
  • Loading branch information
hxtree committed Dec 11, 2024
1 parent 4c39983 commit 645a9a1
Show file tree
Hide file tree
Showing 39 changed files with 862 additions and 109 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"Aniroth",
"Asmin",
"bson",
"dtos",
"Embeddable",
"esbuild",
"Gaali",
Expand Down
2 changes: 1 addition & 1 deletion clients/jukebox/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"@galaxyops/base-nodejs": "0.2.0",
"@galaxyops/constructs": "2.2.0",
"@galaxyops/nestjs-modules": "2.2.0",
"@galaxyops/validation-schemas": "2.2.0",
"@galaxyops/validation-schemas": "workspace:*",
"@nestjs/common": "9.4.0",
"@nestjs/config": "2.2.0",
"@nestjs/core": "9.2.1",
Expand Down
9 changes: 7 additions & 2 deletions clients/player-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,17 @@
},
"dependencies": {
"@galaxyops/design-system": "workspace:*",
"@galaxyops/faker-factory": "3.3.0",
"@galaxyops/validation-schemas": "workspace:*",
"axios": "^1.6.7",
"class-transformer": "0.5.1",
"class-validator": "0.13.2",
"lodash": "4.17.21",
"luxon": "~3.3.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-router-dom": "6.22.1"
"react-router-dom": "6.22.1",
"reflect-metadata": "0.1.13"
},
"devDependencies": {
"@galaxyops/base-nodejs": "workspace:*",
Expand All @@ -54,7 +59,7 @@
"ts-jest": "29.1.2",
"ts-node": "10.9.2",
"typescript": "5.3.3",
"vite": "^4.5.0",
"vite": "5.4.11",
"vite-plugin-static-copy": "^2.1.0"
}
}
1 change: 1 addition & 0 deletions clients/player-client/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'reflect-metadata';
import '@galaxyops/design-system/dist/assets/style.css';
import { AppProvider } from './context/App/AppProvider';
import { PageFooter, faGithub } from '@galaxyops/design-system/dist/main';
Expand Down
29 changes: 25 additions & 4 deletions clients/player-client/src/core/GameEngine/GameEngine.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,33 @@
import React from 'react';
import React, { useEffect } from 'react';
import { useInputContext } from '../../context/Input/useInputContext';
import { InputEventRecordKey } from '../../dtos/Player/InputEventRecordKey.type';
import { GameState } from '../../dtos/GameState.dto';

export type GameEngineProps = {
data: any;
data: GameState;
updateData: (newData: any) => void;
};

export const GameEngine: React.FC<GameEngineProps> = () => {
// if input up then try to move up
export const GameEngine: React.FC<GameEngineProps> = props => {
const { data, updateData } = props;
const inputContext = useInputContext();

useEffect(() => {
if (inputContext.state.key === InputEventRecordKey.LEFT) {
data.actors[0].movement.targetPosition.x--;
}
if (inputContext.state.key === InputEventRecordKey.RIGHT) {
data.actors[0].movement.targetPosition.x++;
}
if (inputContext.state.key === InputEventRecordKey.UP) {
data.actors[0].movement.targetPosition.y--;
}
if (inputContext.state.key === InputEventRecordKey.DOWN) {
data.actors[0].movement.targetPosition.y++;
}

updateData(data);
}, [updateData, inputContext.state.key]);

return null;
};
3 changes: 2 additions & 1 deletion clients/player-client/src/core/Keyboard/Keyboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useEffect, useRef } from 'react';
import useHandleInput from './useHandleInput';
import { useInputContext } from '../../context/Input/useInputContext';
import { InputActionType } from '../../context/Input/InputActionType.type';
import { InputEventRecordKey } from '../../dtos/Player/InputEventRecordKey.type';

export type KeyboardProps = {
config?: string;
Expand All @@ -26,7 +27,7 @@ export const Keyboard: React.FC<KeyboardProps> = () => {
payload: { key: input[0]?.key, timestamp: input[0]?.timestamp },
});

if (input[0]?.key === 'debug') {
if (input[0]?.key === InputEventRecordKey.DEBUG) {
inputContextRef.current.dispatch({
type: InputActionType.SET_DEBUG,
payload: { debug: !inputContextRef.current.state.debug },
Expand Down
25 changes: 11 additions & 14 deletions clients/player-client/src/core/Keyboard/keyBindings.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
// keyboard
import { InputEventRecordKey } from '../../dtos/Player/InputEventRecordKey.type';

export const keyboardBindings = {
up: 'w',
down: 's',
left: 'a',
right: 'd',
jump: ' ',
debug: 'p',
select: 'Enter',
back: 'u',
pause: 'Escape',
[InputEventRecordKey.UP]: 'w',
[InputEventRecordKey.DOWN]: 's',
[InputEventRecordKey.LEFT]: 'a',
[InputEventRecordKey.RIGHT]: 'd',
[InputEventRecordKey.JUMP]: ' ',
[InputEventRecordKey.DEBUG]: 'p',
[InputEventRecordKey.SELECT]: 'Enter',
[InputEventRecordKey.BACK]: 'u',
[InputEventRecordKey.PAUSE]: 'Escape',
};

// other inputs will be touch and based
// may need to display buttons on screen for touch
// move by clicking a tile..
29 changes: 16 additions & 13 deletions clients/player-client/src/core/Keyboard/useHandleInput.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,38 @@
import { useState, useEffect } from 'react';
import { keyboardBindings } from './keyBindings';
import { DateTime } from 'luxon';
import { PlayerInputRecord } from '../../core/types';
import { InputEventRecord } from '../../dtos/Player/InputEventRecord.dto';
import { InputEventRecordKey } from '../../dtos/Player/InputEventRecordKey.type';

export default function useHandleInput(): PlayerInputRecord[] | null {
const [inputState, setInputState] = useState<PlayerInputRecord[] | null>(
null,
);
export default function useHandleInput(): InputEventRecord[] | null {
const [inputState, setInputState] = useState<InputEventRecord[] | null>(null);
const pressedKeys = new Set<string>();

useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === ' ') {
event.preventDefault();
}

// TODO ignore select already pressed keys
if (pressedKeys.has(event.key)) {
return; // Ignore if the key is already pressed
return;
}
pressedKeys.add(event.key);

const newInputRecords: PlayerInputRecord[] = [];
const newInputRecords: InputEventRecord[] = [];

// Handle different key strokes
Object.entries(keyboardBindings).forEach(([direction, key]) => {
if (event.key === key) {
// Collect key press for the given direction
newInputRecords.push({
key: direction,
timestamp: DateTime.now(),
});
const inputEventRecord = new InputEventRecord();
inputEventRecord.key = direction as InputEventRecordKey;
inputEventRecord.timestamp = DateTime.now();
newInputRecords.push(inputEventRecord);
}
});

const newState: PlayerInputRecord[] = [];
const newState: InputEventRecord[] = [];
newInputRecords.forEach(record => {
newState.unshift(record);
});
Expand Down
1 change: 0 additions & 1 deletion clients/player-client/src/core/types/index.ts

This file was deleted.

This file was deleted.

50 changes: 50 additions & 0 deletions clients/player-client/src/dtos/Actor/Actor.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import {
IsUrl,
IsEnum,
IsString,
IsNumber,
Min,
ValidateNested,
IsOptional,
} from 'class-validator';
import { ActorAnimation } from './ActorAnimation.dto';
import { Transform, Type } from 'class-transformer';
import { ActorMovement } from './ActorMovement.dto';
import { ActorState } from '../../core/IsometricCanvas/types/ActorState.type';
import { DateTime } from 'luxon';

export class Actor {
@IsString()
actorId: string;

@IsOptional()
@IsNumber()
@Min(0)
height?: number;

@ValidateNested()
@Type(() => ActorMovement)
movement: ActorMovement;

@IsEnum(ActorState)
currentState?: ActorState;

@ValidateNested()
@Type(() => ActorAnimation)
animation: ActorAnimation;

@Transform(({ value }) => {
return Object.keys(value).reduce(
(acc, key) => {
acc[key] = value[key];
return acc;
},
{} as Record<string, string>,
);
})
@IsString({ each: true })
@IsUrl({}, { each: true })
spriteMapRegistry: Record<string, string>;

lastUpdated?: DateTime; // Timestamp for when the actor's data was last updated
}
31 changes: 31 additions & 0 deletions clients/player-client/src/dtos/Actor/ActorAnimation.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { IsBoolean, IsDateString, IsString, IsNumber } from 'class-validator';
import { DateTime, Duration } from 'luxon';

export class ActorAnimation {
@IsNumber()
startingFrame?: number;

@IsNumber()
totalFrames: number;

@IsNumber()
animationDuration?: number;

// @IsNumber()
frameDuration: Duration;

@IsBoolean()
isAnimating?: false;

@IsDateString()
startTime: DateTime;

@IsString()
currentAnimation?: string;

@IsNumber()
currentFrame?: number;

startTimestamp?: DateTime; // Time when the animation started
endTimestamp?: DateTime; // Time when the animation should end
}
30 changes: 30 additions & 0 deletions clients/player-client/src/dtos/Actor/ActorMovement.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { IsBoolean, ValidateNested, IsDateString } from 'class-validator';
import { Type } from 'class-transformer';
import { Duration, DateTime } from 'luxon';
import { Coordinate3d } from '../Coordinate3d.dto';

export class ActorMovement {
@IsBoolean()
isInMotion: boolean;

@ValidateNested()
@Type(() => Coordinate3d)
currentPosition: Coordinate3d;

@ValidateNested()
@Type(() => Coordinate3d)
targetPosition: Coordinate3d;

// TODO type for duration

movementDuration?: Duration; // Duration of the movement (in seconds) ???

@IsBoolean()
targetPositionReached: boolean;

@IsDateString()
startTimestamp: DateTime;

@IsDateString()
endTimestamp?: DateTime;
}
12 changes: 12 additions & 0 deletions clients/player-client/src/dtos/Coordinate3d.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { IsNumber } from 'class-validator';

export class Coordinate3d {
@IsNumber()
x: number;

@IsNumber()
y: number;

@IsNumber()
z: number;
}
10 changes: 10 additions & 0 deletions clients/player-client/src/dtos/Dialogue.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { IsString, Length } from 'class-validator';

export class Dialogue {
@IsString()
actorId: string;

@IsString()
@Length(1, 1000)
text: string;
}
42 changes: 42 additions & 0 deletions clients/player-client/src/dtos/GameState.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { IsString, IsUrl, IsArray, ValidateNested } from 'class-validator';
import { Transform, Type } from 'class-transformer';
import { Properties } from './Properties.dto';
import { Actor } from './Actor/Actor.dto';
import { Dialogue } from './Dialogue.dto';
import { Coordinate3d } from './Coordinate3d.dto';

export class GameState {
@ValidateNested()
@Type(() => Properties)
properties: Properties;

@IsArray()
@ValidateNested({ each: true })
@Type(() => Actor)
actors: Actor[];

@IsArray()
@ValidateNested({ each: true })
@Type(() => Dialogue)
dialogues: Dialogue[];

@Transform(({ value }) => {
return Object.keys(value).reduce(
(acc, key) => {
acc[key] = value[key];
return acc;
},
{} as Record<string, string>,
);
})
@IsString({ each: true })
@IsUrl({}, { each: true })
spriteMapRegistry: Record<string, string>;

// TODO add type for grid
grid: string[][][];

@ValidateNested()
@Type(() => Coordinate3d)
cameraPosition: Coordinate3d;
}
10 changes: 10 additions & 0 deletions clients/player-client/src/dtos/Player/InputEventRecord.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { IsEnum } from 'class-validator';
import { DateTime } from 'luxon';
import { InputEventRecordKey } from './InputEventRecordKey.type';

export class InputEventRecord {
@IsEnum(InputEventRecordKey)
key: InputEventRecordKey;

timestamp: DateTime;
}
11 changes: 11 additions & 0 deletions clients/player-client/src/dtos/Player/InputEventRecordKey.type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export enum InputEventRecordKey {
'UP' = 'UP',
'DOWN' = 'DOWN',
'LEFT' = 'LEFT',
'RIGHT' = 'RIGHT',
'JUMP' = 'JUMP',
'DEBUG' = 'DEBUG',
'SELECT' = 'SELECT',
'BACK' = 'BACK',
'PAUSE' = 'PAUSE',
}
Loading

0 comments on commit 645a9a1

Please sign in to comment.