-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.py
268 lines (221 loc) · 8.13 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
""" pyPong - A simple pong game made with pygame """
import random
import pygame as pg
import settings
# Initialize pyGame
pg.init()
# Set up the ball
ball_pos = [400, 300]
ball_vel = [3, 3]
# Set up the player and CPU paddles
player_pos = [50, 300]
cpu_pos = [730, 300]
ball_rect = pg.Rect(ball_pos[0],
ball_pos[1],
settings.BALL_SIZE,
settings.BALL_SIZE
)
player_rect = pg.Rect(player_pos[0],
player_pos[1],
settings.PADDLE_WIDTH,
settings.PADDLE_HEIGHT
)
cpu_rect = pg.Rect(cpu_pos[0],
cpu_pos[1],
settings.PADDLE_WIDTH,
settings.PADDLE_HEIGHT
)
player_score = 0
cpu_score = 0
has_cpu_hit_ball = False
is_game_over = False
# Set up the clock
clock = pg.time.Clock()
hit_sound = pg.mixer.Sound(settings.SOUNDS + 'ball.wav')
bounce_sound = pg.mixer.Sound(settings.SOUNDS + 'wall_hit.wav')
pg.mixer.Sound.set_volume(hit_sound, 0.2)
pg.mixer.Sound.set_volume(bounce_sound, 0.4)
# Set up a timer to update the CPU paddle's position every 100 milliseconds
UPDATE_cpu_pos = pg.USEREVENT + 1
pg.time.set_timer(UPDATE_cpu_pos, 100)
cpu_target_y = 0
def show_winner_text(who_won):
""" shows the winner of the game, either player or cpu """
winner_text = font.render(who_won+" wins!", True, settings.WHITE)
screen.blit(
winner_text, (settings.PLAYABLE_AREA[0]/2-150,
settings.PLAYABLE_AREA[1]/2-40)
)
def draw_dotted_line(surface,
color,
start_pos,
end_pos,
width=1,
dot_length=10,
gap_length=5
):
""" draws a dotted line on the screen """
distance = end_pos[0] - start_pos[0], end_pos[1] - start_pos[1]
length = pg.math.Vector2(distance).length()
dot_distance = dot_length + gap_length
dots = int(length / dot_distance)
for i in range(dots):
start = (start_pos[0]+i*distance[0]/dots,
start_pos[1]+i*distance[1]/dots
)
end = (start_pos[0]+(i+0.5)*distance[0]/dots,
start_pos[1]+(i+0.5)*distance[1]/dots
)
pg.draw.line(surface, color, start, end, width)
def reset_ball():
""" resets the ball to the middle of the screen and waits 1 second """
ball_vel[1] += (random.random()-0.15)
ball_vel[0] = -ball_vel[0]
pg.time.delay(1000)
def draw_score():
""" draws the score of player and cpu """
player_score_text = font.render(str(player_score), True, settings.WHITE)
cpu_score_text = font.render(str(cpu_score), True, settings.WHITE)
screen.blit(player_score_text, (settings.PLAYABLE_AREA[0]/4, 10))
screen.blit(cpu_score_text, (settings.PLAYABLE_AREA[0]*3/4, 10))
return cpu_score_text
# Set up the display
screen = pg.display.set_mode(settings.PLAYABLE_AREA)
pg.display.set_caption("My Pong")
# Load the font
font = pg.font.Font(None, settings.FONT_SIZE)
# hide mouse pointer
pg.mouse.set_visible(False)
# Game loop
move_up = False
move_down = False
running = 1
while running:
# set FPS
clock.tick(144)
# Handle events
for event in pg.event.get():
if event.type == pg.QUIT:
running = 0
elif event.type == UPDATE_cpu_pos:
# Update the CPU paddle's position
cpu_target_y = ball_rect.centery
cpu_target_y += random.randint(-50, 50)
elif event.type == pg.KEYDOWN:
# restart game if space is pressed
if event.key == pg.K_SPACE and is_game_over:
ball_vel = [3, 3]
settings.CPU_VEL = 5
ball_rect = pg.Rect(ball_pos[0], ball_pos[1], 20, 20)
player_score = 0
cpu_score = 0
is_game_over = False
screen.fill((settings.BLACK))
if event.key == pg.K_UP:
move_up = True
elif event.key == pg.K_DOWN:
move_down = True
elif event.type == pg.KEYUP:
if event.key == pg.K_UP:
move_up = False
elif event.key == pg.K_DOWN:
move_down = False
# Move the player paddle
if move_up:
player_rect.move_ip(0, -10*settings.PLAYER_VEL)
player_rect.top = max(0, player_rect.top)
elif move_down:
player_rect.move_ip(0, 10*settings.PLAYER_VEL)
player_rect.bottom = min(settings.PLAYABLE_AREA[1], player_rect.bottom)
# Update the ball's position
ball_pos[0] += ball_vel[0]
ball_pos[1] += ball_vel[1]
ball_rect.center = ball_pos
# Move the CPU paddle to track the ball
if (ball_pos[0] > (settings.PLAYABLE_AREA[0]/2)+50 and
not has_cpu_hit_ball):
if cpu_rect.centery < cpu_target_y:
cpu_rect.centery += settings.CPU_VEL
elif cpu_rect.centery > cpu_target_y:
cpu_rect.centery -= settings.CPU_VEL
cpu_rect.top = max(0, cpu_rect.top)
cpu_rect.bottom = min(settings.PLAYABLE_AREA[1], cpu_rect.bottom)
# Check if the ball hits upper or lower walls
if ball_rect.top < 0:
ball_pos[1] = ball_rect.height/2
ball_vel[1] = -ball_vel[1]
bounce_sound.play()
elif ball_rect.bottom > settings.PLAYABLE_AREA[1]:
ball_pos[1] = settings.PLAYABLE_AREA[1] - ball_rect.height/2
ball_vel[1] = -ball_vel[1]
bounce_sound.play()
# Check for collisions with the side walls
if ball_rect.left < 0:
if not cpu_score == 10:
cpu_score += 1
ball_pos = [settings.PLAYABLE_AREA[0]/2,
settings.PLAYABLE_AREA[1]/2
]
reset_ball()
elif ball_rect.right >= settings.PLAYABLE_AREA[0]:
if not player_score == 10:
player_score += 1
ball_pos = [settings.PLAYABLE_AREA[0]/2,
settings.PLAYABLE_AREA[1]/2
]
reset_ball()
has_cpu_hit_ball = False
# Play the hit sound if the ball hits a paddle
if ball_rect.colliderect(player_rect) or ball_rect.colliderect(cpu_rect):
hit_sound.play()
# Check for collisions with the player paddle
if ball_rect.colliderect(player_rect):
has_cpu_hit_ball = False
ball_vel[1] += (random.random()-0.15)
if (ball_rect.bottom >= player_rect.top and
ball_rect.top <= player_rect.bottom):
ball_vel[0] = abs(-ball_vel[0])
elif ball_rect.left <= player_rect.right:
ball_vel[1] = -ball_vel[1]
# Check for collisions with the CPU paddle
if ball_rect.colliderect(cpu_rect):
has_cpu_hit_ball = True
ball_vel[1] += (random.random()-0.15)
if (ball_rect.bottom >= cpu_rect.top and
ball_rect.top <= cpu_rect.bottom):
ball_vel[0] = -abs(ball_vel[0])
elif ball_rect.right >= cpu_rect.left:
ball_vel[1] = -ball_vel[1]
# Draw to the screen
screen.fill((settings.BLACK))
draw_score()
# draw dotted line in the middle of the screen
draw_dotted_line(screen,
settings.WHITE,
(settings.PLAYABLE_AREA[0]/2, 0),
(settings.PLAYABLE_AREA[0]/2,
settings.PLAYABLE_AREA[1]+15),
width=10, dot_length=10, gap_length=20
)
# draw the ball and paddles
pg.draw.rect(screen, settings.WHITE, ball_rect)
pg.draw.rect(screen, settings.WHITE, player_rect)
pg.draw.rect(screen, settings.WHITE, cpu_rect)
# if either player has 10 points then show the winner
if player_score == 10 or cpu_score == 10:
is_game_over = True
# stop the ball
ball_vel = [0, 0]
settings.CPU_VEL = 0
# remove ball
ball_rect = pg.Rect(0, 0, 0, 0)
screen.fill((settings.BLACK))
draw_score()
if player_score == 10:
show_winner_text("Player")
elif cpu_score == 10:
show_winner_text("CPU")
# Update the display
pg.display.update()
# Quit pg
pg.quit()