-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
20 changed files
with
623 additions
and
35 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import AzNopolyClient from "./client"; | ||
import AzNopolyGame from "./game"; | ||
import Room from "./room"; | ||
|
||
export function mock(aznopoly: AzNopolyGame) { | ||
let game = aznopoly as any; | ||
game._client = { | ||
id: "1111-2222-3333-4444", | ||
sendPacket: () => {}, | ||
addEventListener: () => {}, | ||
removeEventListener: () => {}, | ||
}; | ||
game._room = { | ||
connectedPlayerIds: ["1111-2222-3333-4444"], | ||
host: "1111-2222-3333-4444", | ||
}; | ||
game._name = "mockius maximus"; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
|
||
|
||
export default class ColorProgressBar extends Phaser.GameObjects.Container { | ||
|
||
private graphics: Phaser.GameObjects.Graphics; | ||
|
||
private colors: Map<number, number> = new Map(); | ||
private barWidth: number; | ||
private barHeight: number; | ||
|
||
constructor(scene: Phaser.Scene, x: number, y: number, width: number, height: number) { | ||
super(scene, x, y); | ||
this.barWidth = width; | ||
this.barHeight = height; | ||
|
||
this.graphics = new Phaser.GameObjects.Graphics(scene); | ||
this.drawBar(); | ||
|
||
this.add(this.graphics); | ||
} | ||
|
||
public setColors(colors: Map<number, number>) { | ||
this.colors = colors; | ||
this.drawBar(); | ||
} | ||
|
||
private drawBar() { | ||
this.graphics.clear(); | ||
|
||
let progress = 0; | ||
for (const[color, percentage] of this.colors.entries()) { | ||
this.graphics.fillStyle(color); | ||
this.graphics.fillRect(this.barWidth * progress, 0, this.barWidth * percentage, this.barHeight); | ||
progress += percentage; | ||
} | ||
this.graphics.fillStyle(0x000000); | ||
this.graphics.fillRect(this.barWidth * progress, 0, this.barWidth * (1 - progress), this.barHeight); | ||
|
||
this.graphics.lineStyle(2, 0xffffff); | ||
this.graphics.strokeRoundedRect(-1, -1, this.barWidth+2, this.barHeight+2, 5); | ||
this.graphics.lineStyle(1, 0x000000); | ||
this.graphics.strokeRoundedRect(-3, -3, this.barWidth+6, this.barHeight+6, 5); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import { HEIGHT, WIDTH } from "../main"; | ||
|
||
const SIZE = 85; | ||
const ARROW_COLOR = 0x00ff00; | ||
export interface RoombaConfig { | ||
id: string; | ||
x: number; | ||
y: number; | ||
angle: number; | ||
color: number; | ||
paintColor: number; | ||
speed: number | ||
} | ||
|
||
|
||
export class Roomba extends Phaser.GameObjects.Container { | ||
static SIZE = SIZE; | ||
|
||
private graphics: Phaser.GameObjects.Graphics; | ||
private arrow: Phaser.GameObjects.Graphics; | ||
|
||
private lastPaintPosition: Phaser.Math.Vector2; | ||
|
||
private color: number; | ||
private paintColor: number; | ||
private speed: number; | ||
|
||
public readonly id: string; | ||
|
||
constructor(scene: Phaser.Scene, { id, x, y, angle, color, paintColor, speed} : RoombaConfig) { | ||
super(scene, x, y); | ||
|
||
this.id = id; | ||
this.color = color; | ||
this.paintColor = paintColor; | ||
this.speed = speed; | ||
|
||
this.graphics = new Phaser.GameObjects.Graphics(scene); | ||
this.arrow = new Phaser.GameObjects.Graphics(scene); | ||
this.lastPaintPosition = new Phaser.Math.Vector2(x, y); | ||
|
||
this.graphics.fillStyle(this.color); | ||
this.graphics.fillCircle(0, 0, SIZE / 2); | ||
this.graphics.fillCircle(SIZE/5 * 2, 0, SIZE / 4); | ||
|
||
scene.physics.world.enable(this); | ||
const body = this.body! as Phaser.Physics.Arcade.Body; | ||
body.setCollideWorldBounds(true) | ||
body.setOffset(-SIZE / 2, -SIZE / 2); | ||
body.setCircle(SIZE/2); | ||
|
||
this.add(this.arrow); | ||
this.add(this.graphics); | ||
|
||
this.updateDirection(new Phaser.Math.Vector2(Math.cos(angle), Math.sin(angle))); | ||
|
||
this.initDragEvents(); | ||
} | ||
|
||
private initDragEvents() { | ||
this.graphics.setInteractive({ | ||
hitArea: new Phaser.Geom.Circle(0, 0, SIZE / 2), | ||
hitAreaCallback: Phaser.Geom.Circle.Contains, | ||
useHandCursor: false, | ||
draggable: true | ||
}, Phaser.Geom.Circle.Contains); | ||
|
||
this.graphics.on('dragstart', () => { | ||
this.arrow.visible = true; | ||
}); | ||
|
||
this.graphics.on('drag', (event: any) => { | ||
const dragOffset = new Phaser.Math.Vector2(event.x - this.x, event.y - this.y); | ||
this.drawArrow(Phaser.Math.Vector2.ZERO, dragOffset); | ||
}); | ||
|
||
this.graphics.on('dragend', (event: any) => { | ||
const dragOffset = new Phaser.Math.Vector2(event.x - this.x, event.y - this.y); | ||
this.scene.events.emit('roomba-dragged', { id: this.id, offset: dragOffset}); | ||
this.drawArrow(new Phaser.Math.Vector2(0, 0), new Phaser.Math.Vector2(0, 0)); | ||
this.arrow.visible = false; | ||
}); | ||
} | ||
|
||
private drawArrow(start: Phaser.Math.Vector2, end: Phaser.Math.Vector2) { | ||
const arrow = this.arrow; | ||
arrow.clear(); | ||
|
||
arrow.lineStyle(5, ARROW_COLOR); | ||
arrow.fillStyle(ARROW_COLOR); | ||
|
||
this.arrow.lineBetween(start.x, start.y, end.x, end.y); | ||
|
||
const arrowAngle = Math.atan2(end.y - start.y, end.x - start.x); | ||
const arrowAngleNormal = arrowAngle + Math.PI/2; | ||
const arrowHeadLength = 10; | ||
const arrowHeadWidth = 10; | ||
|
||
this.arrow.fillTriangle( | ||
end.x + Math.cos(arrowAngleNormal) * arrowHeadWidth, | ||
end.y + Math.sin(arrowAngleNormal) * arrowHeadWidth, | ||
end.x + Math.cos(arrowAngle) * arrowHeadLength, | ||
end.y + Math.sin(arrowAngle) * arrowHeadLength, | ||
end.x - Math.cos(arrowAngleNormal) * arrowHeadWidth, | ||
end.y - Math.sin(arrowAngleNormal) * arrowHeadWidth, | ||
); | ||
} | ||
|
||
public updateDirection(direction: Phaser.Math.Vector2) { | ||
this.graphics.rotation = direction.angle(); | ||
|
||
const normalized = direction.normalize(); | ||
const body = this.body! as Phaser.Physics.Arcade.Body; | ||
body.setVelocity(normalized.x * this.speed, normalized.y * this.speed); | ||
} | ||
|
||
|
||
public paintPath(graphic: Phaser.GameObjects.Graphics) { | ||
graphic.lineStyle(SIZE, this.paintColor); | ||
graphic.lineBetween(this.lastPaintPosition.x, this.lastPaintPosition.y, this.x, this.y); | ||
graphic.fillStyle(this.paintColor) | ||
graphic.fillCircle(this.x, this.y, SIZE/2); | ||
this.lastPaintPosition = new Phaser.Math.Vector2(this.x, this.y); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import AzNopolyGame from "../game"; | ||
|
||
|
||
export default class BaseSceneController { | ||
|
||
protected aznopoly: AzNopolyGame; | ||
|
||
private _scene: Phaser.Scene; | ||
private packetType: string; | ||
|
||
private registeredMethods: string[] = []; | ||
|
||
/** | ||
* A proxy object that allows for calling methods on the controller. | ||
* Functions called on the proxy will be sent to all clients and executed asynchonously | ||
* Functions must be registered with registerSyncedMethod | ||
*/ | ||
protected syncProxy = new Proxy(this, { | ||
get: (_, prop) => { | ||
return this.onProxyCall(prop); | ||
}, | ||
}); | ||
|
||
constructor(scene: Phaser.Scene, aznopoly: AzNopolyGame) { | ||
this._scene = scene; | ||
this.aznopoly = aznopoly; | ||
this.packetType = "CLIENT_MINIGAME_" + this.constructor.name.toUpperCase(); | ||
} | ||
|
||
/** | ||
* Should be called when the scene has initialized all of it's state | ||
* and is ready to start receiving packets | ||
*/ | ||
public onSceneReady() { | ||
const listener = this.aznopoly.addPacketListener(this.packetType, this.onPacket.bind(this) as EventListener); | ||
this._scene.events.once(Phaser.Scenes.Events.SHUTDOWN, () => this.aznopoly.removePacketListener(this.packetType, listener)); | ||
} | ||
|
||
/** | ||
* Registers a method to be allowed to be called with syncProxy | ||
* @param method The method to be registered | ||
*/ | ||
public registerSyncedMethod(method: Function) { | ||
const name = method.name; | ||
if (this.registeredMethods.includes(name)) { | ||
throw new Error(`Packet executor with name ${name} already exists`); | ||
} | ||
this.registeredMethods.push(name); | ||
} | ||
|
||
private isMethodAllowed(method: string) { | ||
return this.registeredMethods.includes(method); | ||
} | ||
|
||
private onProxyCall(prop: symbol | string) { | ||
if (!this.isMethodAllowed(String(prop))) { | ||
throw new Error(`This method was not registered for sync: ${String(prop)}`); | ||
} | ||
|
||
return (...args: any[]) => { | ||
const packet = this.sendExecPacket(String(prop), ...args); | ||
this.executePacket(packet); | ||
} | ||
} | ||
|
||
private onPacket(event: CustomEvent<{type: string, data: any}>) { | ||
const packet = event.detail; | ||
this.executePacket(packet); | ||
} | ||
|
||
private sendExecPacket(method: string, ...args: any[]) { | ||
const packet = { | ||
type: this.packetType, | ||
data: { | ||
method, | ||
arguments: args | ||
} | ||
} | ||
|
||
this.aznopoly.broadcastPacket(packet); | ||
return packet; | ||
} | ||
|
||
private executePacket(packet: {type: string, data: {method: string, arguments: any[]}}) { | ||
if (packet.type !== this.packetType) { | ||
console.error(`Packet type ${packet.type} does not match expected type ${this.packetType}`); | ||
return; | ||
} | ||
|
||
if (!this.isMethodAllowed(packet.data.method)) { | ||
console.error(`Method ${packet.data.method} is not allowed`); | ||
return; | ||
} | ||
|
||
const method = (this as any)[packet.data.method]; | ||
if (typeof method !== "function") { | ||
console.error(`Method ${packet.data.method} is not a function`); | ||
return; | ||
} | ||
(method).apply(this, packet.data.arguments); | ||
} | ||
|
||
} |
Oops, something went wrong.