This is a solution to the Hangman game challenge on Frontend Mentor. Frontend Mentor challenges help you improve your coding skills by building realistic projects.
Users should be able to:
- Learn how to play Hangman from the main menu.
- Start a game and choose a category.
- Play Hangman with a random word selected from that category.
- See their current health decrease based on incorrect letter guesses.
- Win the game if they complete the whole word.
- Lose the game if they make eight wrong guesses.
- Pause the game and choose to continue, pick a new category, or quit.
- View the optimal layout for the interface depending on their device's screen size.
- See hover and focus states for all interactive elements on the page.
- Navigate the entire game only using their keyboard.
- Semantic HTML5 markup
- CSS custom properties
- Flexbox
- CSS Grid
- Mobile-first workflow
- TypeScript
- React - JS library
- React Spring - React framework
During this project, I deepened my understanding of responsive design principles and the practical use of CSS Grid and Flexbox to achieve complex layouts. Specifically, I learned how to manipulate grid areas and flex items to align and size elements precisely across various screen sizes. This project also reinforced my TypeScript skills, particularly in leveraging types for props to ensure component interfaces are used correctly.
Additionally, I honed my skills in React, gaining more experience in managing state and effects. Utilizing the useSpring hook from React Spring allowed me to create smooth animations that enhanced the user experience, making the game feel more dynamic and engaging.
Here's a code snippet that illustrates how I used useSpring to animate the hangman health animation as the player loses health:
import { useEffect, useRef } from 'react';
import { useSpring } from 'react-spring';
// In the game, health represents the number of guesses the player has left.
// As the player makes incorrect guesses, the health bar changes color dynamically to reflect the danger.
// This use of React Spring creates a more engaging user experience by visually indicating the game's progress.
const useHealthAnimation = (health, maxHealth) => {
const healthPercentage = (health / maxHealth) * 100;
const prevHealthRef = useRef(health);
const [{ color }, api] = useSpring(() => ({
color: 'var(--dark-navy)',
}));
useEffect(() => {
// Only trigger the glowing effect if health is decreasing
if (health < prevHealthRef.current) {
// I'm particularly proud of this animation sequence that uses a looping effect to draw attention
// to the health bar as it depletes. It's a subtle touch that adds to the game's polish.
api.start({
to: [
{ color: 'rgba(255, 0, 0, .8)', immediate: false },
{ color: 'rgba(255, 137, 0, .8)', immediate: false },
],
loop: true,
reset: true,
config: { duration: 150 },
});
// After the health has decreased, we stop the loop and return the color back to normal
const timeoutId = setTimeout(() => {
api.stop();
api.start({ color: 'var(--dark-navy)', immediate: true });
}, 700);
return () => clearTimeout(timeoutId);
}
prevHealthRef.current = health;
}, [health, api]);
return color;
};
Looking ahead, I aim to focus on mastering state management in React, particularly with complex state logic as seen in games. I also want to continue improving my animation skills, exploring more intricate motion designs with React Spring. In addition, I plan to delve deeper into accessibility, ensuring that all future projects are fully navigable via keyboard and screen readers, providing a seamless experience for all users.
Another area of interest is component design patterns in React, such as compound components and higher-order components, to write more reusable and maintainable code. As I progress, I intend to contribute to open source projects to collaborate with the community and sharpen my problem-solving skills in real-world scenarios.
- Chat GPT - React - Helped me a ton!