Skip to content

Commit

Permalink
feat: tried adding game
Browse files Browse the repository at this point in the history
  • Loading branch information
DemoTheMann committed Mar 22, 2024
1 parent 1efb2ef commit 96df2e0
Show file tree
Hide file tree
Showing 26 changed files with 456 additions and 138 deletions.
14 changes: 14 additions & 0 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"react-qr-reader-es6": "^2.2.1-2",
"react-router": "^6.21.3",
"react-router-dom": "^6.22.1",
"yup": "^1.3.3"
"yup": "^1.3.3",
"phaser": "^3.80.1"
},
"devDependencies": {
"@testing-library/react": "^14.1.2",
Expand Down
Binary file added client/public/assets/game/javelin/gauge.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added client/public/assets/game/runner/audio/tap.mp3
Binary file not shown.
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.
Binary file added client/public/assets/game/runner/flag.png
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.
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.
File renamed without changes
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed client/public/assets/img/game/runner/RunAnim.gif
Binary file not shown.
Binary file not shown.
Binary file removed client/public/assets/img/game/runner/WinAnim.gif
Binary file not shown.
3 changes: 3 additions & 0 deletions client/src/components/game/EventBus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Phaser from "phaser";

export const EventBus = new Phaser.Events.EventEmitter();
21 changes: 21 additions & 0 deletions client/src/components/game/JavelinThrowGame.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useEffect, useRef } from "react";
import StartGame from "./main";
// import { EventBus } from "./EventBus";

export interface IRefRunnerGame {
game: Phaser.Game | null;
}

const JavelinThrowGame = () => {
const gameRef = useRef<Phaser.Game | null>(null);

useEffect(() => {
if (gameRef.current === null) {
gameRef.current = StartGame("game-container");
}
});

return <div id="game-container"></div>;
};

export default JavelinThrowGame;
159 changes: 24 additions & 135 deletions client/src/components/game/RunnerGame.tsx
Original file line number Diff line number Diff line change
@@ -1,147 +1,36 @@
import { motion } from "framer-motion";
import { useState, useEffect } from "react";
import { APIHandler } from "../../utils/api/api-handler";
import { useAuth } from "../../hooks/useAuth";
import React, { useEffect, useRef } from "react";
import StartGame from "./main";
import { EventBus } from "./EventBus";

