Skip to content

Commit

Permalink
new icons for gamepad, faster input timings, score is multiplied by c…
Browse files Browse the repository at this point in the history
…urrent level
  • Loading branch information
ivanquirino committed Sep 22, 2023
1 parent 5c5d0a9 commit 1b6505e
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 21 deletions.
23 changes: 23 additions & 0 deletions src/blockpuzzle/components/ArrowIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import classNames from "classnames";

interface IconProps {
className?: string;
}

const ArrowIcon = ({ className }: IconProps) => {
return (
<svg
className={classNames("h-[32px] w-[32px] text-white group-active:text-black", className)}
fill="currentColor"
version="1.1"
id="Layer_1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
enable-background="new 0 0 512 512"
>
<polygon points="289.7,341.3 289.7,0 204.3,0 204.3,341.3 33.7,170.7 33.7,298.7 247,512 460.3,298.7 460.3,170.7 " />
</svg>
);
};

export default ArrowIcon
2 changes: 1 addition & 1 deletion src/blockpuzzle/components/Game.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ const Game = forwardRef<HTMLDivElement, GameProps>(function Game(props, ref) {
</Fragment>
))
)}
<Gamepad />
</div>
)}
</div>
<Gamepad />
</>
);
});
Expand Down
26 changes: 15 additions & 11 deletions src/blockpuzzle/components/Gamepad.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { useCallback, useEffect, useRef } from "react";
import { MouseEvent, useEffect, useRef } from "react";
import { acceptedKeys, idleInput } from "../constants";
import { useGameStore } from "./GameClient";
import { GameInput } from "../types";
import { clearInterval } from "timers";
import ArrowIcon from "./ArrowIcon"
import { timeout } from "../tools";
import RotateIcon from "./RotateIcon";
import React from "react";

const buttonStyle =
"border-white border-[1px] rounded aspect-square text-center align-middle w-[64px] first:mr-3 flex justify-center items-center text-[32px] active:bg-white active:text-black select-none";
"border-white border-[1px] rounded aspect-square text-center align-middle w-[64px] first:mr-3 flex justify-center items-center text-[32px] active:bg-white active:text-black select-none group";

const isMobile = () => {
return navigator.userAgent.match(/mobile|iphone|android|ipad/i);
Expand Down Expand Up @@ -64,7 +66,7 @@ const Gamepad = () => {
while (isPressed) {
input(inputObj);

await timeout(33);
await timeout(16);
}
},
end: () => {
Expand Down Expand Up @@ -102,7 +104,9 @@ const Gamepad = () => {
};
}, [input]);

const handleClick = (inputObj: GameInput) => () => {
const handleClick = (inputObj: GameInput) => (event: MouseEvent) => {
event.stopPropagation();

if (isMobile() && inputObj.up) {
input(inputObj);
}
Expand All @@ -118,25 +122,25 @@ const Gamepad = () => {
const downClick = handleClick({ ...idleInput, down: true });

return (
<div className="flex justify-between w-full mt-2">
<div className="flex justify-between w-full mt-2 absolute -bottom-[80px]">
<div className="flex">
<button ref={leftRef} className={buttonStyle} onClick={leftClick}>
&lsaquo;
<ArrowIcon className="rotate-90"/>
</button>
<button ref={rightRef} className={buttonStyle} onClick={rightClick}>
&rsaquo;
<ArrowIcon className="-rotate-90" />
</button>
</div>
<div className="flex">
<button ref={upRef} className={buttonStyle} onClick={upClick}>
&#x27F3;
<RotateIcon />
</button>
<button ref={downRef} className={buttonStyle} onClick={downClick}>
&#x2304;
<ArrowIcon />
</button>
</div>
</div>
);
};

export default Gamepad;
export default React.memo(Gamepad);
32 changes: 32 additions & 0 deletions src/blockpuzzle/components/RotateIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import classNames from "classnames";

interface IconProps {
className?: string;
}

const RotateIcon = ({ className }: IconProps) => {
return (
<svg
className={classNames("h-[32px] w-[32px] text-white group-active:text-black", className)}
viewBox="-0.5 0 25 25"
stroke="currentColor"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M14 10.55L18 14.55L22 10.55"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M15.65 18.08C14.3398 19.387 12.6171 20.1993 10.7752 20.3786C8.93336 20.558 7.0863 20.0931 5.54864 19.0634C4.01099 18.0337 2.87786 16.5028 2.34232 14.7314C1.80677 12.96 1.90192 11.0577 2.61154 9.34859C3.32116 7.63947 4.60135 6.22926 6.23407 5.35811C7.86679 4.48697 9.75103 4.20879 11.5658 4.571C13.3806 4.93321 15.0137 5.91327 16.1869 7.34444C17.3601 8.77561 18.0009 10.5693 18 12.4199V14.1499"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);
};

export default RotateIcon;
2 changes: 1 addition & 1 deletion src/blockpuzzle/game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ export function clearCompleteRows(state: State) {

return {
grid: newGrid,
score: state.score + scorePerRow * fullRows.length * fullRows. length,
score: state.score + state.level * scorePerRow * fullRows.length * fullRows.length,
};
}

Expand Down
12 changes: 4 additions & 8 deletions src/blockpuzzle/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,10 @@ const store: (callbacks: GameCallbacks) => StateCreator<State & Actions> =
return spawnBag;
};

const limitedMove = throttle((input: GameInput) => get().move(input), 100, {
leading: true,
});

const limitedDrop = throttle(() => get().drop(), 50, { leading: true });
const limitedRotate = throttle(() => get().rotateClockwise(), 150, {
leading: true,
});
const limitedMove = throttle((input: GameInput) => get().move(input), 50);

const limitedDrop = throttle(() => get().drop(), 30);
const limitedRotate = throttle(() => get().rotateClockwise(), 100);

return {
...getInitialState(),
Expand Down

0 comments on commit 1b6505e

Please sign in to comment.