Skip to content

test 1 #17

Description

@jesterking5

jester_game.py

Improved prototype: event-based actions, timer resets, clamped movement, small refactor.

import pygame
import sys

pygame.init()
WIDTH, HEIGHT = 800, 600
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Jester's Tale - Prototype")

FONT = pygame.font.SysFont("consolas", 24)
BIG_FONT = pygame.font.SysFont("consolas", 40)

CLOCK = pygame.time.Clock()

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (200, 40, 40)
YELLOW = (230, 210, 80)
BLUE = (80, 120, 230)
GRAY = (80, 80, 80)
GREEN = (60, 160, 60)

Game states

STATE_WAKE = "wake"
STATE_CLEARING = "clearing"
STATE_COIN_EVENT = "coin_event"
STATE_BLACKOUT = "blackout"
STATE_AFTER_BLACKOUT = "after_blackout"
STATE_SLOT = "slot"
STATE_PATH_CHOICE = "path_choice"
STATE_PATH_LOCKED = "path_locked"

state = STATE_WAKE

Jester

jester = pygame.Rect(WIDTH // 2 - 20, HEIGHT // 2, 40, 60)
jester_color = GREEN

Objects

coin_rect = pygame.Rect(WIDTH // 2 - 10, HEIGHT // 2 + 80, 20, 20)
coin_visible = False
coin_obtained = False

serpent_rect = pygame.Rect(WIDTH // 2 - 80, HEIGHT // 2 - 40, 160, 60)
serpent_visible = False

slot_rect = pygame.Rect(WIDTH // 2 - 25, HEIGHT // 2 + 40, 50, 10)
slot_active = False

door_rect = pygame.Rect(WIDTH // 2 - 80, HEIGHT // 2 - 150, 160, 200)
door_open = False

Paths

path1_rect = pygame.Rect(WIDTH // 2 - 260, HEIGHT // 2 - 100, 140, 200)
path2_rect = pygame.Rect(WIDTH // 2 - 70, HEIGHT // 2 - 100, 140, 200)
path3_rect = pygame.Rect(WIDTH // 2 + 120, HEIGHT // 2 - 100, 140, 200)
chosen_path = None

Timers (frame counts)

wake_timer = 0
coin_event_timer = 0
blackout_timer = 0

Input action flags (set from event loop)

action_space = False
action_e = False

def draw_text(text, font, color, x, y, center=False):
surf = font.render(text, True, color)
rect = surf.get_rect()
if center:
rect.center = (x, y)
else:
rect.topleft = (x, y)
WIN.blit(surf, rect)

def clamp_rect_to_window(r: pygame.Rect):
r.x = max(0, min(WIDTH - r.width, r.x))
r.y = max(0, min(HEIGHT - r.height, r.y))

def change_state(new_state):
global state, wake_timer, coin_event_timer, blackout_timer
state = new_state
# reset state-specific timers
wake_timer = 0
coin_event_timer = 0
blackout_timer = 0
# Optionally reset or reposition the jester when entering some states
if new_state in (STATE_CLEARING, STATE_AFTER_BLACKOUT, STATE_SLOT, STATE_PATH_CHOICE):
jester.center = (WIDTH // 2, HEIGHT // 2 + 120)
clamp_rect_to_window(jester)

def handle_wake():
global coin_visible, wake_timer
WIN.fill(BLACK)
wake_timer += 1

draw_text("...", BIG_FONT, WHITE, WIDTH // 2, HEIGHT // 2 - 40, center=True)
draw_text("Jester wakes up in a place he doesn't know.", FONT, WHITE, 80, 400)
draw_text("Press SPACE to stand up.", FONT, WHITE, 80, 430)

# Use event-driven SPACE press
if action_space:
    coin_visible = True
    change_state(STATE_CLEARING)

def handle_clearing():
global coin_obtained, state
WIN.fill((20, 40, 60))

# Simple "forest" background
for x in range(0, WIDTH, 80):
    pygame.draw.rect(WIN, (10, 30, 40), (x, 0, 40, HEIGHT))

# Jester
pygame.draw.rect(WIN, jester_color, jester)

# Coin slot & coin
pygame.draw.rect(WIN, GRAY, slot_rect)
if coin_visible and not coin_obtained:
    pygame.draw.rect(WIN, YELLOW, coin_rect)

draw_text("Jester: 'Where... am I? Why can't I remember anything?'", FONT, WHITE, 40, 40)
draw_text("Use arrow keys to move. Stand on the coin and press E to touch it.", FONT, WHITE, 40, 70)

keys = pygame.key.get_pressed()
speed = 3
if keys[pygame.K_LEFT]:
    jester.x -= speed
if keys[pygame.K_RIGHT]:
    jester.x += speed
if keys[pygame.K_UP]:
    jester.y -= speed
if keys[pygame.K_DOWN]:
    jester.y += speed

clamp_rect_to_window(jester)

# Touch coin (use event-based E press)
if coin_visible and not coin_obtained and jester.colliderect(coin_rect) and action_e:
    change_state(STATE_COIN_EVENT)

def handle_coin_event():
global serpent_visible, coin_obtained, coin_visible, coin_event_timer
WIN.fill((40, 10, 10))

# Jester & coin (bloody)
pygame.draw.rect(WIN, jester_color, jester)
pygame.draw.rect(WIN, RED, coin_rect)

draw_text("The ground shakes as Jester touches the coin...", FONT, WHITE, 40, 40)
draw_text("A giant serpent rises from the earth!", FONT, WHITE, 40, 70)

serpent_visible = True
pygame.draw.rect(WIN, (0, 150, 0), serpent_rect)

draw_text("Everything goes black...", FONT, RED, 40, 110)
coin_event_timer += 1
# wait ~2 seconds (assuming 60 fps)
if coin_event_timer > 120:
    # mark coin as obtained now that event has played
    coin_obtained = True
    coin_visible = False
    change_state(STATE_BLACKOUT)

def handle_blackout():
global blackout_timer
WIN.fill(BLACK)
draw_text("TAKE A NAP FOR A SECOND, JESTER.", BIG_FONT, RED, WIDTH // 2, HEIGHT // 2, center=True)
blackout_timer += 1
# ~2 seconds blackout
if blackout_timer > 120:
change_state(STATE_AFTER_BLACKOUT)

def handle_after_blackout():
global serpent_visible, slot_active
WIN.fill((20, 40, 60))

# Background
for x in range(0, WIDTH, 80):
    pygame.draw.rect(WIN, (10, 30, 40), (x, 0, 40, HEIGHT))

# Jester
pygame.draw.rect(WIN, jester_color, jester)

# Dead serpent (simple)
serpent_visible = True
pygame.draw.rect(WIN, (0, 80, 0), serpent_rect)
pygame.draw.line(WIN, RED, (serpent_rect.left, serpent_rect.centery),
                 (serpent_rect.right, serpent_rect.centery), 4)

draw_text("Jester wakes up. The giant serpent is dead beside him.", FONT, WHITE, 40, 40)
draw_text("There's a bloody coin in his hand.", FONT, WHITE, 40, 70)
draw_text("[You got: BLOODY COIN]", FONT, RED, 40, 100)

draw_text("Jester: 'I... I didn't do this... I couldn't have...'", FONT, WHITE, 40, 140)
draw_text("Press SPACE to move toward the coin slot.", FONT, WHITE, 40, 180)

# Move slowly until player hits SPACE; event-driven SPACE triggers moving to slot state
keys = pygame.key.get_pressed()
speed = 2
if keys[pygame.K_LEFT]:
    jester.x -= speed
if keys[pygame.K_RIGHT]:
    jester.x += speed
if keys[pygame.K_UP]:
    jester.y -= speed
if keys[pygame.K_DOWN]:
    jester.y += speed

clamp_rect_to_window(jester)

if action_space:
    slot_active = True
    change_state(STATE_SLOT)

def handle_slot():
global door_open
WIN.fill((20, 40, 60))

# Background
for x in range(0, WIDTH, 80):
    pygame.draw.rect(WIN, (10, 30, 40), (x, 0, 40, HEIGHT))

pygame.draw.rect(WIN, jester_color, jester)
pygame.draw.rect(WIN, GRAY, slot_rect)

draw_text("Jester can barely move, but he reaches the slot.", FONT, WHITE, 40, 40)
draw_text("Press E to place the BLOODY COIN into the slot.", FONT, WHITE, 40, 70)

keys = pygame.key.get_pressed()
speed = 1.5  # heavy movement
if keys[pygame.K_LEFT]:
    jester.x -= speed
if keys[pygame.K_RIGHT]:
    jester.x += speed
if keys[pygame.K_UP]:
    jester.y -= speed
if keys[pygame.K_DOWN]:
    jester.y += speed

clamp_rect_to_window(jester)

if jester.colliderect(slot_rect) and action_e:
    door_open = True
    change_state(STATE_PATH_CHOICE)

def handle_path_choice():
global chosen_path
WIN.fill((10, 10, 20))

# Door
pygame.draw.rect(WIN, GRAY, door_rect)
draw_text("The ground opens. A door appears.", FONT, WHITE, 40, 40)
draw_text("Inside, three paths glow. Only one can be chosen.", FONT, WHITE, 40, 70)
draw_text("Walk into a path to choose it. The others will close.", FONT, RED, 40, 100)

# Paths
pygame.draw.rect(WIN, YELLOW, path1_rect)
pygame.draw.rect(WIN, BLUE, path2_rect)
pygame.draw.rect(WIN, RED, path3_rect)

draw_text("Soft Glow", FONT, BLACK, path1_rect.centerx - 50, path1_rect.centery - 10)
draw_text("Cold Echo", FONT, WHITE, path2_rect.centerx - 50, path2_rect.centery - 10)
draw_text("Red Pulse", FONT, WHITE, path3_rect.centerx - 50, path3_rect.centery - 10)

pygame.draw.rect(WIN, jester_color, jester)

keys = pygame.key.get_pressed()
speed = 3
if keys[pygame.K_LEFT]:
    jester.x -= speed
if keys[pygame.K_RIGHT]:
    jester.x += speed
if keys[pygame.K_UP]:
    jester.y -= speed
if keys[pygame.K_DOWN]:
    jester.y += speed

clamp_rect_to_window(jester)

if jester.colliderect(path1_rect):
    chosen_path = "soft_glow"
    change_state(STATE_PATH_LOCKED)
elif jester.colliderect(path2_rect):
    chosen_path = "cold_echo"
    change_state(STATE_PATH_LOCKED)
elif jester.colliderect(path3_rect):
    chosen_path = "red_pulse"
    change_state(STATE_PATH_LOCKED)

def handle_path_locked():
WIN.fill(BLACK)

if chosen_path == "soft_glow":
    msg = "You chose the Soft Glow path."
    color = YELLOW
elif chosen_path == "cold_echo":
    msg = "You chose the Cold Echo path."
    color = BLUE
elif chosen_path == "red_pulse":
    msg = "You chose the Red Pulse path."
    color = RED
else:
    msg = "You chose a path."
    color = WHITE

draw_text(msg, BIG_FONT, color, WIDTH // 2, HEIGHT // 2 - 40, center=True)
draw_text("The other two paths slam shut behind you.", FONT, WHITE, 80, 360)
draw_text("(This is the end of the prototype for now.)", FONT, WHITE, 80, 390)

def main():
global action_space, action_e
change_state(STATE_WAKE)
while True:
CLOCK.tick(60)

    # Reset action flags each frame; they are set true on KEYDOWN events
    action_space = False
    action_e = False

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        # Use KEYDOWN for one-off actions so the player doesn't have to hold the key
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                action_space = True
            if event.key == pygame.K_e:
                action_e = True

    if state == STATE_WAKE:
        handle_wake()
    elif state == STATE_CLEARING:
        handle_clearing()
    elif state == STATE_COIN_EVENT:
        handle_coin_event()
    elif state == STATE_BLACKOUT:
        handle_blackout()
    elif state == STATE_AFTER_BLACKOUT:
        handle_after_blackout()
    elif state == STATE_SLOT:
        handle_slot()
    elif state == STATE_PATH_CHOICE:
        handle_path_choice()
    elif state == STATE_PATH_LOCKED:
        handle_path_locked()

    pygame.display.flip()

if name == "main":
main()

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions