Refactor
This commit is contained in:
parent
1ce961d6c2
commit
99cdb62928
76 changed files with 340 additions and 433 deletions
|
|
@ -1,6 +1,6 @@
|
|||
import { Command, CommandReceiver, serialize, TransportEvents } from 'shared';
|
||||
|
||||
export class CommandReceiverSocket extends CommandReceiver {
|
||||
export class CommandSocket extends CommandReceiver {
|
||||
constructor(private readonly socket: SocketIOClient.Socket) {
|
||||
super();
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import { CommandGenerator, SecondaryActionCommand, TernaryActionCommand } from 'shared';
|
||||
import { Game } from '../../game';
|
||||
|
||||
export class MouseListener extends CommandGenerator {
|
||||
constructor(target: HTMLElement, private readonly game: Game) {
|
||||
super();
|
||||
|
||||
target.addEventListener('mousedown', (event: MouseEvent) => {
|
||||
const position = this.positionFromEvent(event);
|
||||
|
||||
if (event.button == 0) {
|
||||
this.sendCommandToSubscribers(new SecondaryActionCommand(position));
|
||||
}
|
||||
});
|
||||
|
||||
target.addEventListener('contextmenu', (event: MouseEvent) => {
|
||||
event.preventDefault();
|
||||
const position = this.positionFromEvent(event);
|
||||
this.sendCommandToSubscribers(new TernaryActionCommand(position));
|
||||
});
|
||||
}
|
||||
|
||||
private positionFromEvent(event: MouseEvent): vec2 {
|
||||
return this.game.displayToWorldCoordinates(
|
||||
vec2.fromValues(event.clientX, event.clientY),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import {
|
||||
CommandGenerator,
|
||||
SecondaryActionCommand,
|
||||
MoveActionCommand,
|
||||
last,
|
||||
} from 'shared';
|
||||
import { Game } from '../../game';
|
||||
|
||||
export class TouchJoystickListener extends CommandGenerator {
|
||||
private readonly deadZone = 8;
|
||||
private readonly deltaScaling = 0.4;
|
||||
|
||||
private joystick: HTMLElement;
|
||||
private joystickButton: HTMLElement;
|
||||
|
||||
private isJoystickActive = false;
|
||||
private touchStartPosition!: vec2;
|
||||
|
||||
constructor(
|
||||
target: HTMLElement,
|
||||
private overlay: HTMLElement,
|
||||
private readonly game: Game,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.joystick = document.createElement('div');
|
||||
this.joystick.className = 'joystick';
|
||||
this.joystickButton = document.createElement('div');
|
||||
this.joystick.appendChild(this.joystickButton);
|
||||
|
||||
target.addEventListener('touchstart', (event: TouchEvent) => {
|
||||
event.preventDefault();
|
||||
if (this.isJoystickActive) {
|
||||
const center = vec2.fromValues(
|
||||
last(event.touches)!.clientX,
|
||||
last(event.touches)!.clientY,
|
||||
);
|
||||
this.sendCommandToSubscribers(
|
||||
new SecondaryActionCommand(this.game.displayToWorldCoordinates(center)),
|
||||
);
|
||||
} else {
|
||||
this.touchStartPosition = vec2.fromValues(
|
||||
event.touches[0].clientX,
|
||||
event.touches[0].clientY,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
target.addEventListener('touchmove', (event: TouchEvent) => {
|
||||
event.preventDefault();
|
||||
|
||||
const touchPosition = vec2.fromValues(
|
||||
event.touches[0].clientX,
|
||||
event.touches[0].clientY,
|
||||
);
|
||||
|
||||
const delta = vec2.subtract(vec2.create(), touchPosition, this.touchStartPosition);
|
||||
vec2.scale(delta, delta, this.deltaScaling);
|
||||
const deltaLength = vec2.length(delta);
|
||||
|
||||
if (!this.isJoystickActive && deltaLength > this.deadZone) {
|
||||
this.isJoystickActive = true;
|
||||
this.overlay.appendChild(this.joystick);
|
||||
this.joystickButton.style.transform = `translateX(-50%) translateY(-50%)`;
|
||||
this.joystick.style.transform = `translateX(${this.touchStartPosition.x}px) translateY(${this.touchStartPosition.y}px) translateX(-50%) translateY(-50%)`;
|
||||
}
|
||||
|
||||
const maxLength = 20;
|
||||
vec2.scale(delta, delta, Math.min(1, maxLength / deltaLength));
|
||||
this.joystickButton.style.transform = `translateX(${delta.x}px) translateY(${delta.y}px) translateX(-50%) translateY(-50%)`;
|
||||
|
||||
vec2.set(delta, delta.x, -delta.y);
|
||||
if (deltaLength > this.deadZone) {
|
||||
this.sendCommandToSubscribers(
|
||||
new MoveActionCommand(vec2.normalize(delta, delta)),
|
||||
);
|
||||
} else {
|
||||
this.sendCommandToSubscribers(new MoveActionCommand(vec2.create()));
|
||||
}
|
||||
});
|
||||
|
||||
target.addEventListener('touchend', (event: TouchEvent) => {
|
||||
event.preventDefault();
|
||||
|
||||
if (!this.isJoystickActive) {
|
||||
const center = vec2.fromValues(
|
||||
event.changedTouches[0].clientX,
|
||||
event.changedTouches[0].clientY,
|
||||
);
|
||||
this.sendCommandToSubscribers(
|
||||
new SecondaryActionCommand(this.game.displayToWorldCoordinates(center)),
|
||||
);
|
||||
} else if (event.touches.length === 0) {
|
||||
this.isJoystickActive = false;
|
||||
this.joystick.parentElement?.removeChild(this.joystick);
|
||||
this.sendCommandToSubscribers(new MoveActionCommand(vec2.create()));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -4,22 +4,29 @@ import { CommandGenerator, MoveActionCommand } from 'shared';
|
|||
export class KeyboardListener extends CommandGenerator {
|
||||
private keysDown: Set<string> = new Set();
|
||||
|
||||
constructor(target: HTMLElement) {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
target.addEventListener('keydown', (event: KeyboardEvent) => {
|
||||
const key = this.normalize(event.key);
|
||||
this.keysDown.add(key);
|
||||
this.generateCommands();
|
||||
});
|
||||
|
||||
target.addEventListener('keyup', (event: KeyboardEvent) => {
|
||||
const key = this.normalize(event.key);
|
||||
this.keysDown.delete(key);
|
||||
this.generateCommands();
|
||||
});
|
||||
addEventListener('keydown', this.keyDownListener);
|
||||
addEventListener('keyup', this.keyUpListener);
|
||||
addEventListener('blur', this.blurListener);
|
||||
}
|
||||
|
||||
private keyDownListener = (event: KeyboardEvent) => {
|
||||
this.keysDown.add(event.key.toLowerCase());
|
||||
this.generateCommands();
|
||||
};
|
||||
|
||||
private keyUpListener = (event: KeyboardEvent) => {
|
||||
this.keysDown.delete(event.key.toLowerCase());
|
||||
this.generateCommands();
|
||||
};
|
||||
|
||||
private blurListener = () => {
|
||||
this.keysDown.clear();
|
||||
this.generateCommands();
|
||||
};
|
||||
|
||||
private generateCommands() {
|
||||
const up = ~~(
|
||||
this.keysDown.has('w') ||
|
||||
|
|
@ -34,10 +41,13 @@ export class KeyboardListener extends CommandGenerator {
|
|||
if (vec2.squaredLength(movement) > 0) {
|
||||
vec2.normalize(movement, movement);
|
||||
}
|
||||
|
||||
this.sendCommandToSubscribers(new MoveActionCommand(movement));
|
||||
}
|
||||
|
||||
private normalize(key: string): string {
|
||||
return key.toLowerCase();
|
||||
public destroy() {
|
||||
removeEventListener('keydown', this.keyDownListener);
|
||||
removeEventListener('keyup', this.keyUpListener);
|
||||
removeEventListener('blur', this.blurListener);
|
||||
}
|
||||
}
|
||||
38
frontend/src/scripts/commands/mouse-listener.ts
Normal file
38
frontend/src/scripts/commands/mouse-listener.ts
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import { CommandGenerator, PrimaryActionCommand, SecondaryActionCommand } from 'shared';
|
||||
import { Game } from '../game';
|
||||
|
||||
export class MouseListener extends CommandGenerator {
|
||||
constructor(private readonly game: Game) {
|
||||
super();
|
||||
|
||||
addEventListener('mousedown', this.mouseDownListener);
|
||||
addEventListener('contextmenu', this.contextMenuListener);
|
||||
}
|
||||
|
||||
private mouseDownListener = (event: MouseEvent) => {
|
||||
const position = this.positionFromEvent(event);
|
||||
|
||||
if (event.button === 0) {
|
||||
this.sendCommandToSubscribers(new PrimaryActionCommand(position));
|
||||
}
|
||||
};
|
||||
|
||||
private contextMenuListener = (event: MouseEvent) => {
|
||||
event.preventDefault();
|
||||
|
||||
const position = this.positionFromEvent(event);
|
||||
this.sendCommandToSubscribers(new SecondaryActionCommand(position));
|
||||
};
|
||||
|
||||
private positionFromEvent(event: MouseEvent): vec2 {
|
||||
return this.game.displayToWorldCoordinates(
|
||||
vec2.fromValues(event.clientX, event.clientY),
|
||||
);
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
removeEventListener('mousedown', this.mouseDownListener);
|
||||
removeEventListener('contextmenu', this.contextMenuListener);
|
||||
}
|
||||
}
|
||||
104
frontend/src/scripts/commands/touch-listener.ts
Normal file
104
frontend/src/scripts/commands/touch-listener.ts
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import {
|
||||
CommandGenerator,
|
||||
SecondaryActionCommand,
|
||||
MoveActionCommand,
|
||||
last,
|
||||
} from 'shared';
|
||||
import { Game } from '../game';
|
||||
|
||||
export class TouchListener extends CommandGenerator {
|
||||
private static readonly deadZone = 8;
|
||||
private static readonly deltaScaling = 0.4;
|
||||
|
||||
private joystick: HTMLElement;
|
||||
private joystickButton: HTMLElement;
|
||||
private isJoystickActive = false;
|
||||
private touchStartPosition!: vec2;
|
||||
|
||||
constructor(private overlay: HTMLElement, private readonly game: Game) {
|
||||
super();
|
||||
|
||||
this.joystick = document.createElement('div');
|
||||
this.joystick.className = 'joystick';
|
||||
this.joystickButton = document.createElement('div');
|
||||
this.joystick.appendChild(this.joystickButton);
|
||||
|
||||
addEventListener('touchstart', this.touchStartListener);
|
||||
addEventListener('touchmove', this.touchMoveListener);
|
||||
addEventListener('touchend', this.touchEndListener);
|
||||
}
|
||||
|
||||
private touchStartListener = (event: TouchEvent) => {
|
||||
event.preventDefault();
|
||||
if (this.isJoystickActive) {
|
||||
const center = vec2.fromValues(
|
||||
last(event.touches)!.clientX,
|
||||
last(event.touches)!.clientY,
|
||||
);
|
||||
this.sendCommandToSubscribers(
|
||||
new SecondaryActionCommand(this.game.displayToWorldCoordinates(center)),
|
||||
);
|
||||
} else {
|
||||
this.touchStartPosition = vec2.fromValues(
|
||||
event.touches[0].clientX,
|
||||
event.touches[0].clientY,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
private touchMoveListener = (event: TouchEvent) => {
|
||||
event.preventDefault();
|
||||
|
||||
const touchPosition = vec2.fromValues(
|
||||
event.touches[0].clientX,
|
||||
event.touches[0].clientY,
|
||||
);
|
||||
|
||||
const delta = vec2.subtract(vec2.create(), touchPosition, this.touchStartPosition);
|
||||
vec2.scale(delta, delta, TouchListener.deltaScaling);
|
||||
const deltaLength = vec2.length(delta);
|
||||
|
||||
if (!this.isJoystickActive && deltaLength > TouchListener.deadZone) {
|
||||
this.isJoystickActive = true;
|
||||
this.overlay.appendChild(this.joystick);
|
||||
this.joystickButton.style.transform = `translateX(-50%) translateY(-50%)`;
|
||||
this.joystick.style.transform = `translateX(${this.touchStartPosition.x}px) translateY(${this.touchStartPosition.y}px) translateX(-50%) translateY(-50%)`;
|
||||
}
|
||||
|
||||
const maxLength = 20;
|
||||
vec2.scale(delta, delta, Math.min(1, maxLength / deltaLength));
|
||||
this.joystickButton.style.transform = `translateX(${delta.x}px) translateY(${delta.y}px) translateX(-50%) translateY(-50%)`;
|
||||
|
||||
vec2.set(delta, delta.x, -delta.y);
|
||||
if (deltaLength > TouchListener.deadZone) {
|
||||
this.sendCommandToSubscribers(new MoveActionCommand(vec2.normalize(delta, delta)));
|
||||
} else {
|
||||
this.sendCommandToSubscribers(new MoveActionCommand(vec2.create()));
|
||||
}
|
||||
};
|
||||
|
||||
private touchEndListener = (event: TouchEvent) => {
|
||||
event.preventDefault();
|
||||
|
||||
if (!this.isJoystickActive) {
|
||||
const center = vec2.fromValues(
|
||||
event.changedTouches[0].clientX,
|
||||
event.changedTouches[0].clientY,
|
||||
);
|
||||
this.sendCommandToSubscribers(
|
||||
new SecondaryActionCommand(this.game.displayToWorldCoordinates(center)),
|
||||
);
|
||||
} else if (event.touches.length === 0) {
|
||||
this.isJoystickActive = false;
|
||||
this.joystick.parentElement?.removeChild(this.joystick);
|
||||
this.sendCommandToSubscribers(new MoveActionCommand(vec2.create()));
|
||||
}
|
||||
};
|
||||
|
||||
public destroy() {
|
||||
removeEventListener('touchstart', this.touchStartListener);
|
||||
removeEventListener('touchmove', this.touchMoveListener);
|
||||
removeEventListener('touchend', this.touchEndListener);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import { Command } from 'shared';
|
||||
|
||||
export class MoveToCommand extends Command {
|
||||
public constructor(public readonly position: vec2) {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
import { Renderer } from 'sdf-2d';
|
||||
import { Command } from 'shared';
|
||||
|
||||
export class RenderCommand extends Command {
|
||||
public constructor(public readonly renderer: Renderer) {
|
||||
super();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue