为了在现有的数字弹珠游戏代码中添加开始界面和开始游戏按钮,需要在游戏启动时显示开始界面,在界面上绘制按钮,并处理按钮的点击事件。以下是修改后的代码:
```python
import pygame
import random
import math
import sys
Screen_width = 800
Screen_height = 600
FPS = 60
White = (255, 255, 255)
Black = (0, 0, 0)
Red = (255, 0, 0)
Green = (0, 255, 0)
Blue = (0, 0, 255)
Gray = (200, 200, 200)
Yellow = (255, 225, 0)
Ball_Size = 8
Ball_First_Speed = 10
Ball_Bounce_Speed = 1.5
Block_Width = 50
Block_Height = 30
Initial_Block_Number = 8
Probability_Block = 0.5
Block_Max_Number = 5
Block_Move_Speed = 30
Block_Spawn_Y = Screen_height - 40
Block_Max_Y = 20
Launch_area = 200
Ball_Shot = 5
Delay_time = 8
FONT_SIZE = 20
class Grid:
def __init__(self, x, y, number):
self.rect = pygame.Rect(x, y, Block_Width, Block_Height)
self.number = number
self.color = Green
self.font = pygame.font.Font(None, FONT_SIZE)
self.update_text_surface()
def update_text_surface(self):
self.text_surface = self.font.render(str(self.number), True, Black)
self.text_rect = self.text_surface.get_rect(center=self.rect.center)
def draw(self, screen):
pygame.draw.rect(screen, self.color, self.rect)
screen.blit(self.text_surface, self.text_rect)
def update(self):
self.rect.y -= Block_Move_Speed
self.text_rect.center = self.rect.center
def hit(self):
self.number -= 1
if self.number <= 0:
return True
else:
self.update_text_surface()
return False
class Ball:
def __init__(self, x, y, angle_rad):
self.radius = Ball_Size
self.color = Blue
self.speed = Ball_First_Speed
self.speed_x = self.speed * math.cos(angle_rad)
self.speed_y = self.speed * math.sin(angle_rad)
self.x = x
self.y = y
self.angle_rad = angle_rad
self.active = True
def move(self):
if self.active:
self.x += self.speed_x
self.y += self.speed_y
if self.x - self.radius < 0 or self.x + self.radius > Screen_width:
self.speed_x *= -1
self.angle_rad = math.atan2(self.speed_y, self.speed_x)
def draw(self, screen):
if self.active:
pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), self.radius)
def bounce(self, grid_rect):
ball_center_x = self.x
ball_center_y = self.y
grid_center_x = grid_rect.centerx
grid_center_y = grid_rect.centery
offset_x = ball_center_x - grid_center_x
offset_y = ball_center_y - grid_center_y
relative_collision_x = offset_x / grid_rect.width
relative_collision_y = offset_y / grid_rect.height
self.speed_y *= -1
self.speed_x = self.speed * self.relative_collision_x_to_speed(relative_collision_x)
self.angle_rad = math.atan2(self.speed_y, self.speed_x)
def relative_collision_x_to_speed(self, relative_x):
return relative_x * Ball_Bounce_Speed
pygame.init()
screen = pygame.display.set_mode((Screen_width, Screen_height))
pygame.display.set_caption("数字弹珠游戏")
clock = pygame.time.Clock()
font_large = pygame.font.Font(None, 72)
font_medium = pygame.font.Font(None, 40)
grids = []
balls = []
delay_counter = 0
shot_queue = []
game_over = False
all_balls_launched = False
in_start_menu = True
# 开始游戏按钮设置
button_width = 200
button_height = 80
button_x = (Screen_width - button_width) // 2
button_y = (Screen_height - button_height) // 2
button_rect = pygame.Rect(button_x, button_y, button_width, button_height)
def create_initial_grids():
num_grids_to_create = Initial_Block_Number
attempts = 0
while len(grids) < num_grids_to_create and attempts < 100:
x = random.randint(0, Screen_width - Block_Width)
y = Block_Spawn_Y - random.randint(0, Block_Height * 5)
num = random.randint(1, Block_Max_Number)
new_grid = Grid(x, y, num)
is_overlapping = False
for existing_grid in grids:
if new_grid.rect.colliderect(existing_grid.rect):
is_overlapping = True
break
if not is_overlapping:
grids.append(new_grid)
attempts += 1
def add_new_grid():
if random.random() < Probability_Block:
min_grid = 1
max_grid = 3
num_grid = random.randint(min_grid, max_grid)
for _ in range(num_grid):
x = random.randint(0, Screen_width - Block_Width)
y = Block_Spawn_Y
num = random.randint(1, Block_Max_Number)
new_grid = Grid(x, y, num)
is_overlapping = False
for existing_grid in grids:
if new_grid.rect.colliderect(existing_grid.rect):
is_overlapping = True
break
if not is_overlapping:
grids.append(new_grid)
def check_game_over():
for grid in grids:
if grid.rect.top <= 0:
return True
return False
def reset_game():
global balls, grids, game_over, all_balls_launched
balls = []
grids = []
game_over = False
all_balls_launched = False
create_initial_grids()
create_initial_grids()
running = True
while running:
dt = clock.tick(FPS) / 1000.0
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if in_start_menu:
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
mouse_x, mouse_y = event.pos
if button_rect.collidepoint(mouse_x, mouse_y):
in_start_menu = False
elif not game_over:
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
mouse_x, mouse_y = event.pos
start_x = Screen_width // 2
start_y = 50
direction_vector_x = mouse_x - start_x
direction_vector_y = mouse_y - start_y
target_angle_rad = math.atan2(direction_vector_y, direction_vector_x)
for i in range(Ball_Shot):
shot_angle = target_angle_rad
shot_queue.append((start_x, start_y, shot_angle))
all_balls_launched = True
if in_start_menu:
screen.fill(Black)
pygame.draw.rect(screen, Gray, button_rect)
start_text = font_medium.render("开始游戏", True, Black)
text_x = button_x + (button_width - start_text.get_width()) // 2
text_y = button_y + (button_height - start_text.get_height()) // 2
screen.blit(start_text, (text_x, text_y))
else:
if shot_queue:
delay_counter += 1
if delay_counter >= Delay_time:
start_x, start_y, shot_angle = shot_queue.pop(0)
new_ball = Ball(start_x, start_y, shot_angle)
balls.append(new_ball)
delay_counter = 0
if all_balls_launched and len(shot_queue) == 0 and len(balls) == 0:
grids_to_keep = []
for grid in grids:
grid.update()
if grid.rect.top > Block_Max_Y:
grids_to_keep.append(grid)
else:
game_over = True
break
grids = grids_to_keep
if not game_over:
add_new_grid()
all_balls_launched = False
if not game_over:
balls_to_keep = []
for ball in balls:
if ball.active:
ball.move()
balls_to_keep.append(ball)
balls = balls_to_keep
for ball in balls:
if ball.active:
for i in range(len(grids) - 1, -1, -1):
grid = grids[i]
if ball.y < grid.rect.bottom and \
ball.y > grid.rect.top and \
ball.x < grid.rect.right and \
ball.x > grid.rect.left:
ball.bounce(grid.rect)
if grid.hit():
grids.pop(i)
break
if check_game_over():
game_over = True
screen.fill(Black)
for ball in balls:
ball.draw(screen)
for grid in grids:
grid.draw(screen)
if game_over:
screen.fill(Black)
game_over_text = font_large.render("Game Over", True, Red)
restart_text = font_medium.render("Click to Restart", True, White)
screen.blit(game_over_text, (
Screen_width // 2 - game_over_text.get_width() // 2, Screen_height // 2 - game_over_text.get_height()))
screen.blit(restart_text, (Screen_width // 2 - restart_text.get_width() // 2, Screen_height // 2 + 50))
pygame.display.flip()
pygame.quit()
```
### 代码解释
1. **全局变量添加**:添加了 `in_start_menu` 变量,用于判断是否处于开始菜单界面。
2. **按钮设置**:定义了按钮的大小、位置和矩形区域,使用 `pygame.Rect` 创建按钮矩形。
3. **开始菜单绘制**:在 `in_start_menu` 为 `True` 时,绘制开始界面和开始游戏按钮。
4. **按钮点击事件处理**:在事件循环中,检查鼠标点击事件,若点击位置在按钮矩形内,则将 `in_start_menu` 设为 `False`,开始游戏。
###