interface Click {
x: number;
y: number;
export interface IRefRunnerGame {
game: Phaser.Game | null;
timer: number | null;
}

const RunnerGame = () => {
const { token } = useAuth();
const [clicks, setClicks] = useState<Click[]>([]);
const [isStarting, setIsStarting] = useState<boolean>(false);
const [gameOver, setGameOver] = useState<boolean>(false);
const [score, setScore] = useState<number>(0);
const maxClicks = 6;
const RunnerGame = ({
setTime,
}: {
setTime: React.Dispatch<React.SetStateAction<number>>;
}) => {
const gameRef = useRef<Phaser.Game | null>(null);

const handleClick = (e: React.MouseEvent<HTMLElement>) => {
setIsStarting(true);
const newClick = { x: e.clientX, y: e.clientY };

const newClicks = [...clicks, newClick];

if (newClicks.length > maxClicks) {
newClicks.splice(0, newClicks.length - maxClicks);
}

setClicks(newClicks);

if (!gameOver) {
setScore((prevScore) => prevScore + 1);
useEffect(() => {
if (gameRef.current === null) {
gameRef.current = StartGame("game-container");
}

setTimeout(() => {
setClicks((prevClicks) => prevClicks.slice(1));
}, 3000);
};
const timerListener = (timer: number) => {
setTime(timer);
};

useEffect(() => {
setTimeout(() => {
setGameOver(true);
APIHandler<any>("/my/flami/training", false, "PATCH", {
worked_stat: "speed"
}, token)
}, 9000);
}, []);
EventBus.on("timer", timerListener);

return (
<div
className="h-[calc(100%-3rem)] relative bg-tree-poppy-300 overflow-hidden"
onClick={handleClick}
>
{isStarting ? (
<div className="text-white">Start</div>
) : (
<div className="text-white">Pas start</div>
)}
{clicks.map((click, index) => (
<motion.img
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ ease: "easeIn", duration: 0.2 }}
key={index}
className={`w-16 h-16 fixed z-10`}
style={{
top: click.y,
left: click.x,
}}
src="/assets/img/game/runner/TapSprite.png"
alt=""
/>
))}
<div
className="h-full bg-alabaster-950"
style={{
clipPath: "circle(25% at 50% 50%)",
}}
>
<div
className={`absolute w-full top-[52%] -z-10 ${
isStarting && !gameOver ? "animate-slide" : ""
} flex`}
>
<img
className="w-full"
loading="lazy"
src="/assets/img/game/runner/PisteDépart.png"
alt=""
/>
<img
className="w-full"
loading="lazy"
src="/assets/img/game/runner/PisteNormale.png"
alt=""
/>
return () => {
EventBus.removeListener("timer", timerListener);
};
});

<img
className="w-full"
loading="lazy"
src="/assets/img/game/runner/PisteNormale.png"
alt=""
/>
<img
className="w-48 h-32 -translate-x-24 -translate-y-4 z-10"
loading="lazy"
src="/assets/img/game/runner/ArrivéeIdle.gif"
alt=""
/>
<img
className="w-full -translate-x-48"
loading="lazy"
src="/assets/img/game/runner/PisteNormale.png"
alt=""
/>
</div>
{isStarting && !gameOver ? (
<>
<img
className="absolute w-100 top-[57%] right-[15%] translate-x-[20%] -translate-y-[50%] -z-10 scale-50"
loading="lazy"
src="/assets/img/game/runner/RunAnim.gif"
alt=""
/>
</>
) : (
<>
<img
className="absolute w-100 top-[57%] -right-[2.5%] -translate-x-[20%] -translate-y-[50%] -z-10 scale-50"
loading="lazy"
src="/assets/img/game/runner/RunPrepAnim.gif"
alt=""
/>
</>
)}
</div>
{gameOver && (
<div className="max-h-min bg-alabaster-950 p-8 text-center fixed z-50 left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 flex items-center justify-center text-4xl font-bold text-alabaster-50">
Bravo tu as été rapide ! Score : {score}
</div>
)}
</div>
);
return <div id="game-container"></div>;
};

export default RunnerGame;
18 changes: 18 additions & 0 deletions client/src/components/game/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Phaser from "phaser";
import { Runner } from "./scenes/Runner";
// import { JavelinThrow } from "./scenes/JavelinThrow";

const config: Phaser.Types.Core.GameConfig = {
type: Phaser.AUTO,
scale: {
mode: Phaser.Scale.RESIZE,
},
parent: "game-container",
scene: [Runner],
};

const StartGame = (parent: string) => {
return new Phaser.Game({ ...config, parent: parent });
};

export default StartGame;
98 changes: 98 additions & 0 deletions client/src/components/game/scenes/JavelinThrow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
export class JavelinThrow extends Phaser.Scene {
private gauge!: Phaser.GameObjects.Image;
private maskGraphics!: Phaser.GameObjects.Graphics;
private maskWidth: number = -250;
private chargeSpeed: number = 2;
private startingGame: boolean = false;
private power: number = 0;

constructor() {
super("JavelinThrow");
}

preload() {
this.load.image("gauge", "assets/javelin/gauge.png");
}

create() {
this.gauge = this.add.image(this.cameras.main.width / 2, 100, "gauge");
this.gauge.displayWidth = 300;
this.gauge.displayHeight = 150;

this.maskGraphics = this.add.graphics();
this.maskGraphics.fillStyle(0x00000);
this.maskGraphics.fillRect(
this.cameras.main.width / 2 + 125,
0,
this.maskWidth,
this.gauge.displayHeight
);

this.input.on("pointerdown", () => {
this.startingGame = true;
});

this.input.on("pointerup", () => {
this.launchJavelin();
this.startingGame = false;
});
}

update() {
if (this.startingGame) {
this.maskWidth += this.chargeSpeed;

if (this.maskWidth > 0) {
return;
}

this.maskGraphics.clear();
this.maskGraphics.fillRect(
this.cameras.main.width / 2 + 125,
0,
this.maskWidth,
this.gauge.displayHeight
);

this.getPosition(this.maskWidth);
}
}

getPosition(position: number) {
switch (true) {
case position >= -250 && position < -192:
this.power = 0;
break;
case position >= -192 && position < -143:
this.power = 25;
break;
case position >= -143 && position < -118:
this.power = 50;
break;
case position >= -118 && position < -92:
this.power = 75;
break;
case position >= -92 && position < -62:
this.power = 99;
break;
case position >= -62 && position < -48:
this.power = 75;
break;
case position >= -48 && position < -34:
this.power = 50;
break;
case position >= -34 && position < -18:
this.power = 25;
break;
case position >= -18 && position <= 0:
this.power = 0;
break;
default:
break;
}
}

launchJavelin() {
console.log("Javelin launched with power:", this.power);
}
}
Loading

0 comments on commit 96df2e0

Please sign in to comment.