Skip to content

Commit

Permalink
Merge pull request #38 from SaltieRL/pa-bug-fixes
Browse files Browse the repository at this point in the history
General bug fixes and adjustments
  • Loading branch information
Abbondanzo committed Jun 27, 2019
2 parents 6f1de55 + ed88a9e commit 948f293
Show file tree
Hide file tree
Showing 17 changed files with 215 additions and 78 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "replay-viewer",
"version": "0.3.3",
"version": "0.4.0",
"description": "Rocket League replay viewer React component and tooling",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
Expand Down
2 changes: 2 additions & 0 deletions src/constants/eventNames.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export const CAMERA_CHANGE = "CAMERA_CHANGE"
export const CAMERA_FRAME_UPDATE = "CAMERA_FRAME_UPDATE"
export const PLAY_PAUSE = "PLAY_PAUSE"
export const FRAME = "FRAME"
export const CANVAS_RESIZE = "CANVAS_RESIZE"
3 changes: 3 additions & 0 deletions src/eventbus/EventBus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ class EventBus {
if (!this.listeners[type]) {
this.listeners[type] = []
}
// Remove duplicate event listeners
this.removeEventListener(type, callback, scope)
// Add this listener to the list
this.listeners[type].push({ type, callback, scope })
}

Expand Down
3 changes: 3 additions & 0 deletions src/eventbus/events/cameraChange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { Camera } from "three"
import { CAMERA_CHANGE } from "../../constants/eventNames"
import EventBus from "../EventBus"

/**
* Event fired when the active camera is updated with a new object.
*/
export interface CameraChangeEvent {
camera: Camera
}
Expand Down
3 changes: 3 additions & 0 deletions src/eventbus/events/cameraFrameUpdate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { Vector3 } from "three"
import { CAMERA_FRAME_UPDATE } from "../../constants/eventNames"
import EventBus from "../EventBus"

