import pgzrun import random import itertools from pgzhelper import * WIDTH = 1500 HEIGHT = 800 # 背景 bg1 = Actor('连续道路', topleft=(0, 0)) bg2 = Actor('连续道路', topleft=(1500, 0)) # 摩托车 motor = Actor('摩托1', (200, HEIGHT // 2)) motor.images = ['摩托1', '摩托2'] # 障碍物 obstacles = [Actor('路障', (random.randint(WIDTH, WIDTH + 1200), random.randint(150, HEIGHT - 150))) for _ in range(2)] # 终点线 line = Actor('终点线', topleft=(30000, 163)) # 钻石 zuan = Actor('钻石', topleft=(WIDTH + 100, random.randint(150, HEIGHT - 150))) # 游戏参数 speed = 10 flag = 0 # 0=进行中,1=胜利,2=失败 score = 0 combo = 0 particles = [] blink = itertools.cycle([255, 180, 120, 180]) # 加速状态 boost_active = False boost_time = 0 BOOST_DURATION = 5 # 秒 BOOST_SPEED = 20 BOOST_CD = 8 # 技能冷却时间 boost_cd_timer = 0 # CD倒计时 # 游戏计时 game_time = 0 # 加速提示圆圈参数 boost_circle_radius = 50 boost_circle_pos = (WIDTH - 100, HEIGHT - 100) # 绘制函数 def draw(): bg1.draw() bg2.draw() if flag == 1 or flag == 2: music.stop() color = (255, next(blink), next(blink)) result_text = '胜利!' if flag == 1 else '失败!' screen.draw.text(result_text, center=(WIDTH / 2, HEIGHT / 2 - 100), fontsize=120, color=color, fontname='simkai') # 显示用时和钻石数量 screen.draw.text(f'用时:{game_time:.2f}s', center=(WIDTH / 2, HEIGHT / 2 + 50), fontsize=60, color='white', fontname='simkai') screen.draw.text(f'收集钻石:{score}', center=(WIDTH / 2, HEIGHT / 2 + 120), fontsize=60, color='yellow', fontname='simkai') # 显示总评分 total_score = calculate_score() screen.draw.text(f'最终评分:{total_score}', center=(WIDTH / 2, HEIGHT / 2 + 190), fontsize=60, color='orange', fontname='simkai') else: for obs in obstacles: obs.draw() draw_particles() motor.draw() line.draw() zuan.draw() # draw_collision_rect() # 可选调试 x = int(line.x - motor.x) screen.draw.text(f'距终点:{x} m', (50, 700), fontname='simkai', fontsize=50) screen.draw.text(f'钻石:{score}', (50, 100), fontname='simkai', fontsize=50) screen.draw.text(f'速度:{int(speed)}', (1300, 50), fontname='simkai', fontsize=40, color='yellow') # 绘制加速技能圆圈 draw_boost_circle() def draw_particles(): for p in particles: screen.draw.filled_circle((p['x'], p['y']), 4, (255, 255, 150, int(p['alpha']))) def update_particles(): for p in particles: p['x'] -= 8 p['alpha'] -= 4 particles[:] = [p for p in particles if p['alpha'] > 0] # 背景与障碍物移动 def bg_move(): bg1.x -= speed bg2.x -= speed if bg1.right <= 0: bg1.left = bg2.right if bg2.right <= 0: bg2.left = bg1.right line.x -= speed zuan.x -= speed if zuan.x <= 0: zuan.x = random.randint(WIDTH, WIDTH + 1200) zuan.y = random.randint(150, HEIGHT - 150) def obs_move(): for obs in obstacles: obs.x -= speed if obs.x < -100: obs.x = random.randint(WIDTH, WIDTH + 1200) obs.y = random.randint(150, HEIGHT - 150) def line_collide(): global flag if motor.collide_pixel(line): flag = 1 else: motor.x += 10 def obs_collide(): global flag mx, my = motor.x, motor.y mw, mh = motor.width, motor.height rect_width = int(mw * 0.3) rect_height = int(mh * 0.2) left = int(mx - rect_width / 2) top = int(my + mh / 2 - rect_height) bottom_center_rect = Rect((left, top), (rect_width, rect_height)) for obs in obstacles: obs_rect = Rect((obs.left, obs.top), (obs.width, obs.height)) if bottom_center_rect.colliderect(obs_rect): flag = 2 def zuan_collide(): global score, combo if motor.collide_pixel(zuan): combo += 1 score += combo zuan.x = random.randint(WIDTH, WIDTH + 1200) zuan.y = random.randint(150, HEIGHT - 150) else: combo = max(combo - 0.03, 0) def draw_collision_rect(): # 调试用,可注释 mx, my = motor.x, motor.y mw, mh = motor.width, motor.height rect_width = int(mw * 0.3) rect_height = int(mh * 0.2) left = int(mx - rect_width / 2) top = int(my + mh / 2 - rect_height) collision_rect = Rect((left, top), (rect_width, rect_height)) screen.draw.rect(collision_rect, (255, 0, 0)) def draw_boost_circle(): # 圆圈颜色随CD变化 if boost_cd_timer > 0: color = (100, 100, 100) elif boost_active: color = (0, 255, 255) else: color = (0, 200, 255) screen.draw.circle(boost_circle_pos, boost_circle_radius, color) screen.draw.text("SHIFT", center=boost_circle_pos, color="white", fontsize=30) # 评分计算 def calculate_score(): """根据用时、钻石和胜利情况计算最终得分""" global score, game_time, flag base_score = 0 # 胜利奖励 if flag == 1: base_score += 500 # 钻石加分,每颗钻石10分 base_score += score * 10 # 时间加分,时间越短,额外加分 time_score = max(0, int(1000 - game_time * 10)) base_score += time_score return base_score def update(): global speed, boost_active, boost_time, boost_cd_timer, game_time if flag == 0: # 计时 game_time += 1 / 60 # 更新技能CD if boost_cd_timer > 0 and not boost_active: boost_cd_timer -= 1 / 60 if boost_cd_timer < 0: boost_cd_timer = 0 # Shift 加速 if (keyboard['lshift'] or keyboard['rshift']) and not boost_active and boost_cd_timer == 0: boost_active = True boost_time = BOOST_DURATION speed = BOOST_SPEED if boost_active: boost_time -= 1 / 60 if boost_time <= 0: boost_active = False speed = 10 boost_cd_timer = BOOST_CD # 启动冷却 # 正常加减速 if not boost_active: if keyboard.right: speed = min(speed + 0.2, 18) elif keyboard.left: speed = max(speed - 0.2, 6) # 背景移动 if line.x > WIDTH - 200: bg_move() obs_move() else: line_collide() # 上下移动 if keyboard.up and motor.top > 0: motor.y -= 6 if keyboard.down and motor.bottom < HEIGHT - 50: motor.y += 6 # 碰撞检测 obs_collide() zuan_collide() # 尾焰粒子 particles.append({'x': motor.x - 40, 'y': motor.y + 10, 'alpha': 255}) update_particles() def change_image(): motor.next_image() clock.schedule_interval(change_image, 0.3) music.play('速度与激情') pgzrun.go()