Python Game Tutorial - The Smiley Crush Game

 Hello Readers,

Welcome to Coding by Learning !!! 😀 

In this tutorial, we look at the code which creates a "Smiley Crush Game" similar to Candy Crush in Python language. 

Here You Go !!

import pygame
import random

# --- Game Setup ---
pygame.init()
WIDTH, HEIGHT = 600, 650   # extra space for score/moves
ROWS, COLS = 8, 8
CANDY_SIZE = WIDTH // COLS
FPS = 60

screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Smiley Crush")

# Fonts for text & smileys
font = pygame.font.SysFont("Arial", 28)
emoji_font = pygame.font.SysFont("Segoe UI Emoji", 48)  # Emoji-friendly font

# Smiley icons (candies)
smileys = ["😀", "😂", "😍", "😎", "😡", "🤢"]

# Create board
board = [[random.choice(smileys) for _ in range(COLS)] for _ in range(ROWS)]

# Score and moves
score = 0
moves = 0

# --- Load Sounds (replace with your own .wav or .ogg files) ---
try:
    click_sound = pygame.mixer.Sound("mouse-click.mp3")
    score_sound = pygame.mixer.Sound("winning.mp3")
except:
    click_sound = None
    score_sound = None


# --- Helper Functions ---
def draw_board():
    """Draw smiley candies on the screen"""
    for row in range(ROWS):
        for col in range(COLS):
            if board[row][col] is not None:
                emoji_surface = emoji_font.render(board[row][col], True, (255, 255, 255))
                rect = emoji_surface.get_rect(center=(
                    col * CANDY_SIZE + CANDY_SIZE // 2,
                    row * CANDY_SIZE + 50 + CANDY_SIZE // 2
                ))
                screen.blit(emoji_surface, rect)
            # Draw grid
            pygame.draw.rect(screen, (0, 0, 0),
                             (col * CANDY_SIZE, row * CANDY_SIZE + 50, CANDY_SIZE, CANDY_SIZE), 2)


def draw_score_moves():
    """Draw score and move counter"""
    score_text = font.render(f"Score: {score}", True, (255, 255, 255))
    moves_text = font.render(f"Moves: {moves}", True, (255, 255, 255))
    screen.blit(score_text, (20, 10))
    screen.blit(moves_text, (WIDTH - 150, 10))


def swap(c1, c2):
    """Swap two candies on the board"""
    r1, c1 = c1
    r2, c2 = c2
    board[r1][c1], board[r2][c2] = board[r2][c2], board[r1][c1]


def find_matches():
    """Find all smileys that are part of a match (3+)"""
    matched = set()

    # Horizontal matches
    for r in range(ROWS):
        for c in range(COLS - 2):
            if board[r][c] == board[r][c + 1] == board[r][c + 2]:
                matched.update([(r, c), (r, c + 1), (r, c + 2)])

    # Vertical matches
    for r in range(ROWS - 2):
        for c in range(COLS):
            if board[r][c] == board[r + 1][c] == board[r + 2][c]:
                matched.update([(r, c), (r + 1, c), (r + 2, c)])

    return matched


def clear_matches(matched):
    """Clear matched smileys (set to None) and update score"""
    global score
    if matched and score_sound:
        score_sound.play()  # play sound when clearing
    for r, c in matched:
        board[r][c] = None
        score += 10   # +10 points per cleared smiley


def apply_gravity():
    """Make smileys fall down into empty spaces"""
    for c in range(COLS):
        empty_row = ROWS - 1
        for r in range(ROWS - 1, -1, -1):
            if board[r][c] is not None:
                board[empty_row][c] = board[r][c]
                if empty_row != r:
                    board[r][c] = None
                empty_row -= 1


def refill_board():
    """Fill empty spaces with new random smileys"""
    for r in range(ROWS):
        for c in range(COLS):
            if board[r][c] is None:
                board[r][c] = random.choice(smileys)


# --- Main Game Loop ---
running = True
clock = pygame.time.Clock()
selected = None  # store first clicked smiley

while running:
    screen.fill((30, 30, 30))  # dark background
    draw_score_moves()
    draw_board()

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        elif event.type == pygame.MOUSEBUTTONDOWN:
            x, y = event.pos
            if y >= 50:  # ignore clicks above the board
                row, col = (y - 50) // CANDY_SIZE, x // CANDY_SIZE

                if selected is None:
                    selected = (row, col)
                    if click_sound:
                        click_sound.play()
                else:
                    # Swap if adjacent
                    r1, c1 = selected
                    r2, c2 = row, col
                    if abs(r1 - r2) + abs(c1 - c2) == 1:
                        swap((r1, c1), (r2, c2))
                        matched = find_matches()
                        if matched:  # valid move
                            moves += 1
                            if click_sound:
                                click_sound.play()
                        else:  # invalid move, swap back
                            swap((r1, c1), (r2, c2))
                    selected = None

    # Handle matches
    matched = find_matches()
    if matched:
        clear_matches(matched)
        apply_gravity()
        refill_board()

    pygame.display.flip()
    clock.tick(FPS)

pygame.quit()

The Code Explanation is available in my YouTube Channel: https://www.youtube.com/@SmartBotSphere




Comments

Popular posts from this blog

VBA Interview questions - screen updating

VBA Interview Questions - Part 2 - Variables and Data types

VBA Interview questions - Part 3 - Array concept