DEV Community

Mate Technologies
Mate Technologies

Posted on

๐ŸŽฎ Building an Animated Hangman Game in Python (Tkinter) โ€” Step by Step

In this tutorial, weโ€™ll build a Hangman game with animations, dark mode, and a modern UI using Pythonโ€™s built-in Tkinter library.

No prior game dev experience required โ€” weโ€™ll build everything incrementally.

๐Ÿงฐ What Weโ€™ll Use

Python 3

Tkinter (GUI framework)

ttk (styled widgets)

sv-ttk (modern light/dark themes)

๐Ÿ“ฆ Step 1: Imports and Dependencies

Letโ€™s start by importing everything we need.

import sys
import os
import random
import tkinter as tk
from tkinter import ttk, messagebox
import sv_ttk
Enter fullscreen mode Exit fullscreen mode

Why these imports?

random โ†’ choose random words

tkinter โ†’ build the GUI

ttk โ†’ nicer looking widgets

messagebox โ†’ pop-up dialogs

sv_ttk โ†’ modern light/dark theme support

๐Ÿง  Step 2: Helper Functions
Loading files correctly (even after packaging)

def resource_path(file_name):
    base_path = getattr(sys, "_MEIPASS", os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(base_path, file_name)
Enter fullscreen mode Exit fullscreen mode

This helper ensures file paths work correctly if you later bundle the app with tools like PyInstaller.

Updating the status bar

def set_status(msg):
    status_var.set(msg)
    root.update_idletasks()
Enter fullscreen mode Exit fullscreen mode

This updates the status message at the bottom of the app in real time.

๐ŸชŸ Step 3: Create the Main App Window

root = tk.Tk()
root.title("Animated Hangman Game")
root.geometry("700x850")
sv_ttk.set_theme("light")
Enter fullscreen mode Exit fullscreen mode

Tk() creates the window

geometry() sets its size

sv_ttk.set_theme() applies a modern theme

๐ŸŒ Step 4: Global Game State

Weโ€™ll store our game data here.

dark_mode_var = tk.BooleanVar(value=False)

word_list = ["PYTHON", "HANGMAN", "COMPUTER", "AI", "PROGRAMMING", "DEVELOPER"]

current_word = ""
guessed_letters = set()
wrong_guesses = 0
max_wrong = 6
Enter fullscreen mode Exit fullscreen mode

UI-bound variables

display_word_var = tk.StringVar()
status_var = tk.StringVar(value="Ready")
lives_var = tk.StringVar(value=f"Lives: {max_wrong}")
Enter fullscreen mode Exit fullscreen mode

StringVar allows Tkinter widgets to update automatically when values change.

๐ŸŒ— Step 5: Dark Mode Toggle

def toggle_theme():
    bg = "#2E2E2E" if dark_mode_var.get() else "#FFFFFF"
    fg = "white" if dark_mode_var.get() else "black"

    root.configure(bg=bg)

    for w in ["TFrame", "TLabel", "TLabelframe", "TLabelframe.Label", "TCheckbutton"]:
        style.configure(w, background=bg, foreground=fg)

    guess_entry.configure(background=bg, foreground=fg)
    hangman_canvas.configure(bg=bg)
Enter fullscreen mode Exit fullscreen mode

This dynamically switches background and text colors when the checkbox is toggled.

๐Ÿ” Step 6: Starting a New Game

def start_new_game():
    global current_word, guessed_letters, wrong_guesses

    current_word = random.choice(word_list)
    guessed_letters = set()
    wrong_guesses = 0

    update_display_word()
    lives_var.set(f"Lives: {max_wrong}")
    draw_hangman(animated=False)

    set_status("New game started! Guess a letter.")
Enter fullscreen mode Exit fullscreen mode

This resets everything:

Picks a new word

Clears guesses

Resets the hangman drawing

๐Ÿ”ค Step 7: Updating the Word Display

def update_display_word():
    display = " ".join(
        c if c in guessed_letters else "_" for c in current_word
    )
    display_word_var.set(display)
Enter fullscreen mode Exit fullscreen mode

Example output:

P Y T H O N


Win condition

    if "_" not in display:
        set_status("Congratulations! You guessed the word!")
        messagebox.showinfo("Winner!", f"You correctly guessed: {current_word}")
Enter fullscreen mode Exit fullscreen mode

โ“ Step 8: Guessing a Letter

def guess_letter():
    global wrong_guesses

    letter = guess_var.get().strip().upper()
    guess_var.set("")
Enter fullscreen mode Exit fullscreen mode

Validate input

    if not letter or len(letter) != 1 or not letter.isalpha():
        set_status("Please enter a single letter.")
        return
Enter fullscreen mode Exit fullscreen mode

Prevent duplicate guesses

    if letter in guessed_letters:
        set_status(f"You already guessed '{letter}'.")
        return
Enter fullscreen mode Exit fullscreen mode

Handle correct vs wrong guesses

    guessed_letters.add(letter)

    if letter not in current_word:
        wrong_guesses += 1
        lives_var.set(f"Lives: {max_wrong - wrong_guesses}")
        draw_hangman(animated=True)
Enter fullscreen mode Exit fullscreen mode

Game over logic

        if wrong_guesses >= max_wrong:
            messagebox.showinfo("Game Over", f"The word was: {current_word}")
            start_new_game()
            return

    update_display_word()
Enter fullscreen mode Exit fullscreen mode

๐ŸŽจ Step 9: Drawing the Hangman
Base structure (always drawn)

def draw_hangman(animated=True):
    hangman_canvas.delete("all")

    hangman_canvas.create_line(50, 350, 250, 350, width=3)
    hangman_canvas.create_line(150, 350, 150, 50, width=3)
    hangman_canvas.create_line(150, 50, 300, 50, width=3)
    hangman_canvas.create_line(300, 50, 300, 100, width=3)
Enter fullscreen mode Exit fullscreen mode

Body parts (added per mistake)

    parts = []

    if wrong_guesses >= 1:
        parts.append(("oval", 275, 100, 325, 150))  # Head
    if wrong_guesses >= 2:
        parts.append(("line", 300, 150, 300, 250))  # Body
Enter fullscreen mode Exit fullscreen mode

๐ŸŽž Step 10: Animating the Hangman

def animate_parts(parts, idx=0):
    if idx >= len(parts):
        return
Enter fullscreen mode Exit fullscreen mode

Animated head

    if parts[idx][0] == "oval":
        hangman_canvas.create_oval(*parts[idx][1:], width=3)
Enter fullscreen mode Exit fullscreen mode

Animated limbs

    else:
        x1, y1, x2, y2 = parts[idx][1:]
        hangman_canvas.create_line(x1, y1, x2, y2, width=3)
Enter fullscreen mode Exit fullscreen mode

Delay before next part

    hangman_canvas.after(400, lambda: animate_parts(parts, idx + 1))
Enter fullscreen mode Exit fullscreen mode

๐ŸŽ› Step 11: UI Layout
Main container

main = ttk.Frame(root, padding=20)
main.pack(expand=True, fill="both")
Enter fullscreen mode Exit fullscreen mode

Canvas

hangman_canvas = tk.Canvas(main, width=400, height=400, bg="white")
hangman_canvas.grid(row=1, column=0, pady=10)
Enter fullscreen mode Exit fullscreen mode

Input & buttons

guess_var = tk.StringVar()

guess_entry = ttk.Entry(main, textvariable=guess_var, font=("Segoe UI", 16), width=5)
guess_entry.grid(row=4, column=0)
Enter fullscreen mode Exit fullscreen mode

ttk.Button(main, text="Guess", command=guess_letter).grid(row=5, column=0)

โ–ถ๏ธ Step 12: Run the App

start_new_game()
root.mainloop()
Enter fullscreen mode Exit fullscreen mode

This starts the game loop and opens the window.

๐ŸŽ‰ Final Result

You now have:

โœ… Animated hangman drawing

๐ŸŒ— Light / Dark mode

๐ŸŽฏ Input validation

๐Ÿง  Game state handling

๐ŸŽจ Modern UI styling

๐Ÿš€ Next Ideas

Add difficulty levels

Load words from a file

Add keyboard input

Track high scores

Package as an .exe

Animated Hangman Game

Top comments (0)