1 line
25 KiB
JSON
1 line
25 KiB
JSON
{"repo": "beak2825/mariopipeslidegame", "files": {"10_Round_webMap.json": {"e26b8a1e0f8d5b4bcfc811e5c3dc2d3862bf4570": {"t": 1785604262.089549, "n": 1060, "h": "1d1b8328bc8917f4", "c": "[\n [\n [\n 240,\n 160\n ],\n [\n 320,\n 160\n ]\n ],\n [\n [\n 240,\n 190\n ],\n [\n 320,\n 200\n ]\n ],\n [\n [\n 320,\n 230\n ],\n [\n 240,\n 220\n ]\n ],\n [\n [\n 240,\n 240\n ],\n [\n 320,\n 240\n ]\n ],\n [\n [\n 320,\n 270\n ],\n [\n 240,\n 270\n ]\n ],\n [\n [\n 240,\n 280\n ],\n [\n 320,\n 280\n ]\n ],\n [\n [\n 320,\n 300\n ],\n [\n 240,\n 300\n ]\n ],\n [\n [\n 240,\n 320\n ],\n [\n 320,\n 310\n ]\n ],\n [\n [\n 320,\n 330\n ],\n [\n 240,\n 330\n ]\n ],\n [\n [\n 240,\n 360\n ],\n [\n 320,\n 360\n ]\n ],\n [\n [\n 240,\n 390\n ],\n [\n 160,\n 380\n ]\n ],\n [\n [\n 160,\n 400\n ],\n [\n 80,\n 400\n ]\n ],\n [\n [\n 80,\n 70\n ],\n [\n 160,\n 80\n ]\n ],\n [\n [\n 240,\n 80\n ],\n [\n 320,\n 80\n ]\n ]\n]"}}, "3_Round_webMap.json": {"078cdeaae8b482bda226fca40d164dea2efced60": {"t": 1785604263.8505278, "n": 379, "h": "6fb7b9d0020a517a", "c": "[\n [\n [\n 80,\n 110\n ],\n [\n 160,\n 110\n ]\n ],\n [\n [\n 160,\n 150\n ],\n [\n 240,\n 150\n ]\n ],\n [\n [\n 240,\n 180\n ],\n [\n 160,\n 180\n ]\n ],\n [\n [\n 160,\n 80\n ],\n [\n 240,\n 40\n ]\n ],\n [\n [\n 320,\n 110\n ],\n [\n 240,\n 130\n ]\n ]\n]"}}, "5_Round_webMap.json": {"6e1dde27bfdc643372a8b42b6094089b332eb28f": {"t": 1785604265.0490274, "n": 525, "h": "3a495c8b6220166e", "c": "[\n [\n [\n 80,\n 40\n ],\n [\n 160,\n 40\n ]\n ],\n [\n [\n 80,\n 70\n ],\n [\n 160,\n 70\n ]\n ],\n [\n [\n 160,\n 120\n ],\n [\n 240,\n 180\n ]\n ],\n [\n [\n 320,\n 90\n ],\n [\n 240,\n 80\n ]\n ],\n [\n [\n 80,\n 410\n ],\n [\n 160,\n 410\n ]\n ],\n [\n [\n 160,\n 370\n ],\n [\n 240,\n 360\n ]\n ],\n [\n [\n 240,\n 280\n ],\n [\n 320,\n 240\n ]\n ]\n]"}}, "main.py": {"1ed6b223f5fca02c0cde7b9ddcc8f5e7005599e7": {"t": 1785604267.2789745, "n": 22315, "h": "2c33c8334f4b0510", "c": "import pygame\nimport sys\nimport os\nimport math\nimport time\nimport random\nimport json\n\n# --- Init ---\npygame.init()\n\n# --- Constants ---\nWINDOW_WIDTH = 800\nWINDOW_HEIGHT = 600\nFPS = 60\n\nLINE_COUNT = 4\nLINE_SPACING = 80\n\nMARIO_SIZE = 20\nMARIO_SPEED_DEFAULT = 1.1\nMARIO_SPEED_3 = MARIO_SPEED_DEFAULT * 1.5\nMARIO_SPEED_FAST = MARIO_SPEED_DEFAULT * 4.2\nMARIO_SPEED = MARIO_SPEED_DEFAULT\nSLIDE_SPEED = 2\n\nPIPE_Y = WINDOW_HEIGHT - 40\nMAX_PATH_LENGTH = WINDOW_HEIGHT // 10\nMUSIC_FOLDER = \"music/\"\nSOUNDS_FOLDER = \"sounds/\"\nSPRITES_FOLDER = \"sprites/\"\n# --- Sound Paths ---\nMAIN_MUSIC = MUSIC_FOLDER + \"slides.wav\" # Plays whole time\nSOUND_PATH = SOUNDS_FOLDER + \"scream.wav\" # plays on death\nWIN_SOUND_PATH = SOUNDS_FOLDER + \"win.wav\"\nMARIO_HAHA_PATH = SOUNDS_FOLDER + \"mario_haha.wav\" # plays on win\nDRAW_SOUND_PATH = SOUNDS_FOLDER + \"line_drawing.mp3\"\nSNAP_SOUND_PATH = SOUNDS_FOLDER + \"line_snap.wav\"\nPOP_SOUND_PATH = SOUNDS_FOLDER + \"mario_switch.wav\"\nSPEEDUP_SOUND_PATH = SOUNDS_FOLDER + \"mario_switch.wav\" # figure out how to play at higher pitch with higher speed\n\n# --- Sprites ---\nSPRITE_MARIO_PATH = SPRITES_FOLDER + \"mario.png\"\nSPRITE_STAR_PATH = SPRITES_FOLDER + \"star.png\"\nSPRITE_PIPE_PATH = SPRITES_FOLDER + \"pipe.png\"\nSPRITE_PIRANHA_PATH = SPRITES_FOLDER + \"piranha.png\"\nSPRITE_BG_PATH = SPRITES_FOLDER + \"bg.png\"\n\n\n# --- Configurable Mario Start VLINE ---\nMARIO_SIZE = 32\nSTAR_SIZE = 16\nMARIO_START_VLINE = 0 # 0 = VLINE 1, 1 = VLINE 2, etc.\nVLINE_STAR = None # 1-based index for user, will convert to 0-based\nRANDOMIZE_STAR_LOCATION = False\n\n\n# Load images as Surfaces\nSPRITE_MARIO = pygame.image.load(SPRITE_MARIO_PATH) if os.path.exists(SPRITE_MARIO_PATH) else pygame.Surface((MARIO_SIZE, MARIO_SIZE))\nSPRITE_STAR = pygame.image.load(SPRITE_STAR_PATH) if os.path.exists(SPRITE_STAR_PATH) else pygame.Surface((STAR_SIZE, STAR_SIZE))\nSPRITE_PIPE = pygame.image.load(SPRITE_PIPE_PATH) if os.path.exists(SPRITE_PIPE_PATH) else pygame.Surface((20, 20))\nSPRITE_PIRANHA = pygame.image.load(SPRITE_PIRANHA_PATH) if os.path.exists(SPRITE_PIRANHA_PATH) else pygame.Surface((20, 20))\n\n# --- Assets ---\nscream_sound = pygame.mixer.Sound(SOUND_PATH) if os.path.exists(SOUND_PATH) else None\nwin_sound = pygame.mixer.Sound(WIN_SOUND_PATH) if os.path.exists(WIN_SOUND_PATH) else None\nmario_haha_sound = pygame.mixer.Sound(MARIO_HAHA_PATH) if os.path.exists(MARIO_HAHA_PATH) else None\ndraw_sound = pygame.mixer.Sound(DRAW_SOUND_PATH) if os.path.exists(DRAW_SOUND_PATH) else None\nsnap_sound = pygame.mixer.Sound(SNAP_SOUND_PATH) if os.path.exists(SNAP_SOUND_PATH) else None\npop_sound = pygame.mixer.Sound(POP_SOUND_PATH) if os.path.exists(POP_SOUND_PATH) else None\nspeedup_sound = pygame.mixer.Sound(SPEEDUP_SOUND_PATH) if os.path.exists(SPEEDUP_SOUND_PATH) else None\nerror_sound = pygame.mixer.Sound(SOUNDS_FOLDER + \"error.wav\") if os.path.exists(SOUNDS_FOLDER + \"error.wav\") else None\n\n# --- Setup ---\nscreen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))\npygame.display.set_caption(\"Mario's Slides\")\nclock = pygame.time.Clock()\n\n# --- Game State Variables ---\nVLINE_STATE = [0] * LINE_COUNT\nPATH = 0\nVLINE_PERCENTAGE = 0\nABOUT_TO_DIE = 1\nABOUT_TO_WIN = 0\nDIST_NEXT_PATH = 0\nSEC_ALIVE = 0.00\nTIME_TO_WIN = None\nstart_time = 0.0\nused_webs = set() # Track used webs for sliding\nwebsAmount = 0\nSTAR_IDX = None # 0-based index for star sprite location\nwonGames = 0 # Track number of games won\nwaiting_for_win_sound = False # Track if waiting for win sound to finish\nwin_sound_end_time = 0\npaused = False\nTOTAL_TIME_TO_WIN = 0.0\n\n\n# --- Background Config ---\nBG_WIDTH = 500 # You can adjust this\nBG_HEIGHT = 600 # You can adjust this\nBG_SCALE = 1.7 # You can adjust this (1.0 = no scale, >1 = bigger)\n\nSPRITE_BG = pygame.image.load(SPRITE_BG_PATH) if os.path.exists(SPRITE_BG_PATH) else pygame.Surface((BG_WIDTH, BG_HEIGHT))\n\n\ndef save_web_map(filename=\"webMap.json\"):\n try:\n # Save as a list of [[x1, y1], [x2, y2]] for each web\n web_list = [[list(start), list(end)] for start, end in webs]\n with open(filename, \"w\") as f:\n json.dump(web_list, f, indent=2)\n print(f\"Web map saved to {filename}\")\n except Exception as e:\n print(f\"Error saving web map: {e}\")\n\ndef load_web_map(filename=\"webMap.json\"):\n global webs, websAmount\n try:\n with open(filename, \"r\") as f:\n web_list = json.load(f)\n webs = [ (tuple(start), tuple(end)) for start, end in web_list ]\n websAmount = len(webs)\n print(f\"Web map loaded from {filename}\")\n except Exception as e:\n print(f\"Error loading web map: {e}\")\n\n\ndef play_music():\n if os.path.exists(MAIN_MUSIC):\n pygame.mixer.music.load(MAIN_MUSIC)\n pygame.mixer.music.play(-1)\n\n\ndef reset_game():\n global lines_x, mario_x, mario_y, mario_sliding, pipes, drawing, start_point, webs\n global game_over, slide_target, prev_path, start_time, SEC_ALIVE, VLINE_STAR, websAmount, TIME_TO_WIN, TOTAL_TIME_TO_WIN, MARIO_SPEED\n global STAR_IDX, waiting_for_win_sound, win_sound_end_time\n if 'webs' not in globals():\n webs = []\n play_music()\n lines_x = [LINE_SPACING * (i + 1) for i in range(LINE_COUNT)]\n\n VLINE_STAR = random.randint(1, LINE_COUNT) # 1-based index for win VLINE\n STAR_IDX = VLINE_STAR - 1 # Star sprite always matches the win VLINE\n mario_x = lines_x[random.randint(0, LINE_COUNT - 1)] - MARIO_SIZE // 2 # Random VLINE for Mario\n mario_y = 0\n mario_sliding = False\n slide_target = None\n prev_path = None\n pipes = []\n for i, x in enumerate(lines_x):\n color = (255, 255, 0) if i == STAR_IDX else (0, 255, 0)\n rect = pygame.Rect(x - 10, PIPE_Y, 20, 20)\n pipes.append((rect, color))\n drawing = False\n start_point = None\n game_over = False\n start_time = time.time()\n SEC_ALIVE = 0.00\n TIME_TO_WIN = None\n waiting_for_win_sound = False\n win_sound_end_time = 0\n # Only clear webs if less than 3 wins and webs was not just loaded\n if wonGames < 3 and not getattr(reset_game, 'skip_webs_clear', False):\n webs.clear()\n websAmount = 0\n if wonGames > 2:\n MARIO_SPEED = MARIO_SPEED_3\n if wonGames == 3: # Equivalent to rounds getting progressively harder. Also wongames being 3 means that this won't run ever again.\n webs.clear()\n load_web_map(\"3_Round_webMap.json\")\n elif wonGames == 5: # After 5 wins, load a different web map\n webs.clear()\n load_web_map(\"5_Round_webMap.json\")\n elif wonGames == 10: # After 10 wins, load a different web map\n webs.clear()\n load_web_map(\"10_Round_webMap.json\")\n # After 3 wins, do NOT clear webs, so they persist\n # Reset the skip_webs_clear flag\n if hasattr(reset_game, 'skip_webs_clear'):\n delattr(reset_game, 'skip_webs_clear')\n\n\n\nreset_game()\n\nrunning = True\nwhile running:\n clock.tick(FPS)\n\n if not game_over:\n SEC_ALIVE = round(time.time() - start_time, 2)\n\n for event in pygame.event.get():\n if event.type == pygame.QUIT:\n running = False\n if event.type == pygame.KEYDOWN:\n if event.key == pygame.K_p:\n paused = not paused\n if event.key == pygame.K_r:\n wonGames = 0\n TOTAL_TIME_TO_WIN = 0.0\n reset_game()\n wonGames = 0 # double reset to ensure wonGames is reset.\n TOTAL_TIME_TO_WIN = 0.0\n elif event.key == pygame.K_k:\n save_web_map(\"webMap.json\")\n elif event.key == pygame.K_l:\n load_web_map(\"webMap.json\")\n reset_game.skip_webs_clear = True\n reset_game()\n elif event.key == pygame.K_j:\n load_web_map(\"3_Round_webMap.json\")\n reset_game.skip_webs_clear = True\n reset_game()\n elif event.key == pygame.K_u:\n wonGames += 1\n elif event.key == pygame.K_SPACE:\n MARIO_SPEED = MARIO_SPEED_FAST\n if speedup_sound:\n speedup_sound.play()\n if event.type == pygame.KEYUP:\n if event.key == pygame.K_SPACE:\n MARIO_SPEED = MARIO_SPEED_DEFAULT if wonGames < 3 else MARIO_SPEED_3\n\n if event.type == pygame.MOUSEBUTTONDOWN and not game_over:\n mx, my = pygame.mouse.get_pos()\n nearest_x = min(lines_x, key=lambda x: abs(mx - x))\n if abs(mx - nearest_x) < 15:\n snapped_y = round(my / 10) * 10\n start_point = (nearest_x, snapped_y)\n drawing = True\n if draw_sound:\n draw_sound.play(-1)\n\n if event.type == pygame.MOUSEBUTTONUP and drawing:\n mx, my = pygame.mouse.get_pos()\n nearest_x = min(lines_x, key=lambda x: abs(mx - x))\n if abs(mx - nearest_x) < 15:\n snapped_y = round(my / 10) * 10\n end_point = (nearest_x, snapped_y)\n # Ensure start_point and end_point are not None before using\n if start_point is not None and end_point is not None and start_point[0] != end_point[0]:\n idx1 = lines_x.index(start_point[0])\n idx2 = lines_x.index(end_point[0])\n if abs(idx1 - idx2) == 1:\n dy = abs(end_point[1] - start_point[1])\n if dy > MAX_PATH_LENGTH:\n direction = 1 if end_point[1] > start_point[1] else -1\n end_point = (end_point[0], start_point[1] + direction * MAX_PATH_LENGTH)\n valid = True\n # --- Flexible web overlap check: only block if any pixel is already on a web ---\n for existing_start, existing_end in webs:\n # Check for pixel overlap between the new web and any existing web\n # Use a simple line segment intersection test\n def ccw(A, B, C):\n return (C[1]-A[1]) * (B[0]-A[0]) > (B[1]-A[1]) * (C[0]-A[0])\n def segments_intersect(A,B,C,D):\n return (ccw(A,C,D) != ccw(B,C,D)) and (ccw(A,B,C) != ccw(A,B,D))\n if segments_intersect(start_point, end_point, existing_start, existing_end):\n valid = False\n break\n if valid:\n webs.append((start_point, end_point))\n websAmount += 1\n if snap_sound:\n snap_sound.play()\n else:\n if error_sound:\n error_sound.play()\n drawing = False\n start_point = None\n if draw_sound:\n draw_sound.stop()\n\n if paused:\n pause_font = pygame.font.SysFont(None, 80, bold=True)\n pause_text = pause_font.render(\"PAUSED\", True, (255, 255, 0))\n pause_rect = pause_text.get_rect(center=(WINDOW_WIDTH // 2, WINDOW_HEIGHT // 2))\n screen.blit(pause_text, pause_rect)\n pygame.display.flip()\n continue\n\n if not game_over:\n mario_center_x = mario_x + MARIO_SIZE // 2\n mario_center_y = mario_y + MARIO_SIZE // 2\n VLINE_STATE = [0] * LINE_COUNT\n PATH = 1 if mario_sliding else 0\n VLINE_PERCENTAGE = min(100, int((mario_y / (PIPE_Y)) * 100))\n ABOUT_TO_DIE = 1\n ABOUT_TO_WIN = 0\n DIST_NEXT_PATH = 100\n for i, x in enumerate(lines_x):\n if abs(mario_center_x - x) < 5:\n VLINE_STATE[i] = 1\n mario_vline_idx = i\n break\n else:\n mario_vline_idx = None\n\n # --- ABOUT_TO_DIE and ABOUT_TO_WIN logic ---\n web_below = False\n min_web_y = None\n next_web_dist = None\n if mario_vline_idx is not None:\n mario_cx = mario_x + MARIO_SIZE // 2\n mario_cy = mario_y + MARIO_SIZE // 2\n for start, end in webs:\n # Only consider webs that span across VLINEs\n x1, y1 = start\n x2, y2 = end\n # Check if Mario's X is between the web's endpoints (inclusive)\n if min(x1, x2) <= mario_cx <= max(x1, x2):\n # Calculate the Y on the web at Mario's X using linear interpolation\n if x1 != x2:\n t = (mario_cx - x1) / (x2 - x1)\n web_y_at_mario_x = y1 + t * (y2 - y1)\n else:\n web_y_at_mario_x = y1 # vertical web\n if web_y_at_mario_x > mario_cy:\n web_below = True\n dist = web_y_at_mario_x - mario_cy\n if next_web_dist is None or dist < next_web_dist:\n next_web_dist = dist\n if min_web_y is None or web_y_at_mario_x < min_web_y:\n min_web_y = web_y_at_mario_x\n if web_below:\n ABOUT_TO_DIE = 0\n if mario_sliding:\n ABOUT_TO_DIE = 0\n star_idx = (VLINE_STAR - 1) if VLINE_STAR is not None else 0\n if mario_vline_idx == star_idx:\n ABOUT_TO_DIE = 0\n max_web_y = -1\n for start, end in webs:\n if (start[0] == lines_x[star_idx] or end[0] == lines_x[star_idx]):\n web_y = start[1]\n if web_y > max_web_y:\n max_web_y = web_y\n if mario_y + MARIO_SIZE // 2 > max_web_y:\n ABOUT_TO_WIN = 1\n if web_below and mario_vline_idx == star_idx:\n ABOUT_TO_WIN = 0\n # --- DIST_NEXT_WEB logic ---\n if next_web_dist is not None:\n DIST_NEXT_WEB = int(next_web_dist)\n else:\n # If Mario is below all webs on his VLINE, set to -1\n DIST_NEXT_WEB = -1\n # --- Used webs logic ---\n if mario_y <= 0:\n used_webs.clear()\n # --- Smooth sliding logic with used webs ---\n if mario_sliding:\n dx = slide_target[0] - mario_x\n dy = slide_target[1] - mario_y\n dist = math.hypot(dx, dy)\n if dist <= MARIO_SPEED:\n mario_x = slide_target[0]\n mario_y = slide_target[1]\n mario_sliding = False\n if pop_sound: # avoid crash\n pop_sound.play() # Play pop sound when Mario gets off the web\n else:\n step_x = MARIO_SPEED * (dx / dist)\n step_y = MARIO_SPEED * (dy / dist)\n mario_x += step_x\n mario_y += step_y\n else:\n hopped = False\n mario_cx = mario_x + MARIO_SIZE // 2\n mario_cy = mario_y + MARIO_SIZE // 2\n # --- Improved web detection for high speed ---\n web_hopped_this_frame = False\n if DIST_NEXT_WEB != -1 and ABOUT_TO_DIE == 0 and ABOUT_TO_WIN == 0:\n next_cy = mario_cy + MARIO_SPEED\n for start, end in webs:\n web_id = tuple(sorted([start, end]))\n x1, y1 = start\n x2, y2 = end\n if min(x1, x2) - 1 <= mario_cx <= max(x1, x2) + 1:\n dx, dy = x2 - x1, y2 - y1\n if dx == dy == 0:\n continue\n t = max(0, min(1, ((mario_cx - x1) * dx + (mario_cy - y1) * dy) / (dx * dx + dy * dy)))\n px, py = x1 + t * dx, y1 + t * dy\n distance = math.hypot(mario_cx - px, mario_cy - py)\n # --- Symmetric web detection: allow hopping from either endpoint ---\n if distance < MARIO_SPEED + MARIO_SIZE / 4 and web_id not in used_webs:\n # Always slide to the endpoint that is NOT closest to Mario's current position\n if math.hypot(mario_cx - x1, mario_cy - y1) < math.hypot(mario_cx - x2, mario_cy - y2):\n target = end\n else:\n target = start\n slide_target = (target[0] - MARIO_SIZE // 2, target[1] - MARIO_SIZE // 2)\n mario_sliding = True\n used_webs.add(web_id)\n if pop_sound: pop_sound.play()\n hopped = True\n web_hopped_this_frame = True\n break\n\n if not hopped and not web_hopped_this_frame:\n mario_y += MARIO_SPEED\n # --- Death check: if Mario falls past the last web and not on a VLINE with a web, he dies ---\n if mario_y + MARIO_SIZE >= PIPE_Y:\n # If not on star, it's a loss\n star_x = lines_x[(VLINE_STAR - 1) if VLINE_STAR is not None else 0]\n if abs(mario_center_x - star_x) < 5:\n for rect, color in pipes:\n if color == (255, 255, 0) and rect.top - mario_y < 5:\n if win_sound and mario_haha_sound:\n win_sound.play()\n mario_haha_sound.play()\n game_over = True\n TIME_TO_WIN = SEC_ALIVE\n wonGames += 1\n # Add TIME_TO_WIN to TOTAL_TIME_TO_WIN\n TOTAL_TIME_TO_WIN += TIME_TO_WIN if TIME_TO_WIN is not None else 0\n reset_game() # Instantly go to next round after win\n else:\n if scream_sound: scream_sound.play()\n game_over = True\n # --- Save highscore on death ---\n import datetime\n highscore_entry = {\n \"timestamp\": datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"),\n \"wonGames\": wonGames,\n \"TOTAL_TIME_TO_WIN\": round(TOTAL_TIME_TO_WIN, 2)\n }\n try:\n if os.path.exists(\"highscore.json\"):\n with open(\"highscore.json\", \"r\") as f:\n try:\n content = f.read().strip()\n if not content:\n highscores = []\n else:\n highscores = json.loads(content)\n except Exception:\n highscores = []\n else:\n highscores = []\n highscores.append(highscore_entry)\n with open(\"highscore.json\", \"w\") as f:\n json.dump(highscores, f, indent=2)\n except Exception as e:\n print(f\"Error saving highscore: {e}\")\n\n screen.fill((0, 0, 0))\n\n # --- Draw background ---\n bg_scaled = pygame.transform.scale(SPRITE_BG, (int(BG_WIDTH * BG_SCALE), int(BG_HEIGHT * BG_SCALE)))\n screen.blit(bg_scaled, (-int((BG_WIDTH * BG_SCALE - WINDOW_WIDTH) // 2), -int((BG_HEIGHT * BG_SCALE - WINDOW_HEIGHT) // 2)))\n\n for x in lines_x:\n pygame.draw.line(screen, (255, 255, 255), (x, 0), (x, WINDOW_HEIGHT), 2)\n\n for start, end in webs:\n pygame.draw.line(screen, (0, 255, 255), start, end, 3)\n\n if drawing and start_point:\n mx, my = pygame.mouse.get_pos()\n nearest_x = min(lines_x, key=lambda x: abs(mx - x))\n if abs(mx - nearest_x) < 15:\n snapped_y = round(my / 10) * 10\n pygame.draw.line(screen, (0, 128, 255), start_point, (nearest_x, snapped_y), 2)\n\n for i, (rect, color) in enumerate(pipes):\n if i == STAR_IDX:\n # Center the star image in the actual square (rect)\n star_pos = (rect.centerx - SPRITE_STAR.get_width() // 2, rect.centery - SPRITE_STAR.get_height() // 2)\n screen.blit(SPRITE_STAR, star_pos)\n else:\n # is a piranha plant pipe\n # Center the pipe image in the same way as the star\n pipe_pos = (rect.centerx - SPRITE_PIPE.get_width() // 2, rect.centery - SPRITE_PIPE.get_height() // 2)\n screen.blit(SPRITE_PIPE, pipe_pos)\n\n screen.blit(SPRITE_MARIO, (mario_x, mario_y))\n\n font = pygame.font.SysFont(None, 20)\n debug = [\n f\"SEC_ALIVE = {SEC_ALIVE:.2f}\",\n f\"websAmount = {websAmount}\",\n f\"VLINE_1 = {VLINE_STATE[0]}\",\n f\"VLINE_2 = {VLINE_STATE[1]}\",\n f\"VLINE_3 = {VLINE_STATE[2]}\",\n f\"VLINE_4 = {VLINE_STATE[3]}\",\n f\"VLINE_STAR = {VLINE_STAR}\",\n f\"onWeb = {1 if mario_sliding else 0}\",\n f\"DIST_NEXT_WEB = {DIST_NEXT_WEB}\",\n f\"VLINE_PIXELS_AWAY = {VLINE_PERCENTAGE} pixels\",\n f\"ABOUT_TO_DIE = {ABOUT_TO_DIE}\",\n f\"ABOUT_TO_WIN = {ABOUT_TO_WIN}\",\n f\"TIME_TO_WIN = {TIME_TO_WIN if TIME_TO_WIN is not None else 0}\",\n f\"TOTAL_TIME_TO_WIN = {TOTAL_TIME_TO_WIN:.2f}\",\n f\"wonGames = {wonGames}\",\n ]\n for i, txt in enumerate(debug):\n render = font.render(txt, True, (255, 255, 255))\n screen.blit(render, (420, 10 + i * 20))\n\n # --- User Notes (lower right, visually distinct, non-blocking) ---\n notes = [\n \"SPACE to speed up Mario.\",\n \"Press P to pause the game.\",\n \"Press K to save your spider-web layout.\",\n \"Press L to load your saved spider-web map.\",\n \"Press J to load the 3RD Round Map.\",\n \"Press R to reset the game.\",\n \"Press U to increase wonGames (for testing).\",\n ]\n note_font = pygame.font.SysFont(None, 20, bold=True)\n note_color = (180, 220, 255)\n note_y_start = 10 + len(debug) * 20 + 60 # Many lines below debug\n for i, note in enumerate(notes):\n note_render = note_font.render(note, True, note_color)\n note_rect = note_render.get_rect()\n note_rect.topright = (WINDOW_WIDTH - 10, note_y_start + i * 24)\n screen.blit(note_render, note_rect)\n\n pygame.display.flip()\n\npygame.quit()\nsys.exit()\n\n"}}}} |