1+ import pygame
2+ from sys import exit
3+ from random import choice
4+
5+ # Initialize Pygame and mixer
6+ pygame .mixer .pre_init (44100 , - 16 , 2 , 512 )
7+ pygame .init ()
8+
9+ # Set up screen and clock
10+ screen = pygame .display .set_mode ((800 , 400 ))
11+ pygame .display .set_caption ("Platform Game" )
12+ clock = pygame .time .Clock ()
13+ test_font = pygame .font .Font ('../image/Pixeltype.ttf' , 50 )
14+
15+ # Game state
16+ game_active = False
17+ start_time = 0
18+ score = 0
19+
20+ # Load audio
21+ jump_sound = pygame .mixer .Sound ('../image/jump.mp3' )
22+ jump_sound .set_volume (0.7 )
23+ pygame .mixer .music .load ('../image/music.wav' )
24+ pygame .mixer .music .set_volume (0.4 )
25+ pygame .mixer .music .play (- 1 ) # Loop music
26+
27+ # Background and ground
28+ Sky_surface = pygame .image .load ('../image/Sky.png' ).convert ()
29+ ground_surface = pygame .image .load ('../image/ground.png' ).convert ()
30+
31+ # Snail animation
32+ snail_1 = pygame .image .load ('../image/snail1.png' ).convert_alpha ()
33+ snail_2 = pygame .image .load ('../image/snail1.png' ).convert_alpha ()
34+ snail_frames = [snail_1 , snail_2 ]
35+ snail_frame_index = 0
36+ snail_surf = snail_frames [snail_frame_index ]
37+
38+ # Fly animation
39+ fly_1 = pygame .image .load ("../image/Fly1.png" ).convert_alpha ()
40+ fly_2 = pygame .image .load ("../image/Fly2.png" ).convert_alpha ()
41+ fly_frames = [fly_1 , fly_2 ]
42+ fly_frame_index = 0
43+ fly_surf = fly_frames [fly_frame_index ]
44+
45+ # Obstacles
46+ obstacle_rect_list = []
47+
48+ # Player animation and position
49+ player_walk_1 = pygame .image .load ('../image/player_walk_1.png' ).convert_alpha ()
50+ player_walk_2 = pygame .image .load ('../image/player_walk_2.png' ).convert_alpha ()
51+ player_walk = [player_walk_1 , player_walk_2 ]
52+ player_index = 0
53+ player_jump = pygame .image .load ('../image/jump.png' ).convert_alpha ()
54+
55+ player_surf = player_walk [player_index ]
56+ # Fix player x position near left side (e.g. x=80), only allow vertical movement
57+ player_rect = player_surf .get_rect (midbottom = (80 , 300 ))
58+ player_gravity = 0
59+
60+ # Player idle graphic
61+ player_stand = pygame .image .load ('../image/player_stand.png' ).convert_alpha ()
62+ player_stand = pygame .transform .rotozoom (player_stand , 0 , 2 )
63+ player_stand_rect = player_stand .get_rect (center = (400 , 200 ))
64+
65+ # UI text
66+ game_name = test_font .render ('Platform Game' , False , (111 , 196 , 169 ))
67+ game_name_rect = game_name .get_rect (center = (400 , 80 ))
68+
69+ game_message = test_font .render ('Press space to Run' , False , (111 , 196 , 169 ))
70+ game_message_rect = game_message .get_rect (center = (400 , 330 ))
71+
72+ # Timers
73+ obstacle_timer = pygame .USEREVENT + 1
74+ pygame .time .set_timer (obstacle_timer , 1500 )
75+
76+ snail_animation_timer = pygame .USEREVENT + 2
77+ pygame .time .set_timer (snail_animation_timer , 200 )
78+
79+ fly_animation_timer = pygame .USEREVENT + 3
80+ pygame .time .set_timer (fly_animation_timer , 150 )
81+
82+ # World scroll speed (speed at which obstacles and background move left)
83+ world_scroll_speed = 5
84+
85+ # Functions
86+ def display_score ():
87+ current_time = int (pygame .time .get_ticks () / 1000 ) - start_time
88+ score_surf = test_font .render (f'Score: { current_time } ' , False , (64 , 64 , 64 ))
89+ score_rect = score_surf .get_rect (center = (400 , 50 ))
90+ screen .blit (score_surf , score_rect )
91+ return current_time
92+
93+ def collision (player , obstacles ):
94+ for _ , obstacle_rect in obstacles :
95+ if player .colliderect (obstacle_rect ):
96+ return False
97+ return True
98+
99+ def player_animation ():
100+ global player_surf , player_index
101+ if player_rect .bottom < 300 :
102+ player_surf = player_jump
103+ else :
104+ player_index += 0.1
105+ if player_index >= len (player_walk ):
106+ player_index = 0
107+ player_surf = player_walk [int (player_index )]
108+
109+ # Variables to help with background scrolling
110+ ground_scroll_x = 0
111+ sky_scroll_x = 0
112+ SKY_WIDTH = Sky_surface .get_width ()
113+ GROUND_WIDTH = ground_surface .get_width ()
114+
115+ while True :
116+ for event in pygame .event .get ():
117+ if event .type == pygame .QUIT :
118+ pygame .quit ()
119+ exit ()
120+
121+ if game_active :
122+ if event .type == pygame .MOUSEBUTTONDOWN :
123+ if player_rect .collidepoint (event .pos ) and player_rect .bottom >= 300 :
124+ player_gravity = - 20
125+ jump_sound .play ()
126+
127+ if event .type == pygame .KEYDOWN :
128+ if event .key == pygame .K_SPACE and player_rect .bottom >= 300 :
129+ player_gravity = - 20
130+ jump_sound .play ()
131+
132+ if event .type == obstacle_timer :
133+ obstacle_type = choice (['snail' , 'fly1' , 'fly2' ])
134+ if obstacle_type == 'snail' :
135+ obstacle_rect = snail_surf .get_rect (bottomright = (900 , 300 ))
136+ else :
137+ obstacle_rect = fly_surf .get_rect (bottomright = (900 , 210 ))
138+ obstacle_rect_list .append ((obstacle_type , obstacle_rect ))
139+
140+ if event .type == snail_animation_timer :
141+ snail_frame_index = (snail_frame_index + 1 ) % len (snail_frames )
142+ snail_surf = snail_frames [snail_frame_index ]
143+
144+ if event .type == fly_animation_timer :
145+ fly_frame_index = (fly_frame_index + 1 ) % len (fly_frames )
146+ fly_surf = fly_frames [fly_frame_index ]
147+
148+ else :
149+ if event .type == pygame .KEYDOWN and event .key == pygame .K_SPACE :
150+ game_active = True
151+ start_time = int (pygame .time .get_ticks () / 1000 )
152+ obstacle_rect_list .clear ()
153+ player_rect .midbottom = (80 , 300 )
154+ player_gravity = 0
155+ ground_scroll_x = 0
156+ sky_scroll_x = 0
157+
158+ if game_active :
159+ # Scroll sky and ground
160+ sky_scroll_x -= world_scroll_speed / 4 # slower scroll for parallax effect
161+ ground_scroll_x -= world_scroll_speed
162+
163+ # Loop sky background
164+ if abs (sky_scroll_x ) > SKY_WIDTH :
165+ sky_scroll_x = 0
166+ # Loop ground background
167+ if abs (ground_scroll_x ) > GROUND_WIDTH :
168+ ground_scroll_x = 0
169+
170+ # Draw sky twice for continuous scrolling
171+ screen .blit (Sky_surface , (sky_scroll_x , 0 ))
172+ screen .blit (Sky_surface , (sky_scroll_x + SKY_WIDTH , 0 ))
173+
174+ # Draw ground twice for continuous scrolling
175+ screen .blit (ground_surface , (ground_scroll_x , 300 ))
176+ screen .blit (ground_surface , (ground_scroll_x + GROUND_WIDTH , 300 ))
177+
178+ score = display_score ()
179+
180+ # Obstacles move left by scroll speed
181+ for obstacle_type , obstacle_rect in obstacle_rect_list :
182+ obstacle_rect .x -= world_scroll_speed
183+ if obstacle_type == 'snail' :
184+ screen .blit (snail_surf , obstacle_rect )
185+ else :
186+ screen .blit (fly_surf , obstacle_rect )
187+
188+ # Remove obstacles off-screen left
189+ obstacle_rect_list = [(t , r ) for (t , r ) in obstacle_rect_list if r .right > 0 ]
190+
191+ # Player physics and vertical movement only
192+ player_gravity += 1
193+ player_rect .y += player_gravity
194+ if player_rect .bottom >= 300 :
195+ player_rect .bottom = 300
196+
197+ player_animation ()
198+
199+ # Draw player fixed at ~x=80 horizontally
200+ # So player x pos doesn't change; only y changes
201+ player_rect .x = 80
202+ screen .blit (player_surf , player_rect )
203+
204+ # Collision detection
205+ game_active = collision (player_rect , obstacle_rect_list )
206+
207+ else :
208+ screen .fill ((94 , 129 , 162 ))
209+ screen .blit (player_stand , player_stand_rect )
210+ screen .blit (game_name , game_name_rect )
211+
212+ if score == 0 :
213+ screen .blit (game_message , game_message_rect )
214+ else :
215+ score_message = test_font .render (f'Score: { score } ' , False , (111 , 196 , 169 ))
216+ score_message_rect = score_message .get_rect (center = (400 , 330 ))
217+ screen .blit (score_message , score_message_rect )
218+
219+ pygame .display .update ()
220+ clock .tick (60 )
0 commit comments