From 90a50af66ae67f15b312a0973fdcc7c9621c8eb9 Mon Sep 17 00:00:00 2001 From: Michael Tintiuc Date: Tue, 11 Oct 2022 18:42:57 +0300 Subject: [PATCH] Refactor 4 --- src/components/App/index.tsx | 11 ++++--- src/components/Player/index.tsx | 47 ++++----------------------- src/components/Player/style.css | 6 ---- src/components/PlayerHealth/index.tsx | 34 +++++++++++++++++++ src/components/PlayerHealth/style.css | 5 +++ src/constants.ts | 3 ++ src/contexts/global.ts | 4 ++- src/hooks/useAnimatedSprite.ts | 4 +-- src/hooks/useSprite.ts | 8 ++--- 9 files changed, 65 insertions(+), 57 deletions(-) create mode 100644 src/components/PlayerHealth/index.tsx create mode 100644 src/components/PlayerHealth/style.css diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index e14f5d6..88e26f2 100644 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { GlobalContext } from "../../contexts"; import World from "../World"; import Player from "../Player"; +import PlayerHealth from "../PlayerHealth"; import Npc from "../Npc"; import Heart from "../Heart"; import Coin from "../Coin"; @@ -10,7 +11,7 @@ import Lever from "../Lever"; import House from "../House"; import Fire from "../Fire"; import GameOver from "../GameOver"; -import { GAME_STATES } from "../../constants"; +import { GAME_STATES, MAX_HEALTH } from "../../constants"; import "./style.css"; /* @@ -22,17 +23,19 @@ export default function App() { const [gameState, setGameState] = useState(GAME_STATES.Game); const [isCellarDoorOpen, setIsCellarDoorOpen] = useState(false); const [isLeverUsed, setIsLeverUsed] = useState(false); - const [playerHealth, setPlayerHealth] = useState(4); + const [playerHealth, setPlayerHealth] = useState(MAX_HEALTH); return (
- + {gameState === GAME_STATES.GameOver && } + diff --git a/src/components/Player/index.tsx b/src/components/Player/index.tsx index 53ede43..4545e01 100644 --- a/src/components/Player/index.tsx +++ b/src/components/Player/index.tsx @@ -12,7 +12,6 @@ const ANIMATION_LENGTH = 3; type PlayerProps = { top: number; left: number; - health: number; onInteract: (isOpen: boolean | ((wasOpen: boolean) => boolean)) => void; onCollision: (health: number | ((prev: number) => number)) => void; }; @@ -27,23 +26,14 @@ type PlayerProps = { * - create util function for collisions */ let invulnerable = false; -const Player: FC = ({ - health, - onInteract, - onCollision, - top, - left, -}) => { +const Player: FC = ({ onInteract, onCollision, top, left }) => { const canvasRef = useRef(null); - const { setGameState } = useContext(GlobalContext); + const { setGameState, playerHealth } = useContext(GlobalContext); useEffect(() => { const fireCanvas = document.getElementById( "fire-canvas" ) as HTMLCanvasElement | null; - const healthCanvas = document.getElementById( - "health-canvas" - ) as HTMLCanvasElement | null; const heartCanvas = document.getElementById( "heart-canvas" ) as HTMLCanvasElement | null; @@ -51,28 +41,6 @@ const Player: FC = ({ "coin-canvas" ) as HTMLCanvasElement | null; - if (healthCanvas) { - const ctx = healthCanvas.getContext("2d"); - if (ctx) { - const tileSet = new Image(); - tileSet.src = TILE_SETS.Objects; - tileSet.onload = () => { - ctx.clearRect(0, 0, 30, 26); - if (health === 4) { - ctx.drawImage(tileSet, 128, 4, 30, 26, 0, 0, 30, 26); - } else if (health === 3) { - ctx.drawImage(tileSet, 160, 4, 30, 26, 0, 0, 30, 26); - } else if (health === 2) { - ctx.drawImage(tileSet, 192, 4, 30, 26, 0, 0, 30, 26); - } else if (health === 1) { - ctx.drawImage(tileSet, 224, 4, 30, 26, 0, 0, 30, 26); - } else if (health === 0) { - ctx.drawImage(tileSet, 256, 4, 30, 26, 0, 0, 30, 26); - } - }; - } - } - if (!canvasRef.current) { return; } @@ -164,8 +132,8 @@ const Player: FC = ({ return; } - if (health > 0) { - if (health < 4) { + if (playerHealth > 0) { + if (playerHealth < 4) { if ( heartCanvas && parseInt(canvasRef.current.style.left || "0") + 6 <= @@ -177,7 +145,7 @@ const Player: FC = ({ parseInt(canvasRef.current.style.top || "0") + 36 >= parseInt(heartCanvas.style.top || "0") + 16 ) { - onCollision((health) => Math.min(4, health + 1)); + onCollision((playerHealth) => Math.min(4, playerHealth + 1)); heartCanvas.remove(); } } @@ -254,7 +222,7 @@ const Player: FC = ({ )}px`; } - onCollision((health) => Math.max(0, health - 1)); + onCollision((playerHealth) => Math.max(0, playerHealth - 1)); invulnerable = true; canvasRef.current.style.filter = "brightness(6)"; @@ -347,7 +315,7 @@ const Player: FC = ({ } }; }; - }, [onInteract, onCollision, health, setGameState, top, left]); + }, [onInteract, onCollision, playerHealth, setGameState, top, left]); return ( <> @@ -357,7 +325,6 @@ const Player: FC = ({ width={WIDTH} height={HEIGHT} > - ); }; diff --git a/src/components/Player/style.css b/src/components/Player/style.css index 51d62d6..b09f201 100644 --- a/src/components/Player/style.css +++ b/src/components/Player/style.css @@ -1,9 +1,3 @@ #player-canvas { z-index: 99; } - -#health-canvas { - z-index: 99; - top: calc((1536px - 100vh) / 2 + 8px); - left: calc((2048px - 100vw) / 2 + 8px); -} diff --git a/src/components/PlayerHealth/index.tsx b/src/components/PlayerHealth/index.tsx new file mode 100644 index 0000000..e669ca4 --- /dev/null +++ b/src/components/PlayerHealth/index.tsx @@ -0,0 +1,34 @@ +import { useRef, useContext, FC } from "react"; +import { TILE_SIZE, TILE_SETS, MAX_HEALTH } from "../../constants"; +import { GlobalContext } from "../../contexts"; +import { useSprite } from "../../hooks"; +import "./style.css"; + +const WIDTH = TILE_SIZE; +const HEIGHT = TILE_SIZE; +const TILE_X = 128; + +const PlayerHealth: FC = () => { + const canvasRef = useRef(null); + const { playerHealth } = useContext(GlobalContext); + + useSprite({ + canvasRef, + tileSet: TILE_SETS.Objects, + width: WIDTH, + height: HEIGHT, + tileX: TILE_X + WIDTH * (MAX_HEALTH - playerHealth), + tileY: 0, + }); + + return ( + + ); +}; + +export default PlayerHealth; diff --git a/src/components/PlayerHealth/style.css b/src/components/PlayerHealth/style.css new file mode 100644 index 0000000..1e5b27d --- /dev/null +++ b/src/components/PlayerHealth/style.css @@ -0,0 +1,5 @@ +#health-canvas { + z-index: 99; + top: calc((1536px - 100vh) / 2 + 32px); + left: calc((2048px - 100vw) / 2 + 8px); +} diff --git a/src/constants.ts b/src/constants.ts index 5073bea..75f666c 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -13,3 +13,6 @@ export enum TILE_SETS { export const TILE_SIZE = 32; export const WORLD_WIDTH = 2048; export const WORLD_HEIGHT = 1536; + +export const MAX_HEALTH = 4; +export const MIN_HEALTH = 0; diff --git a/src/contexts/global.ts b/src/contexts/global.ts index 4c5a3a0..3c7aa8f 100644 --- a/src/contexts/global.ts +++ b/src/contexts/global.ts @@ -1,12 +1,14 @@ import { createContext } from "react"; -import { GAME_STATES } from "../constants"; +import { GAME_STATES, MAX_HEALTH } from "../constants"; export type GlobalContextType = { readonly gameState: GAME_STATES; setGameState(newState: GAME_STATES): void; + playerHealth: number; }; export const GlobalContext = createContext({ gameState: GAME_STATES.Game, setGameState: () => {}, + playerHealth: MAX_HEALTH, }); diff --git a/src/hooks/useAnimatedSprite.ts b/src/hooks/useAnimatedSprite.ts index 8538c2b..3d88a67 100644 --- a/src/hooks/useAnimatedSprite.ts +++ b/src/hooks/useAnimatedSprite.ts @@ -15,8 +15,8 @@ export const useAnimatedSprite = (props: AnimatedSpriteProps) => { return; } - props.canvasRef.current.style.left = `${props.left}px`; - props.canvasRef.current.style.top = `${props.top}px`; + props.left && (props.canvasRef.current.style.left = `${props.left}px`); + props.top && (props.canvasRef.current.style.top = `${props.top}px`); const sprite = new Image(); sprite.src = props.tileSet; diff --git a/src/hooks/useSprite.ts b/src/hooks/useSprite.ts index d1a6397..f4a0790 100644 --- a/src/hooks/useSprite.ts +++ b/src/hooks/useSprite.ts @@ -8,8 +8,8 @@ export type SpriteProps = { height: number; tileX: number; tileY: number; - left: number; - top: number; + left?: number; + top?: number; }; export const useSprite = (props: SpriteProps) => { @@ -20,8 +20,8 @@ export const useSprite = (props: SpriteProps) => { return; } - props.canvasRef.current.style.left = `${props.left}px`; - props.canvasRef.current.style.top = `${props.top}px`; + props.left && (props.canvasRef.current.style.left = `${props.left}px`); + props.top && (props.canvasRef.current.style.top = `${props.top}px`); const sprite = new Image(); sprite.src = props.tileSet;