Skip to content

Commit

Permalink
Merge pull request #19 from Abstractolotl/minigame/clicker-race
Browse files Browse the repository at this point in the history
Clicker Race Minigame
  • Loading branch information
NouCake authored Apr 25, 2024
2 parents 6008e92 + 7314852 commit 9bd9966
Show file tree
Hide file tree
Showing 9 changed files with 385 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
- name: Comment PR
uses: thollander/actions-comment-pull-request@v2
with:
message: |
message: |
The staging environment is now available at [${{ env.STAGING_URL }}](${{ env.STAGING_URL }}).
comment_tag: staging

Expand Down
9 changes: 6 additions & 3 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import TitleScene from './phaser/scenes/title-scene';
import BoardScene from './phaser/scenes/board-scene';
import LobbyScene from './phaser/scenes/lobby-scene';
import AzNopolyGame from './game';
import { RoombaScene } from './phaser/scenes/minigame/roomba-scene';
import { mock } from './util/debug-util';
import { COLOR_BACKGROUND } from './style';

import ShittyShooterScene from './phaser/scenes/minigame/shitty-shooter-scene';
import { RoombaScene } from '@/phaser/scenes/minigame/roomba-scene';
import ShittyShooterScene from '@/phaser/scenes/minigame/shitty-shooter-scene';
import ClickerRaceScene from "@/phaser/scenes/minigame/clicker-race-scene";

import { SETTINGS } from './settings';
import WaterDropScene from './phaser/scenes/minigame/water-drop-scene';

Expand Down Expand Up @@ -71,6 +73,7 @@ window.onload = () => {
game.scene.add('minigame-roomba', new RoombaScene(aznopoly));
game.scene.add('minigame-shitty-shooter', new ShittyShooterScene(aznopoly));
game.scene.add('minigame-water-drop', new WaterDropScene(aznopoly));
game.scene.add('minigame-clicker-race', new ClickerRaceScene(aznopoly));

//Debug
game.scene.add('debug', new DebugScene());
Expand All @@ -88,4 +91,4 @@ window.onload = () => {
Object.assign(window, { game });

}, 250)
};
};
1 change: 0 additions & 1 deletion src/phaser/components/ui/button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ export class AzNopolyButton extends Phaser.GameObjects.Container {
this.alpha = 0;

this.enabled = false;

this.isDown = false;
}

Expand Down
110 changes: 110 additions & 0 deletions src/phaser/components/ui/range-slider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import {COLOR_CONTRAST, COLOR_PRIMARY, FONT_STYLE_BUTTON} from "@/style.ts";

export class AzNopolySlider extends Phaser.GameObjects.Container {

public static preload(scene: Phaser.Scene) {
}

private max: number;
private value = 10;
private graphic!: Phaser.GameObjects.Graphics;

private disabled = false;
private dragging = false;

private onChange: (value: number) => void;

constructor(scene: Phaser.Scene, x: number, y: number, width: number, height: number, max: number, onChange: (value: number) => void) {
super(scene, x + width/2, y + height/2);

this.height = height;
this.width = width;

this.max = max
this.onChange = onChange;

this.graphic = new Phaser.GameObjects.Graphics(scene);

// background
this.graphic.fillStyle(COLOR_PRIMARY);
this.graphic.fillRect(-width/2, -height/2, width, height);

// fill
this.graphic.fillStyle(COLOR_CONTRAST);
this.graphic.fillRect(-width/2 + 5, -height/2 + 5, this.value * (width / this.max) -10, height - 10);

const text = new Phaser.GameObjects.Text(scene, 0, 0, "Refill", FONT_STYLE_BUTTON);
text.setOrigin(0.5, 0.5);

this.add(this.graphic);
this.add(text);

this.setSize(width, height);

this.initDrag()
}

preUpdate(time: number, delta: number) {
this.graphic.clear()

this.graphic.fillStyle(COLOR_PRIMARY);
this.graphic.fillRect(-this.width/2, -this.height/2, this.width, this.height);

// fill
this.graphic.fillStyle(COLOR_CONTRAST);
this.graphic.fillRect(-this.width/2 + 5, -this.height/2 + 5, this.value * (this.width / this.max) -10, this.height - 10);

}

reset(){
this.value = 10;
}

public changeMax(max: number){
this.max = max;
}

public getMax(){
return this.max;
}

public disable(){
this.value = 10;
this.disabled = true;
this.dragging = false;
}

public enable() {
this.disabled = false;
}

private initDrag() {
this.setInteractive({
hitArea: new Phaser.Geom.Rectangle(0, 0, this.height, this.width),
hitAreaCallback: Phaser.Geom.Rectangle.Contains,
useHandCursor: true,
draggable: true
}, Phaser.Geom.Rectangle.Contains);

this.on('dragstart', (event: any) => {
if (this.disabled) return;

this.dragging = true;
});

this.on('drag', (event: any) => {
if (this.disabled) return;
if (!this.dragging) return;

const dragOffset = new Phaser.Math.Vector2((event.x * 1.5) - this.x, event.y - this.y);
this.value = Math.max(10, Math.min(this.max, dragOffset.x / (this.width - 10) * this.max));

this.onChange(this.value);
if (this.value === this.max) {
this.dragging = false;
}
});
}


}
4 changes: 2 additions & 2 deletions src/phaser/scenes/base/base-scene-controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import AzNopolyGame from "../../../game";
import { DynamicPacket } from "../../../types/client";
import AzNopolyGame from "@/game";
import { DynamicPacket } from "@/types/client";


