Skip to content

Refactor 2 #20

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: refactor-1
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/components/App/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,21 @@ export default function App() {
{gameState === GAME_STATES.GameOver && <GameOver />}
<World />
<Player
top={328}
left={420}
health={playerHealth}
onInteract={setIsLeverUsed}
onCollision={setPlayerHealth}
/>
<Npc left={1608} top={224} />
<CellarDoor isOpen={isCellarDoorOpen} />
<CellarDoor isOpen={isCellarDoorOpen} left={528} top={272} />
<Lever
left={600}
top={264}
used={isLeverUsed}
onInteract={setIsCellarDoorOpen}
/>
<House />
<House left={372} top={192} />
<Fire left={480} top={524} />
<Heart left={320} top={828} />
<Coin left={1152} top={1172} />
Expand Down
82 changes: 35 additions & 47 deletions src/components/CellarDoor/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, FunctionComponent } from "react";
import { useEffect, useRef, FC } from "react";
import { TILE_SETS } from "../../constants";
import "./style.css";

Expand All @@ -7,63 +7,51 @@ const HEIGHT = 64;
const TILE_X = 992;
const TILE_Y = 160;

type CellarDoorProps = { top: number; left: number; isOpen?: boolean };

/*
* TODO:
* - useRef instead of getElementById
* - util function for tile set, tiles and animation
* - create global constants for tile sets and tile size
* - prefer to return early, flip the if condition
* - track state internally
*/
const CellarDoor: FunctionComponent<{ isOpen?: boolean }> = ({
isOpen = false,
}) => {
const CellarDoor: FC<CellarDoorProps> = ({ isOpen = false, top, left }) => {
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
const canvas = document.getElementById(
"cellar-door-canvas"
) as HTMLCanvasElement | null;
const ctx = canvas?.getContext("2d");
const ctx = canvasRef.current?.getContext("2d");

if (!canvasRef.current || !ctx) {
return;
}

if (canvas && ctx) {
canvas.style.left = "528px";
canvas.style.top = "272px";
canvasRef.current.style.left = `${left}px`;
canvasRef.current.style.top = `${top}px`;

const tileSet = new Image();
tileSet.src = TILE_SETS.World;
tileSet.onload = () => {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
const tileSet = new Image();
tileSet.src = TILE_SETS.World;
tileSet.onload = () => {
ctx.clearRect(0, 0, WIDTH, HEIGHT);

if (isOpen) {
ctx.drawImage(
tileSet,
TILE_X + WIDTH,
TILE_Y,
WIDTH,
HEIGHT,
0,
0,
WIDTH,
HEIGHT
);
} else {
ctx.drawImage(
tileSet,
TILE_X,
TILE_Y,
WIDTH,
HEIGHT,
0,
0,
WIDTH,
HEIGHT
);
}
};
}
}, [isOpen]);
ctx.drawImage(
tileSet,
isOpen ? TILE_X + WIDTH : TILE_X,
TILE_Y,
WIDTH,
HEIGHT,
0,
0,
WIDTH,
HEIGHT
);
};
}, [isOpen, left, top]);

return (
<canvas id="cellar-door-canvas" width={WIDTH} height={HEIGHT}></canvas>
<canvas
ref={canvasRef}
id="cellar-door-canvas"
width={WIDTH}
height={HEIGHT}
></canvas>
);
};

Expand Down
123 changes: 46 additions & 77 deletions src/components/Coin/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, FunctionComponent } from "react";
import { useEffect, useRef, FC } from "react";
import { TILE_SIZE, TILE_SETS } from "../../constants";
import "./style.css";

Expand All @@ -8,94 +8,63 @@ const TILE_X = 0;
const TILE_Y = 128;
const ANIMATION_LENGTH = 3;

type CoinProps = { left: number; top: number };

/*
* TODO:
* - useRef instead of getElementById
* - util function for tile set, tiles and animation
* - create global constants for tile sets and tile size
* - prefer to return early, flip the if condition
* - clear interval on component destroy
*/
const Coin: FunctionComponent<{ left: number; top: number }> = ({
left,
top,
}) => {
const Coin: FC<CoinProps> = ({ left, top }) => {
const canvasRef = useRef<HTMLCanvasElement>(null);

useEffect(() => {
const canvas = document.getElementById(
"coin-canvas"
) as HTMLCanvasElement | null;
const ctx = canvas?.getContext("2d");
const ctx = canvasRef.current?.getContext("2d");
let intervalId: number;

if (!canvasRef.current || !ctx) {
return;
}

if (canvas && ctx) {
canvas.style.left = `${left}px`;
canvas.style.top = `${top}px`;
canvasRef.current.style.left = `${left}px`;
canvasRef.current.style.top = `${top}px`;

const tileSet = new Image();
tileSet.src = TILE_SETS.Objects;
tileSet.onload = () => {
let currentFrame = 0;
const tileSet = new Image();
tileSet.src = TILE_SETS.Objects;
tileSet.onload = () => {
let currentFrame = 0;

setInterval(() => {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
intervalId = window.setInterval(() => {
ctx.clearRect(0, 0, WIDTH, HEIGHT);

if (currentFrame === 0) {
ctx.drawImage(
tileSet,
TILE_X,
TILE_Y,
WIDTH,
HEIGHT,
0,
0,
WIDTH,
HEIGHT
);
} else if (currentFrame === 1) {
ctx.drawImage(
tileSet,
TILE_X + WIDTH,
TILE_Y,
WIDTH,
HEIGHT,
0,
0,
WIDTH,
HEIGHT
);
} else if (currentFrame === 2) {
ctx.drawImage(
tileSet,
TILE_X + WIDTH * 2,
TILE_Y,
WIDTH,
HEIGHT,
0,
0,
WIDTH,
HEIGHT
);
} else if (currentFrame === 3) {
ctx.drawImage(
tileSet,
TILE_X + WIDTH * 3,
TILE_Y,
WIDTH,
HEIGHT,
0,
0,
WIDTH,
HEIGHT
);
}
ctx.drawImage(
tileSet,
TILE_X + WIDTH * currentFrame,
TILE_Y,
WIDTH,
HEIGHT,
0,
0,
WIDTH,
HEIGHT
);

currentFrame =
currentFrame === ANIMATION_LENGTH ? 0 : currentFrame + 1;
}, 100);
};
}
currentFrame = currentFrame === ANIMATION_LENGTH ? 0 : currentFrame + 1;
}, 100);
};

return () => {
clearInterval(intervalId);
};
}, [left, top]);

return <canvas id="coin-canvas" width={WIDTH} height={HEIGHT}></canvas>;
return (
<canvas
ref={canvasRef}
id="coin-canvas"
width={WIDTH}
height={HEIGHT}
></canvas>
);
};

export default Coin;
Loading