/**
* Event that fires telling all cameras to adjust their settings.
*/
export interface CameraFrameUpdateEvent {
ballPosition: Vector3
ballCam: boolean
Expand Down
16 changes: 16 additions & 0 deletions src/eventbus/events/canvasResize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { CANVAS_RESIZE } from "../../constants/eventNames"
import EventBus from "../EventBus"

/**
* Fires when the main canvas is resized and its dimensions are adjusted.
*/
export interface CanvasResizeEvent {
width: number
height: number
}

export const {
addEventListener: addCanvasResizeListener,
removeEventListener: removeCanvasResizeListener,
dispatch: dispatchCanvasResizeEvent,
} = EventBus.buildEvent<CanvasResizeEvent>(CANVAS_RESIZE)
15 changes: 15 additions & 0 deletions src/eventbus/events/frame.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { FRAME } from "../../constants/eventNames"
import EventBus from "../EventBus"

/**
* Fires each time the global game clock advances a frame or updates its current frame.
*/
export interface FrameEvent {
frame: number
}

export const {
addEventListener: addFrameListener,
removeEventListener: removeFrameListener,
dispatch: dispatchFrameEvent,
} = EventBus.buildEvent<FrameEvent>(FRAME)
15 changes: 15 additions & 0 deletions src/eventbus/events/playPause.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { PLAY_PAUSE } from "../../constants/eventNames"
import EventBus from "../EventBus"

/**
* Fires when the global game clock has paused.
*/
export interface PlayPauseEvent {
paused: boolean
}

export const {
addEventListener: addPlayPauseListener,
removeEventListener: removePlayPauseListener,
dispatch: dispatchPlayPauseEvent,
} = EventBus.buildEvent<PlayPauseEvent>(PLAY_PAUSE)
41 changes: 39 additions & 2 deletions src/managers/CameraManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ import {
} from "../constants/gameObjectNames"
import { dispatchCameraChange } from "../eventbus/events/cameraChange"
import { dispatchCameraFrameUpdate } from "../eventbus/events/cameraFrameUpdate"
import {
addCanvasResizeListener,
CanvasResizeEvent,
removeCanvasResizeListener,
} from "../eventbus/events/canvasResize"
import { addFrameListener, removeFrameListener } from "../eventbus/events/frame"
import SceneManager from "./SceneManager"

const ORTHOGRAPHIC_CAMERA_NAMES: string[] = Object.keys(ORTHOGRAPHIC).map(
Expand All @@ -33,15 +39,18 @@ class CameraManager {

this.activeCamera.position.z = 5000
this.activeCamera.position.y = 750

addFrameListener(this.update)
addCanvasResizeListener(this.updateSize)
}

updateSize(width: number, height: number) {
private readonly updateSize = ({ width, height }: CanvasResizeEvent) => {
this.width = width
this.height = height
this.updateCameraSize()
}

update() {
private readonly update = () => {
const { position } = SceneManager.getInstance().ball.ball
dispatchCameraFrameUpdate({
ballPosition: position,
Expand Down Expand Up @@ -105,6 +114,25 @@ class CameraManager {
camera.aspect = width / height
camera.updateProjectionMatrix()
} else if (camera instanceof OrthographicCamera) {
/**
* Here, we are computing the zoom of the camera given the aspect ratio. For cameras with an
* aspect ratio greater than 4:3, we base the zoom on the height. Otherwise, we use width. The
* minimum zoom should always be 0.02.
*
* The zoom when based on the height is a simple linear function y = x / 12500 + 0.01, where x
* is the new height and y is the desired zoom.
*
* The denominator of the width-based computation is simply the slope of the previous
* function, 12500, multiplied by 1.3 since this is aspect ratio breaking point we have set in
* the if statement.
*/
if (width / height > 1.3) {
const newZoom = height / 12500 + 0.01
camera.zoom = Math.max(newZoom, 0.02)
} else {
const newZoom = width / 16250 + 0.01
camera.zoom = Math.max(newZoom, 0.02)
}
camera.left = -width / 2
camera.right = width / 2
camera.top = height / 2
Expand All @@ -116,6 +144,7 @@ class CameraManager {
private setActiveCamera(camera: Camera) {
this.activeCamera = camera
this.updateCameraSize()
this.update()
}

/**
Expand All @@ -134,6 +163,14 @@ class CameraManager {
CameraManager.instance = new CameraManager()
return CameraManager.instance
}
static destruct() {
const { instance } = CameraManager
if (instance) {
removeFrameListener(instance.update)
removeCanvasResizeListener(instance.updateSize)
CameraManager.instance = undefined
}
}
}

export interface CameraLocationOptions {
Expand Down
76 changes: 54 additions & 22 deletions src/managers/GameManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,26 @@ import { WebGLRenderer } from "three"

import defaultGameBuilder from "../builders/GameBuilder"
import EventBus from "../eventbus/EventBus"
import FPSClock, { FPSClockSubscriberOptions } from "../utils/FPSClock"
import {
addCameraChangeListener,
removeCameraChangeListener,
} from "../eventbus/events/cameraChange"
import {
addCanvasResizeListener,
CanvasResizeEvent,
removeCanvasResizeListener,
} from "../eventbus/events/canvasResize"
import {
addFrameListener,
FrameEvent,
removeFrameListener,
} from "../eventbus/events/frame"
import {
addPlayPauseListener,
PlayPauseEvent,
removePlayPauseListener,
} from "../eventbus/events/playPause"
import FPSClock from "../utils/FPSClock"
import AnimationManager from "./AnimationManager"
import CameraManager from "./CameraManager"
import SceneManager from "./SceneManager"
Expand All @@ -21,18 +40,22 @@ export class GameManager {
this.animate = this.animate.bind(this)
this.render = this.render.bind(this)
this.clock = clock
clock.subscribe(this.animate)

AnimationManager.getInstance().playAnimationClips()
addPlayPauseListener(this.onPlayPause)
addFrameListener(this.animate)
addCanvasResizeListener(this.updateSize)
addCameraChangeListener(this.render)
}

animate({ }: FPSClockSubscriberOptions) {
onPlayPause = ({ paused }: PlayPauseEvent) => {
paused ? this.clock.pause() : this.clock.play()
}

animate({ }: FrameEvent) {
const delta = this.clock.getDelta()
CameraManager.getInstance().update()

if (delta) {
SceneManager.getInstance().update()
CameraManager.getInstance().update()
AnimationManager.getInstance().updateAnimationClips(delta)
this.render()
}
Expand All @@ -42,31 +65,26 @@ export class GameManager {
return this.renderer.domElement
}

updateSize(width: number = 640, height: number = 480) {
CameraManager.getInstance().updateSize(width, height)
this.renderer.setSize(width, height)
this.render()
}

render() {
private readonly render = () => {
const { scene } = SceneManager.getInstance()
const { activeCamera } = CameraManager.getInstance()
this.renderer.render(scene, activeCamera)
}

static builder = defaultGameBuilder

private destruct() {
this.clock.unsubscribe(this.animate)
this.clock.reset()
EventBus.reset()
private readonly updateSize = ({
width = 640,
height = 480,
}: CanvasResizeEvent) => {
this.renderer.setSize(width, height)
this.render()
}

/**
* ========================================
* Managers are singletons
* ========================================
*/
static builder = defaultGameBuilder
private static instance?: GameManager
static getInstance() {
if (!GameManager.instance) {
Expand All @@ -75,10 +93,24 @@ export class GameManager {
return GameManager.instance
}
static init(options: GameManagerOptions) {
if (GameManager.instance) {
GameManager.instance.destruct()
}
GameManager.instance = new GameManager(options)
return GameManager.instance
}
static destruct() {
// Destruct other managers
SceneManager.destruct()
CameraManager.destruct()

// Handle destruction of the existing game
const { instance } = GameManager
if (instance) {
removePlayPauseListener(instance.onPlayPause)
removeFrameListener(instance.animate)
removeCanvasResizeListener(instance.updateSize)
removeCameraChangeListener(instance.render)
instance.clock.reset()
EventBus.reset()
GameManager.instance = undefined
}
}
}
12 changes: 11 additions & 1 deletion src/managers/SceneManager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Scene } from "three"

import { addFrameListener, removeFrameListener } from "../eventbus/events/frame"
import BallManager from "./models/BallManager"
import FieldManager from "./models/FieldManager"
import PlayerManager from "./models/PlayerManager"
Expand All @@ -22,9 +23,11 @@ export default class SceneManager {
this.ball = ball
this.field = field
this.players = players

addFrameListener(this.update)
}

update() {
private readonly update = () => {
for (const player of this.players) {
if (player.carGroup.position.y < 0) {
player.carGroup.visible = false
Expand All @@ -50,4 +53,11 @@ export default class SceneManager {
SceneManager.instance = new SceneManager(options)
return SceneManager.instance
}
static destruct() {
const { instance } = SceneManager
if (instance) {
removeFrameListener(instance.update)
SceneManager.instance = undefined
}
}
}
Loading

0 comments on commit 948f293

Please sign in to comment.