- 新增 jiyi.py 文件,实现字母翻牌记忆游戏功能 - 添加 youxijiemian.py 文件,创建游戏开始界面 - 使用 turtle 和 tkinter 模块分别实现游戏和界面 - 支持选择不同难度的游戏模式
268 lines
7.1 KiB
Python
268 lines
7.1 KiB
Python
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()
|