summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
authorMike Vink <mike1994vink@gmail.com>2021-07-23 22:09:20 +0200
committerMike Vink <mike1994vink@gmail.com>2021-07-23 22:09:20 +0200
commit4692175208a8f0526c6e0881aa0e51345c5574fb (patch)
tree4753635cc27e319933384b703b357ee86318a3fd /client
parenteaff86546eca516d51c27eb9d63ea33a96576e90 (diff)
feat(): start ui
Diffstat (limited to 'client')
-rw-r--r--client/dist/assets/images/menupicker.pngbin0 -> 1039 bytes
-rw-r--r--client/dist/assets/images/menupicker.svg202
-rw-r--r--client/dist/assets/images/pMenu.pngbin0 -> 56628 bytes
-rw-r--r--client/src/akkamon/GameConfig.ts19
-rw-r--r--client/src/akkamon/client/AkkamonClient.ts2
-rw-r--r--client/src/akkamon/client/Client.ts92
-rw-r--r--client/src/akkamon/client/Events.ts2
-rw-r--r--client/src/akkamon/client/Socket.ts6
-rw-r--r--client/src/akkamon/render/DirectionToAnimation.ts15
-rw-r--r--client/src/akkamon/render/GridControls.ts2
-rw-r--r--client/src/akkamon/render/engine/AkkamonEngine.ts7
-rw-r--r--client/src/akkamon/render/engine/GridPhysics.ts37
-rw-r--r--client/src/akkamon/render/engine/RemotePlayerEngine.ts21
-rw-r--r--client/src/akkamon/render/model/PlayerSprite.ts13
-rw-r--r--client/src/akkamon/render/model/RemotePlayerSprite.ts16
-rw-r--r--client/src/akkamon/scenes/AkkamonWorldScene.ts23
-rw-r--r--client/src/akkamon/scenes/BootScene.ts39
-rw-r--r--client/src/akkamon/scenes/DemoScene.ts132
-rw-r--r--client/src/akkamon/scenes/Pack.ts1
-rw-r--r--client/src/akkamon/scenes/UIElement.ts3
-rw-r--r--client/src/akkamon/scenes/UIScene.ts119
-rw-r--r--client/src/app.ts37
22 files changed, 596 insertions, 192 deletions
diff --git a/client/dist/assets/images/menupicker.png b/client/dist/assets/images/menupicker.png
new file mode 100644
index 0000000..e8bc3e2
--- /dev/null
+++ b/client/dist/assets/images/menupicker.png
Binary files differ
diff --git a/client/dist/assets/images/menupicker.svg b/client/dist/assets/images/menupicker.svg
new file mode 100644
index 0000000..9cf911f
--- /dev/null
+++ b/client/dist/assets/images/menupicker.svg
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="150.52913"
+ height="225.5291"
+ viewBox="0 0 39.8275 59.671237"
+ version="1.1"
+ id="svg5"
+ inkscape:version="1.1 (c4e8f9ed74, 2021-05-24)"
+ sodipodi:docname="menupicker.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="true"
+ inkscape:document-units="mm"
+ showgrid="true"
+ width="200px"
+ borderlayer="true"
+ inkscape:showpageshadow="false"
+ inkscape:snap-global="true"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="false"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-others="false"
+ units="px"
+ inkscape:zoom="2.8284271"
+ inkscape:cx="78.312076"
+ inkscape:cy="99.52528"
+ inkscape:window-width="1594"
+ inkscape:window-height="894"
+ inkscape:window-x="0"
+ inkscape:window-y="1440"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer1"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0">
+ <inkscape:grid
+ type="xygrid"
+ id="grid21"
+ spacingx="6.6145834"
+ spacingy="6.6145834"
+ empspacing="1"
+ dotted="true"
+ originx="-396.80503"
+ originy="-350.50289" />
+ </sodipodi:namedview>
+ <defs
+ id="defs2">
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath1350">
+ <rect
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.140441;stroke-dasharray:0.140441, 0.702204;stroke-opacity:1;marker-start:none;marker-end:none"
+ id="rect1352"
+ width="72.760414"
+ height="72.760414"
+ x="13.229166"
+ y="-79.375" />
+ </clipPath>
+ </defs>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-396.80501,-350.50293)">
+ <g
+ id="g1950"
+ style="stroke:#000000;stroke-opacity:1"
+ transform="translate(978.95832,165.3646)">
+ <rect
+ style="fill:#000000;stroke:#000000;stroke-width:0.14;stroke-opacity:1"
+ id="rect1624"
+ width="39.6875"
+ height="6.614583"
+ x="-582.08331"
+ y="211.66666" />
+ <rect
+ style="fill:#000000;stroke:#000000;stroke-width:0.14;stroke-opacity:1"
+ id="rect1628"
+ width="26.458332"
+ height="6.614583"
+ x="-582.08331"
+ y="205.05208" />
+ <rect
+ style="fill:#000000;stroke:#000000;stroke-width:0.14;stroke-opacity:1"
+ id="rect1630"
+ width="19.84375"
+ height="6.614583"
+ x="-582.08331"
+ y="198.43748" />
+ <rect
+ style="fill:#000000;stroke:#000000;stroke-width:0.14;stroke-opacity:1"
+ id="rect1632"
+ width="13.229166"
+ height="6.614583"
+ x="-582.08331"
+ y="191.82291" />
+ <rect
+ style="fill:#000000;stroke:#000000;stroke-width:0.14;stroke-opacity:1"
+ id="rect1634"
+ width="6.614583"
+ height="6.614583"
+ x="-582.08331"
+ y="185.20833" />
+ <rect
+ style="fill:#000000;stroke:#000000;stroke-width:0.14;stroke-opacity:1"
+ id="rect1636"
+ width="26.458332"
+ height="6.614583"
+ x="-582.08331"
+ y="218.28123" />
+ <rect
+ style="fill:#000000;stroke:#000000;stroke-width:0.14;stroke-opacity:1"
+ id="rect1638"
+ width="19.84375"
+ height="6.614583"
+ x="-582.08331"
+ y="224.89583" />
+ <rect
+ style="fill:#000000;stroke:#000000;stroke-width:0.14;stroke-opacity:1"
+ id="rect1640"
+ width="13.229166"
+ height="6.614583"
+ x="-582.08331"
+ y="231.51041" />
+ <rect
+ style="fill:#000000;stroke:#000000;stroke-width:0.14;stroke-opacity:1"
+ id="rect1642"
+ width="6.614583"
+ height="6.614583"
+ x="-582.08331"
+ y="238.12498" />
+ <rect
+ style="fill:#000000;stroke:#000000;stroke-width:0.14;stroke-opacity:1"
+ id="rect1757"
+ width="6.614583"
+ height="6.614583"
+ x="-555.625"
+ y="218.28123" />
+ <rect
+ style="fill:#000000;stroke:#000000;stroke-width:0.14;stroke-opacity:1"
+ id="rect1759"
+ width="6.614583"
+ height="6.614583"
+ x="-562.23956"
+ y="224.89583" />
+ <rect
+ style="fill:#000000;stroke:#000000;stroke-width:0.14;stroke-opacity:1"
+ id="rect1761"
+ width="6.614583"
+ height="6.614583"
+ x="-568.85419"
+ y="231.51041" />
+ <rect
+ style="fill:#000000;stroke:#000000;stroke-width:0.14;stroke-opacity:1"
+ id="rect1763"
+ width="6.614583"
+ height="6.614583"
+ x="-575.46875"
+ y="238.12498" />
+ <rect
+ style="fill:#000000;stroke:#000000;stroke-width:0.14;stroke-opacity:1"
+ id="rect1765"
+ width="6.614583"
+ height="6.614583"
+ x="-555.625"
+ y="205.05208" />
+ <rect
+ style="fill:#000000;stroke:#000000;stroke-width:0.14;stroke-opacity:1"
+ id="rect1767"
+ width="6.614583"
+ height="6.614583"
+ x="-562.23956"
+ y="198.43748" />
+ <rect
+ style="fill:#000000;stroke:#000000;stroke-width:0.14;stroke-opacity:1"
+ id="rect1769"
+ width="6.614583"
+ height="6.614583"
+ x="-568.85419"
+ y="191.82291" />
+ <rect
+ style="fill:#000000;stroke:#000000;stroke-width:0.14;stroke-opacity:1"
+ id="rect1771"
+ width="6.614583"
+ height="6.614583"
+ x="-575.46875"
+ y="185.20833" />
+ </g>
+ </g>
+</svg>
diff --git a/client/dist/assets/images/pMenu.png b/client/dist/assets/images/pMenu.png
new file mode 100644
index 0000000..715741b
--- /dev/null
+++ b/client/dist/assets/images/pMenu.png
Binary files differ
diff --git a/client/src/akkamon/GameConfig.ts b/client/src/akkamon/GameConfig.ts
new file mode 100644
index 0000000..11fc26a
--- /dev/null
+++ b/client/src/akkamon/GameConfig.ts
@@ -0,0 +1,19 @@
+import {
+ UIScene
+} from './scenes/UIScene';
+import {
+ DemoScene
+} from './scenes/DemoScene';
+import {
+ BootScene
+} from './scenes/BootScene';
+
+
+export const gameConfig: Phaser.Types.Core.GameConfig & Phaser.Types.Core.RenderConfig = {
+ type: Phaser.AUTO,
+ backgroundColor: '#125555',
+ width: 800,
+ height: 600,
+ pixelArt: true,
+ scene: [BootScene, DemoScene, UIScene]
+};
diff --git a/client/src/akkamon/client/AkkamonClient.ts b/client/src/akkamon/client/AkkamonClient.ts
new file mode 100644
index 0000000..db84385
--- /dev/null
+++ b/client/src/akkamon/client/AkkamonClient.ts
@@ -0,0 +1,2 @@
+export interface AkkamonClient {
+}
diff --git a/client/src/akkamon/client/Client.ts b/client/src/akkamon/client/Client.ts
index 8f9115f..b0caa98 100644
--- a/client/src/akkamon/client/Client.ts
+++ b/client/src/akkamon/client/Client.ts
@@ -1,23 +1,39 @@
-import type AkkamonSession from './session';
-import { Socket } from './socket';
-import type { GridPhysics } from './GridPhysics';
-import type { RemotePlayerEngine } from './RemotePlayerEngine';
+import type AkkamonSession from './Session';
+import { Socket } from './Socket';
+
+import { PlayerSprite } from '../render/model/PlayerSprite';
+import { GridPhysics } from '../render/engine/GridPhysics';
+import { GridControls } from '../render/GridControls';
+
+import { RemotePlayerEngine } from '../render/engine/RemotePlayerEngine';
+
+import type { AkkamonClient } from './AkkamonClient';
+
+import type { AkkamonWorldScene } from '../scenes/AkkamonWorldScene';
+
+import { DirectionToAnimation } from '../render/DirectionToAnimation';
+import { Direction } from '../render/Direction';
import {
EventType,
HeartBeatReplyEvent,
IncomingEvent,
AkkamonEvent,
-} from './events';
+} from './Events';
-export class Client
+export class Client implements AkkamonClient
{
private session: AkkamonSession;
+
+ private scene?: AkkamonWorldScene;
private gridPhysics?: GridPhysics;
+ private gridControls?: GridControls;
+
private remotePlayerEngine?: RemotePlayerEngine;
+
constructor(
url: string
) {
@@ -47,8 +63,68 @@ export class Client
}
}
- setRemotePlayerEngine(engine: RemotePlayerEngine) {
- this.remotePlayerEngine = engine;
+ updateScene(delta: number): void {
+ this.gridControls!.update();
+ this.gridPhysics!.update(delta);
+ this.remotePlayerEngine!.update(delta);
+ }
+
+ requestInitPlayerSprite(
+ scene: AkkamonWorldScene
+ ): void {
+
+ this.scene = scene;
+
+ let playerSprite = new PlayerSprite({
+ scene: scene,
+ tilePos: new Phaser.Math.Vector2(scene.spawnPointTilePos!),
+ texture: scene.textures.get("atlas"),
+ frame: "misa-front"
+ });
+
+ this.gridPhysics = new GridPhysics(
+ playerSprite,
+ scene.map!
+ );
+
+ this.gridControls = new GridControls(
+ scene.input,
+ this.gridPhysics
+ );
+
+ this.remotePlayerEngine = new RemotePlayerEngine(
+ scene
+ );
+ this.initAnimation(scene, playerSprite);
+ }
+
+ private initAnimation(
+ scene: AkkamonWorldScene,
+ player: PlayerSprite
+ ): void {
+
+ this.createPlayerAnimation(scene, Direction.LEFT, 0, 3);
+ this.createPlayerAnimation(scene, Direction.RIGHT, 0, 3);
+ this.createPlayerAnimation(scene, Direction.UP, 0, 3);
+ this.createPlayerAnimation(scene, Direction.DOWN, 0, 3);
+
+ // Phaser supports multiple cameras, but you can access the default camera like this:
+ const camera = scene.cameras.main;
+ camera.startFollow(player);
+ camera.roundPixels = true;
+ camera.setBounds(0, 0, scene.map!.widthInPixels, scene.map!.heightInPixels);
+ }
+
+ private createPlayerAnimation(scene: AkkamonWorldScene, direction: Direction, start: number, end: number) {
+ let characterAnimations = DirectionToAnimation.directionToAnimation['misa'];
+
+ scene.anims.create({
+ key: direction, // "misa-left-walk",
+ frames: scene.anims.generateFrameNames("atlas", { prefix: characterAnimations[direction] + ".", start: start, end: end, zeroPad: 3 }),
+ frameRate: 10,
+ repeat: -1
+ });
+
}
}
diff --git a/client/src/akkamon/client/Events.ts b/client/src/akkamon/client/Events.ts
index 1954fd7..830ac23 100644
--- a/client/src/akkamon/client/Events.ts
+++ b/client/src/akkamon/client/Events.ts
@@ -1,5 +1,5 @@
import Phaser from 'phaser';
-import type { Direction } from './Direction';
+import type { Direction } from '../render/Direction';
export enum EventType {
HEART_BEAT = "HeartBeat",
diff --git a/client/src/akkamon/client/Socket.ts b/client/src/akkamon/client/Socket.ts
index 4e83f89..e0c3e0c 100644
--- a/client/src/akkamon/client/Socket.ts
+++ b/client/src/akkamon/client/Socket.ts
@@ -1,9 +1,9 @@
import Phaser from 'phaser';
-import type { Client } from './client'
-import type AkkamonSession from './session'
+import type { Client } from './Client'
+import type AkkamonSession from './Session'
import {
PlayerRegistrationEvent
-} from './events';
+} from './Events';
export class Socket extends WebSocket implements AkkamonSession
{
diff --git a/client/src/akkamon/render/DirectionToAnimation.ts b/client/src/akkamon/render/DirectionToAnimation.ts
new file mode 100644
index 0000000..0e3969d
--- /dev/null
+++ b/client/src/akkamon/render/DirectionToAnimation.ts
@@ -0,0 +1,15 @@
+import { Direction } from './Direction';
+
+export class DirectionToAnimation {
+ static readonly directionToAnimation: {
+ [name: string]: { [key in Direction]: string }
+ } = {misa:
+ {
+ [Direction.UP]: "misa-back-walk",
+ [Direction.DOWN]: "misa-front-walk",
+ [Direction.LEFT]: "misa-left-walk",
+ [Direction.RIGHT]: "misa-right-walk",
+ [Direction.NONE]: "misa-front-walk"
+ }
+ }
+}
diff --git a/client/src/akkamon/render/GridControls.ts b/client/src/akkamon/render/GridControls.ts
index d7feef2..40f3789 100644
--- a/client/src/akkamon/render/GridControls.ts
+++ b/client/src/akkamon/render/GridControls.ts
@@ -1,5 +1,5 @@
import { Direction } from './Direction';
-import type { GridPhysics } from './GridPhysics';
+import type { GridPhysics } from '../render/engine/GridPhysics';
export class GridControls {
private cursors: Phaser.Types.Input.Keyboard.CursorKeys;
diff --git a/client/src/akkamon/render/engine/AkkamonEngine.ts b/client/src/akkamon/render/engine/AkkamonEngine.ts
new file mode 100644
index 0000000..14dae86
--- /dev/null
+++ b/client/src/akkamon/render/engine/AkkamonEngine.ts
@@ -0,0 +1,7 @@
+import { client } from '../../../app';
+
+
+export class AkkamonEngine {
+ client = client;
+
+}
diff --git a/client/src/akkamon/render/engine/GridPhysics.ts b/client/src/akkamon/render/engine/GridPhysics.ts
index b1fe459..2f1c080 100644
--- a/client/src/akkamon/render/engine/GridPhysics.ts
+++ b/client/src/akkamon/render/engine/GridPhysics.ts
@@ -1,17 +1,20 @@
import Phaser from 'phaser';
-import type { PlayerSprite } from './sprite';
-import { Direction } from './Direction';
-import AkkamonStartScene from './scene';
-import {
- akkamonClient
-} from './app';
+
+import { AkkamonWorldScene } from '../../scenes/AkkamonWorldScene';
+
+import { AkkamonEngine } from './AkkamonEngine';
+
+import type { PlayerSprite } from '../model/PlayerSprite';
+
+import { Direction } from '../Direction';
+
import {
StartMovingEvent,
StopMovingEvent,
NewTilePosEvent
-} from './events';
+} from '../../client/Events';
-export class GridPhysics {
+export class GridPhysics extends AkkamonEngine {
static movementDirectionVectors: {
[key in Direction]?: Phaser.Math.Vector2;
@@ -23,7 +26,7 @@ export class GridPhysics {
}
private movementDirection: Direction = Direction.NONE;
- private readonly speedPixelsPerSecond: number = AkkamonStartScene.TILE_SIZE * 4;
+ private readonly speedPixelsPerSecond: number = AkkamonWorldScene.TILE_SIZE * 4;
private tileSizePixelsWalked: number = 0;
@@ -32,7 +35,9 @@ export class GridPhysics {
constructor(
private playerSprite: PlayerSprite,
private tileMap: Phaser.Tilemaps.Tilemap
- ) { }
+ ) {
+ super()
+ }
movePlayerSprite(direction: Direction): void {
this.lastMovementIntent = direction;
@@ -52,7 +57,7 @@ export class GridPhysics {
private startMoving(direction: Direction): void {
console.log("Sending startMovingEvent");
- akkamonClient.send(
+ this.client.send(
new StartMovingEvent(this.playerSprite.getScene(), direction)
);
this.playerSprite.startAnimation(direction);
@@ -76,13 +81,13 @@ export class GridPhysics {
this.spriteMovement(pixelsToWalkThisUpdate);
this.updatePlayerSpriteTilePosition();
} else {
- this.spriteMovement(AkkamonStartScene.TILE_SIZE - this.tileSizePixelsWalked);
+ this.spriteMovement(AkkamonWorldScene.TILE_SIZE - this.tileSizePixelsWalked);
this.stopMoving();
}
}
private updatePlayerSpriteTilePosition() {
- akkamonClient.send(
+ this.client.send(
new NewTilePosEvent(
this.playerSprite.getScene(),
this.playerSprite.getTilePos()
@@ -106,7 +111,7 @@ export class GridPhysics {
private spriteMovement(pixelsToMove: number) {
this.tileSizePixelsWalked += pixelsToMove;
- this.tileSizePixelsWalked %= AkkamonStartScene.TILE_SIZE;
+ this.tileSizePixelsWalked %= AkkamonWorldScene.TILE_SIZE;
const directionVec = GridPhysics.movementDirectionVectors[
@@ -125,7 +130,7 @@ export class GridPhysics {
pixelsToWalkThisUpdate: number
): boolean {
return (
- this.tileSizePixelsWalked + pixelsToWalkThisUpdate >= AkkamonStartScene.TILE_SIZE
+ this.tileSizePixelsWalked + pixelsToWalkThisUpdate >= AkkamonWorldScene.TILE_SIZE
);
}
@@ -135,7 +140,7 @@ export class GridPhysics {
}
private stopMoving(): void {
- akkamonClient.send(
+ this.client.send(
new StopMovingEvent(
this.playerSprite.getScene(),
this.movementDirection
diff --git a/client/src/akkamon/render/engine/RemotePlayerEngine.ts b/client/src/akkamon/render/engine/RemotePlayerEngine.ts
index 5d85f24..917453b 100644
--- a/client/src/akkamon/render/engine/RemotePlayerEngine.ts
+++ b/client/src/akkamon/render/engine/RemotePlayerEngine.ts
@@ -1,22 +1,27 @@
import Phaser from 'phaser';
-import type AkkamonStartScene from './scene';
-import { akkamonClient } from './app';
-import type { Direction } from './Direction';
+
+import type { AkkamonWorldScene } from '../../scenes/AkkamonWorldScene';
+import { AkkamonEngine } from '../engine/AkkamonEngine';
+
+import type { Direction } from '../Direction';
+
import {
Queue,
RemotePlayerSprite
-} from './RemotePlayerSprite';
+} from '../model/RemotePlayerSprite';
+
import type {
RemoteMovementQueues
-} from './events';
+} from '../../client/Events';
-export class RemotePlayerEngine {
+export class RemotePlayerEngine extends AkkamonEngine {
- private scene: AkkamonStartScene;
+ private scene: AkkamonWorldScene;
private trainerIdToRemotePlayerSprite: Map<string, RemotePlayerSprite> = new Map();
- constructor(scene: AkkamonStartScene) {
+ constructor(scene: AkkamonWorldScene) {
+ super();
this.scene = scene;
}
diff --git a/client/src/akkamon/render/model/PlayerSprite.ts b/client/src/akkamon/render/model/PlayerSprite.ts
index 948d8d9..ec44295 100644
--- a/client/src/akkamon/render/model/PlayerSprite.ts
+++ b/client/src/akkamon/render/model/PlayerSprite.ts
@@ -1,6 +1,7 @@
import Phaser from 'phaser';
-import AkkamonStartScene from './scene';
-import type { Direction } from './Direction';
+import { AkkamonWorldScene } from '../../scenes/AkkamonWorldScene';
+
+import type { Direction } from '../Direction';
type PlayerSpriteConfig = {
scene: Phaser.Scene,
@@ -17,12 +18,12 @@ export class PlayerSprite extends Phaser.GameObjects.Sprite implements AkkamonPl
tilePos: Phaser.Math.Vector2;
constructor(config: PlayerSpriteConfig) {
- const offsetX = AkkamonStartScene.TILE_SIZE / 2;
- const offsetY = AkkamonStartScene.TILE_SIZE;
+ const offsetX = AkkamonWorldScene.TILE_SIZE / 2;
+ const offsetY = AkkamonWorldScene.TILE_SIZE;
super(config.scene,
- config.tilePos.x * AkkamonStartScene.TILE_SIZE + offsetX,
- config.tilePos.y * AkkamonStartScene.TILE_SIZE + offsetY,
+ config.tilePos.x * AkkamonWorldScene.TILE_SIZE + offsetX,
+ config.tilePos.y * AkkamonWorldScene.TILE_SIZE + offsetY,
config.texture,
config.frame);
diff --git a/client/src/akkamon/render/model/RemotePlayerSprite.ts b/client/src/akkamon/render/model/RemotePlayerSprite.ts
index 6103d09..0b8d3e9 100644
--- a/client/src/akkamon/render/model/RemotePlayerSprite.ts
+++ b/client/src/akkamon/render/model/RemotePlayerSprite.ts
@@ -1,8 +1,8 @@
import Phaser from 'phaser';
-import AkkamonStartScene from './scene';
-import { PlayerSprite } from './sprite';
-import { GridPhysics } from './GridPhysics';
-import { Direction } from './Direction';
+import { AkkamonWorldScene } from '../../scenes/AkkamonWorldScene';
+import { PlayerSprite } from '../model/PlayerSprite';
+import { GridPhysics } from '../engine/GridPhysics';
+import { Direction } from '../Direction';
export class Queue<T> {
private _data = new Array();
@@ -51,7 +51,7 @@ export class RemotePlayerSprite extends PlayerSprite {
private movementDirection: Direction = Direction.NONE;
- private speedPixelsPerSecond: number = AkkamonStartScene.TILE_SIZE * 4;
+ private speedPixelsPerSecond: number = AkkamonWorldScene.TILE_SIZE * 4;
private tileSizePixelsWalked: number = 0;
@@ -76,7 +76,7 @@ export class RemotePlayerSprite extends PlayerSprite {
} else if (this.shouldContinueMoving()) {
this.move(pixelsToWalkThisUpdate);
} else {
- this.move(AkkamonStartScene.TILE_SIZE - this.tileSizePixelsWalked);
+ this.move(AkkamonWorldScene.TILE_SIZE - this.tileSizePixelsWalked);
this.stopMoving();
}
}
@@ -91,12 +91,12 @@ export class RemotePlayerSprite extends PlayerSprite {
}
willCrossTileBorderThisUpdate(pixelsToWalkThisUpdate: number): boolean {
- return (this.tileSizePixelsWalked + pixelsToWalkThisUpdate) >= AkkamonStartScene.TILE_SIZE;
+ return (this.tileSizePixelsWalked + pixelsToWalkThisUpdate) >= AkkamonWorldScene.TILE_SIZE;
}
move(pixelsToMove: number): void {
this.tileSizePixelsWalked += pixelsToMove;
- this.tileSizePixelsWalked %= AkkamonStartScene.TILE_SIZE;
+ this.tileSizePixelsWalked %= AkkamonWorldScene.TILE_SIZE;
const directionVec = GridPhysics.movementDirectionVectors[this.movementDirection]!.clone();
diff --git a/client/src/akkamon/scenes/AkkamonWorldScene.ts b/client/src/akkamon/scenes/AkkamonWorldScene.ts
new file mode 100644
index 0000000..b9cfc20
--- /dev/null
+++ b/client/src/akkamon/scenes/AkkamonWorldScene.ts
@@ -0,0 +1,23 @@
+import Phaser from 'phaser';
+
+import { client } from '../../app';
+
+export let eventsCenter = new Phaser.Events.EventEmitter();
+
+export class AkkamonWorldScene extends Phaser.Scene {
+ static readonly TILE_SIZE = 32;
+
+ map?: Phaser.Tilemaps.Tilemap;
+
+ client = client;
+
+ eventsCenter = eventsCenter;
+
+ public spawnPointTilePos?: {
+ x: number,
+ y: number
+ };
+
+ spawnPoint: Phaser.Types.Tilemaps.TiledObject | undefined;
+
+}
diff --git a/client/src/akkamon/scenes/BootScene.ts b/client/src/akkamon/scenes/BootScene.ts
new file mode 100644
index 0000000..4642584
--- /dev/null
+++ b/client/src/akkamon/scenes/BootScene.ts
@@ -0,0 +1,39 @@
+import Phaser from 'phaser';
+
+import { AkkamonWorldScene } from './AkkamonWorldScene';
+
+export class BootScene extends AkkamonWorldScene {
+ constructor() {
+ super('BootScene')
+ }
+
+ init(): void {
+ }
+
+ preload(): void {
+ this.load.image("tiles", "assets/tilesets/akkamon-demo-extruded.png");
+ // load from json!
+ this.load.tilemapTiledJSON("map", "assets/tilemaps/akkamon-demo-tilemap.json");
+
+ // An atlas is a way to pack multiple images together into one texture. I'm using it to load all
+ // the player animations (walking left, walking right, etc.) in one image. For more info see:
+
+ // https://labs.phaser.io/view.html?src=src/animation/texture%20atlas%20animation.js
+ // If you don't use an atlas, you can do the same thing with a spritesheet, see:
+ // https://labs.phaser.io/view.html?src=src/animation/single%20sprite%20sheet.js
+ this.load.atlas("atlas",
+ "assets/atlas/atlas.png",
+ "assets/atlas/atlas.json");
+
+ this.load.image("menu", "assets/images/pMenu.png");
+ this.load.image("menupicker", "assets/images/menupicker.png");
+ }
+
+ create(): void {
+ this.scene
+ .launch('DemoScene')
+ .launch('AkkamonUI')
+ .remove()
+ }
+}
+
diff --git a/client/src/akkamon/scenes/DemoScene.ts b/client/src/akkamon/scenes/DemoScene.ts
index c301457..b9a230a 100644
--- a/client/src/akkamon/scenes/DemoScene.ts
+++ b/client/src/akkamon/scenes/DemoScene.ts
@@ -1,146 +1,54 @@
import Phaser from 'phaser';
-import { PlayerSprite } from './sprite';
-import { GridControls } from './GridControls';
-import { GridPhysics } from './GridPhysics';
-import { Direction } from './Direction';
+import { AkkamonWorldScene } from './AkkamonWorldScene';
-import { RemotePlayerEngine } from './RemotePlayerEngine';
-
-import { UIControls } from './uiControls';
-
-import { akkamonClient } from './app';
-
-export default class AkkamonStartScene extends Phaser.Scene
+export class DemoScene extends AkkamonWorldScene
{
-
- static readonly TILE_SIZE = 32;
-
- private gridPhysics?: GridPhysics
- private gridControls?: GridControls
-
- private remotePlayerEngine?: RemotePlayerEngine
-
- public spawnPointTilePos?: {
- x: number,
- y: number
- };
-
- directionToAnimation: {
- [key in Direction]: string
- } = {
- [Direction.UP]: "misa-back-walk",
- [Direction.DOWN]: "misa-front-walk",
- [Direction.LEFT]: "misa-left-walk",
- [Direction.RIGHT]: "misa-right-walk",
- [Direction.NONE]: "misa-front-walk"
- }
-
- spawnPoint: Phaser.Types.Tilemaps.TiledObject | undefined;
-
-
constructor ()
{
- super('akkamonStartScene');
- }
-
- preload ()
- {
- this.load.image("tiles", "assets/tilesets/akkamon-demo-extruded.png");
- // load from json!
- this.load.tilemapTiledJSON("map", "assets/tilemaps/akkamon-demo-tilemap.json");
-
- // An atlas is a way to pack multiple images together into one texture. I'm using it to load all
- // the player animations (walking left, walking right, etc.) in one image. For more info see:
-
- // https://labs.phaser.io/view.html?src=src/animation/texture%20atlas%20animation.js
- // If you don't use an atlas, you can do the same thing with a spritesheet, see:
- // https://labs.phaser.io/view.html?src=src/animation/single%20sprite%20sheet.js
- this.load.atlas("atlas",
- "assets/atlas/atlas.png",
- "assets/atlas/atlas.json");
+ super('DemoScene');
}
-
create ()
{
- const map = this.make.tilemap({ key: "map" });
+ this.map = this.make.tilemap({ key: "map" });
// Parameters are the name you gave the tileset in Tiled and then the key of the tileset image in
// Phaser's cache (i.e. the name you used in preload)
- const tileset = map.addTilesetImage("akkamon-demo-extruded", "tiles");
+ const tileset = this.map.addTilesetImage("akkamon-demo-extruded", "tiles");
// Parameters: layer name (or index) from Tiled, tileset, x, y
- const belowLayer = map.createLayer("Below Player", tileset, 0, 0);
- const worldLayer = map.createLayer("World", tileset, 0, 0);
- const aboveLayer = map.createLayer("Above Player", tileset, 0, 0);
+ const belowLayer = this.map.createLayer("Below Player", tileset, 0, 0);
+ const worldLayer = this.map.createLayer("World", tileset, 0, 0);
+ const aboveLayer = this.map.createLayer("Above Player", tileset, 0, 0);
// By default, everything gets depth sorted on the screen in the order we created things. Here, we
// want the "Above Player" layer to sit on top of the player, so we explicitly give it a depth.
// Higher depths will sit on top of lower depth objects.
aboveLayer.setDepth(10);
- this.spawnPoint = map.findObject("Objects", obj => obj.name === "Spawn Point");
-
- //this.createPlayerAnimation(Direction.UP);
-
-
- // Create a sprite with physics enabled via the physics system. The image used for the sprite has
- // a bit of whitespace, so I'm using setSize & setOffset to control the size of the player's body.
+ this.spawnPoint = this.map.findObject("Objects", obj => obj.name === "Spawn Point");
var tilePos = new Phaser.Math.Vector2(
- Math.floor(this.spawnPoint.x! / AkkamonStartScene.TILE_SIZE),
- Math.floor(this.spawnPoint.y! / AkkamonStartScene.TILE_SIZE),
+ Math.floor(this.spawnPoint.x! / AkkamonWorldScene.TILE_SIZE),
+ Math.floor(this.spawnPoint.y! / AkkamonWorldScene.TILE_SIZE),
);
this.spawnPointTilePos = tilePos;
- let player = new PlayerSprite({
- scene: this,
- tilePos: tilePos,
- texture: this.textures.get("atlas"),
- frame: "misa-front",
- });
-
- this.gridPhysics = new GridPhysics(player, map);
- this.gridControls = new GridControls(
- this.input,
- this.gridPhysics
+ this.client.requestInitPlayerSprite(
+ this
);
- this.remotePlayerEngine = new RemotePlayerEngine(this);
- akkamonClient.setRemotePlayerEngine(this.remotePlayerEngine);
-
- this.createPlayerAnimation(Direction.LEFT, 0, 3);
- this.createPlayerAnimation(Direction.RIGHT, 0, 3);
- this.createPlayerAnimation(Direction.UP, 0, 3);
- this.createPlayerAnimation(Direction.DOWN, 0, 3);
-
- // Phaser supports multiple cameras, but you can access the default camera like this:
- const camera = this.cameras.main;
- camera.startFollow(player);
- camera.roundPixels = true;
- camera.setBounds(0, 0, map.widthInPixels, map.heightInPixels);
+ let akey = this.input.keyboard.addKey('a');
+ akey.on('down', () => {
+ this.input.keyboard.enabled = false;
+ this.eventsCenter.emit('open-menu');
+ // this.client.disableGridControls();
+ });
}
update(time: number, delta: number) {
- this.gridControls!.update();
- this.gridPhysics!.update(delta);
- this.remotePlayerEngine!.update(delta);
+ this.client.updateScene(delta);
}
- private createPlayerAnimation(direction: Direction, start: number, end: number) {
- this.anims.create({
- key: direction, // "misa-left-walk",
- frames: this.anims.generateFrameNames("atlas", { prefix: this.directionToAnimation[direction] + ".", start: start, end: end, zeroPad: 3 }),
- frameRate: 10,
- repeat: -1
- });
-
-// anims.create({
-// key: "misa-left-walk",
-// frames: anims.generateFrameNames("atlas", { prefix: "misa-left-walk.", start: 0, end: 3, zeroPad: 3 }),
-// frameRate: 10,
-// repeat: -1
-
- }
}
diff --git a/client/src/akkamon/scenes/Pack.ts b/client/src/akkamon/scenes/Pack.ts
new file mode 100644
index 0000000..a89c860
--- /dev/null
+++ b/client/src/akkamon/scenes/Pack.ts
@@ -0,0 +1 @@
+import assets from './Assets';
diff --git a/client/src/akkamon/scenes/UIElement.ts b/client/src/akkamon/scenes/UIElement.ts
new file mode 100644
index 0000000..f48827d
--- /dev/null
+++ b/client/src/akkamon/scenes/UIElement.ts
@@ -0,0 +1,3 @@
+export enum UIElement {
+ MAIN_MENU = "main-menu"
+}
diff --git a/client/src/akkamon/scenes/UIScene.ts b/client/src/akkamon/scenes/UIScene.ts
index 3dc7ee9..de415f8 100644
--- a/client/src/akkamon/scenes/UIScene.ts
+++ b/client/src/akkamon/scenes/UIScene.ts
@@ -1,20 +1,125 @@
-import { UIControls } from './uiControls';
+import { Direction } from '../render/Direction';
+import { eventsCenter } from '../../akkamon/scenes/AkkamonWorldScene';
-export class AkkamonUI extends Phaser.Scene
+class MenuText extends Phaser.GameObjects.Text {
+ constructor(scene: Phaser.Scene, group: Phaser.GameObjects.Group, x: number, y: number, text: string) {
+ let style: Phaser.Types.GameObjects.Text.TextStyle = {
+ fontFamily: 'Courier',
+ fontSize: '16px',
+ fontStyle: '',
+ backgroundColor: undefined,
+ color: '#000000',
+ stroke: '#000000',
+ strokeThickness: 0,
+ align: 'left', // 'left'|'center'|'right'|'justify'
+ }
+ super(scene, x, y, text, style);
+ scene.add.existing(this);
+ group.add(this);
+ }
+}
+
+interface AkkamonMenu {
+}
+
+class Menu extends Phaser.GameObjects.Image implements AkkamonMenu {
+
+ private buttons?: Array<MenuText>;
+
+ private buttonSelector?: Phaser.GameObjects.Image;
+
+ private selectedButton?: string;
+
+ private index?: number;
+
+ public group?: Phaser.GameObjects.Group;
+
+ constructor(scene: Phaser.Scene) {
+ const { width, height } = scene.scale;
+ super(scene, width * 0.95, height * 0.05, "menu")
+ this.setOrigin(1,0)
+ this.setVisible(true)
+ this.setDisplaySize(296, 400)
+
+ this.group = new Phaser.GameObjects.Group(scene);
+
+ scene.add.existing(this);
+ this.group.add(this);
+
+ this.buttons = new Array();
+
+ this.setMainButtons();
+
+ this.buttonSelector = scene.add.image(
+ this.x - this.displayWidth + 40,
+ this.buttons![0].y + 7,
+ "menupicker")
+ .setDisplaySize(20,33)
+ .setOrigin(0.5,0.5);
+ this.group.add(this.buttonSelector);
+
+ this.index = 0;
+ this.selectedButton = this.buttons[0].text;
+ }
+
+ resetPicker() {
+ this.buttonSelector!
+ .setPosition(this.x - this.displayWidth + 40,
+ this.buttons![0].y + 7);
+ }
+
+ setMainButtons() {
+ this.buttons!.push(new MenuText(this.scene, this.group!, this.x - 150, this.y + 40, 'POKéDEX'));
+ this.buttons!.push(new MenuText(this.scene, this.group!, this.x - 150, this.y + 140, 'POKéMON'));
+ this.buttons!.push(new MenuText(this.scene, this.group!, this.x - 150, this.y + 240, 'PHONE'));
+ this.buttons!.push(new MenuText(this.scene, this.group!, this.x - 150, this.y + 340, 'CLOSE'));
+ }
+
+ clearButtons() {
+ this.buttons = new Array();
+ }
+
+ selectButton(direction: Direction) {
+ if (direction === Direction.UP && this.index! !== 0) {
+ this.buttonSelector!
+ .setPosition(this.buttonSelector!.x, this.buttonSelector!.y - 100)
+ this.index! -= 1;
+ } else if (direction === Direction.DOWN && this.index !== this.buttons!.length - 1) {
+ this.buttonSelector!
+ .setPosition(this.buttonSelector!.x, this.buttonSelector!.y + 100)
+ this.index! += 1;
+ }
+
+ this.selectedButton = this.buttons![this.index!].text;
+ }
+}
+
+export class UIScene extends Phaser.Scene
{
- private uiControls: UIControls;
+ // private uiControls: UIControls;
+
+ private cursors?: Phaser.Types.Input.Keyboard.CursorKeys;
+
+ private menu?: Menu;
constructor ()
{
super('AkkamonUI');
}
- preload() {
- }
-
create () {
- this.uiControls = new UIControls(this.input);
+ //this.uiControls = new UIControls(this.input);
+
+
+ this.menu = new Menu(this);
+ this.menu.group!.setVisible(false);
+
+ eventsCenter.on('open-menu', () =>
+ {
+ this.menu!.group!.setVisible(true);
+ });
+
}
}
diff --git a/client/src/app.ts b/client/src/app.ts
index c6bad67..197fb63 100644
--- a/client/src/app.ts
+++ b/client/src/app.ts
@@ -1,26 +1,19 @@
-// import Phaser from 'phaser';
-import AkkamonStartScene from './scene';
-import { AkkamonUI } from './uiScene';
-import { Client } from './client';
-
-const serviceUrl = 'ws://localhost:8080';
-
-export const akkamonClient = new Client(serviceUrl);
-
-const config: Phaser.Types.Core.GameConfig & Phaser.Types.Core.RenderConfig = {
- type: Phaser.AUTO,
- backgroundColor: '#125555',
- width: 800,
- height: 600,
- pixelArt: true,
- scene: [AkkamonStartScene, AkkamonUI]
-};
-
-const game: Phaser.Game = new Phaser.Game(config);
+// // import Phaser from 'phaser';
+// import AkkamonStartScene from './scene';
+// import { AkkamonUI } from './uiScene';
+// import { Client } from './client';
+//
+// const serviceUrl = 'ws://localhost:8080';
+//
+// export const akkamonClient = new Client(serviceUrl);
+//
+//
+// const game: Phaser.Game = new Phaser.Game(config);
import Phaser from 'phaser';
-import gameConfig from './app/gameConfig.js';
+import { gameConfig } from './akkamon/GameConfig';
+import { Client } from './akkamon/client/Client';
function newGame () {
if (game) return;
@@ -30,10 +23,10 @@ function newGame () {
function destroyGame () {
if (!game) return;
game.destroy(true);
- game.runDestroy();
game = null;
}
-let game;
+export let client = new Client('ws://localhost:8080');
+let game: Phaser.Game | null | undefined;
if (!game) newGame();