/**
Expand Down
82 changes: 82 additions & 0 deletions src/phaser/scenes/minigame/clicker-race-scene-controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import MinigameSceneController, {ResultData} from "@/phaser/scenes/base/minigame-scene-controller.ts";
import ClickerRaceScene from "@/phaser/scenes/minigame/clicker-race-scene.ts";
import AzNopolyGame from "@/game.ts";

const GAME_TIME = 20000;

export default class ClickerRaceSceneController extends MinigameSceneController {

declare protected scene: ClickerRaceScene;
private schedule: NodeJS.Timeout | null = null;

constructor(scene: ClickerRaceScene, aznopoly: AzNopolyGame) {
super(scene, aznopoly);

this.registerSyncedProp("scene");
this.registerSyncedMethod(this.scene.initPlayer, true);
this.registerSyncedMethod(this.scene.movePlayer, true);
this.registerSyncedMethod(this.scene.stopAllPlayers, true);
this.registerSyncedMethod(this.scene.startTimeBar, true);

this.registerSyncedMethod(this.requestPlayerMove, false);
this.registerSyncedMethod(this.finishedGame, false)
}

onMiniGameStart(): void {
if (!this.aznopoly.isHost) {
return;
}

this.aznopoly.connectedUuids.forEach((uuid, index) => {
this.syncProxy.scene.initPlayer(uuid, index);
})
this.syncProxy.scene.startTimeBar();

this.schedule = setTimeout(() => {
this.syncProxy.scene.stopAllPlayers()

const scores = this.scene.getScore();
const result: ResultData = {
playerWon: Object.keys(scores).sort().slice(0, 1),
sorted: false
}

this.endGame(result);
}, GAME_TIME);
}

public finishedGame() {
if (!this.aznopoly.isHost) {
return;
}

clearTimeout(this.schedule!);

const scores = this.scene.getScore();
const result: ResultData = {
playerWon: Object.keys(scores).sort().slice(0, 1),
sorted: false
}

this.endGame(result);
}

public requestPlayerMove(uuid: string) {
if (!this.aznopoly.isHost) {
return;
}

this.syncProxy.scene.movePlayer(uuid);

}

public onPlayerClick(uuid: string) {
this.syncProxy.requestPlayerMove(uuid);
this.scene.randomInput()
}

public onPlayerFinished() {
this.syncProxy.finishedGame();
}

}
134 changes: 134 additions & 0 deletions src/phaser/scenes/minigame/clicker-race-scene.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import MinigameScene from "@/phaser/scenes/base/minigame-scene.ts";
import ClickerRaceSceneController from "@/phaser/scenes/minigame/clicker-race-scene-controller.ts";
import {TimeBar} from "@/phaser/components/ui/time-bar.ts";
import AzNopolyAvatar from "@/phaser/components/ui/avatar.ts";
import AzNopolyBar from "@/phaser/components/ui/bar.ts";
import AzNopolyPanel from "@/phaser/components/ui/panel.ts";
import {FRAME_PADDING} from "@/style.ts";
import Racer from "@/phaser/scenes/minigame/clicker-racer/racer.ts";
import {AzNopolyButton} from "@/phaser/components/ui/button.ts";
import {AzNopolySlider} from "@/phaser/components/ui/range-slider.ts";

const ACTION_BOUNDS = {
width: 500,
height: 80
}

const PLAYER_SIZE = 50;

const gameBounds = MinigameScene.getGameBounds();
const rightBounds = MinigameScene.getRightBounds();

export default class ClickerRaceScene extends MinigameScene<ClickerRaceSceneController> {

private button!: AzNopolyButton;
private slider!: AzNopolySlider;
private bar!: TimeBar;

private racers: { [uuid: string]: Racer } = {};

preload() {
super.preload();
AzNopolyAvatar.preload(this);
}

init() {
this.controller = new ClickerRaceSceneController(this, this.aznopoly);
}

create() {
super.create();
}

update(time: number, delta: number) {
super.update(time, delta);
}

stopAllPlayers() {
Object.values(this.racers).forEach(racer => {
racer.stop();
});
this.button.disable();
}

getScore() {
const scores: {[key: string]: number} = {};

this.aznopoly.connectedUuids.forEach((uuid, index) => {
scores[uuid] = this.racers[uuid].getProgress()
});

return scores;
}

public initPlayer(uuid: string, position: number) {
let trackWidth = gameBounds.width + rightBounds.width - FRAME_PADDING - PLAYER_SIZE;

const profile = this.aznopoly.getProfile(uuid);
const avatar = new Racer(this, gameBounds.x + FRAME_PADDING, gameBounds.y + FRAME_PADDING + (PLAYER_SIZE + FRAME_PADDING) * position, profile, trackWidth + (PLAYER_SIZE / 2));

this.add.rectangle(avatar.x + (PLAYER_SIZE / 2), avatar.y + (PLAYER_SIZE / 2), trackWidth, 5, 0x000000, 0.5).setOrigin(0, 0)
this.add.existing(avatar);

this.racers[uuid] = avatar;
}

public movePlayer(uuid: string) {
if (this.racers[uuid]) {
this.racers[uuid].move(() => {
this.controller.onPlayerFinished()
});
}
}

public startTimeBar() {
this.bar.resume();
}

public randomInput() {
if (Math.random() > 0.5) {
this.button.setVisible(true)
this.button.enable()
this.slider.disable()
this.slider.setVisible(false)
} else {
this.button.disable()
this.button.setVisible(false)
this.slider.setVisible(true)
this.slider.enable()
this.slider.changeMax(100 + Math.random() * 100)
}
}

protected drawSceneLayout() {
this.add.existing(new AzNopolyBar(this, "Clicker Race"))

const gamePanel = new AzNopolyPanel(this, gameBounds.x, gameBounds.y, (gameBounds.width + rightBounds.width + FRAME_PADDING), gameBounds.height);
this.add.existing(gamePanel);

const actionPanel = new AzNopolyPanel(this, gamePanel.width / 2 - (ACTION_BOUNDS.width / 2), (gameBounds.y / 2) + gameBounds.height - ACTION_BOUNDS.height, ACTION_BOUNDS.width, ACTION_BOUNDS.height)
this.add.existing(actionPanel)

this.button = new AzNopolyButton(this, "Race", actionPanel.x + (FRAME_PADDING * 3), actionPanel.y + FRAME_PADDING, actionPanel.width - (FRAME_PADDING * 6));
this.slider = new AzNopolySlider(this, actionPanel.x + (FRAME_PADDING * 3), actionPanel.y + FRAME_PADDING, actionPanel.width - (FRAME_PADDING * 6), 50, 100, this.onSlider.bind(this))
this.button.setOnClick(() => {
this.controller.onPlayerClick(this.aznopoly.uuid);
});

this.add.existing(this.slider);
this.add.existing(this.button);

this.bar = new TimeBar(this, actionPanel.x, actionPanel.y - (FRAME_PADDING * 3), ACTION_BOUNDS.width, 25, 20000);
this.bar.pause()
this.add.existing(this.bar);

this.randomInput()
}

private onSlider(value: number) {
if (value === this.slider.getMax()) {
this.controller.onPlayerClick(this.aznopoly.uuid);
}
}

}
Loading

0 comments on commit 9bd9966

Please sign in to comment.