20254118 2025-2026-2 《Python程序设计》实验4报告

课程:《python程序设计》
班级:2541
姓名:于欣灵
学号:20254118
实验教师:王志强
实验日期:2026年6月1日
必修/选修:必修课

1.实验内容
Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。
例如:编写从社交网络爬取数据,实现可视化舆情监控或者情感分析。
例如:利用公开数据集,开展图像分类、恶意软件检测等
例如:利用python库,基于ocr技术实现自动化提取图片中数据,并填入excel中。
例如:爬取天气数据,实现自动化微信提醒
例如:利用爬虫,实现自动化下载网站视频、文件等。
例如:编写小游戏:坦克大战、贪吃蛇、扫雷等等
注:在windows/linux系统上使用vim、pdb、idle、pycharm等工具编程实现。

2.实验过程及结果
一、了解跳一跳小游戏游戏规则,构思程序逻辑框架
本次基于pygame开发阶梯跳一跳小游戏,游戏核心规则为:玩家操控方块角色,在多层随机生成的平台之间向上跳跃,通过键盘左右方向键控制水平移动、上方向键控制跳跃。玩家仅能落在当前所在平台或上一级目标闪烁平台上,若误落到其他平台或掉落出屏幕外,则游戏失败;成功跳完全部10层平台即可通关胜利。

(1)配置实验开发环境
本次开发基于pycharm编译器,依赖pygame第三方游戏库。实验前期完成环境部署:在pycharm终端执行pip install pygame指令,将pygame库安装至项目虚拟环,为游戏开发提供基础运行环境。

屏幕截图 2026-06-15 200903

(2)导入模块并初始化游戏环境
程序导入三大核心模块:Pygame用于图形绘制、窗口管理、按键事件监听与动画渲染;random用于随机生成平台位置、粒子特效位置、随机评价文字;sys用于程序安全退出。
通过初始化全部pygame内置模块,激活图形、字体、事件系统,保证后续所有游戏功能正常运行。

屏幕截图 2026-06-15 201211

(3)创建游戏窗口与基础参数
自定义固定游戏窗口尺寸为宽480px、高720px,通过)创建主渲染窗口,设置窗口标题为“跳一跳小游戏”,确定游戏固定显示画布。
同时定义全局时钟对象,设置帧率fps=60,统一游戏运行速度,避免不同设备运行速率不一致,保证操作手感稳定。

屏幕截图 2026-06-15 201420

(4)自定义游戏配色体系
基于rgb色彩规则,自定义整套游戏配色,区分背景、玩家、平台、按钮、透明遮罩等元素,提升界面美观度与层次感:
渐变天空蓝:顶部浅蓝、底部深蓝,实现渐变背景效果
主体粉色、浅粉色:用于玩家方块、普通平台、高亮目标平台
白色:文字、描边高亮
按钮常态色、悬浮高亮色:实现按钮hover放大变色效果
半透明黑色:用于ui文字底栏、暂停遮罩,提升文字可读性

屏幕截图 2026-06-15 201833

(5)定义玩家物理常量
根据游戏手感调试固定物理参数,替代传统变量定义,保证游戏稳定性:
player_size=36:固定玩家方块尺寸
move_speed=5:玩家水平移动速度,空中可减速微调落点
jump_force=-15:跳跃初速度(屏幕y轴向下为正,负值实现向上跳跃)
gravity=0.75:全局重力加速度,模拟真实下落物理效果

屏幕截图 2026-06-15 202212

(6)字体、镜头与全局状态配置
定义大中小三套字体,分别用于标题、分数、提示文字、按钮文字渲染;
设置镜头触发高度,实现玩家向上跳跃时镜头自动跟随上移的滚动效果;
定义全局分数、暂停状态、游戏运行状态,支撑完整游戏流程切换。

屏幕截图 2026-06-15 214954

(7)封装特效与装饰类
1.粒子特效类particle:玩家成功落地时生成粉色粒子,模拟落地撞击特效,带有速度、重力、生命周期,自动消散,提升游戏动画质感。
2.背景圆点装饰类backdot:批量生成慢速下落的半透明粉色圆点,动态刷新,丰富背景视觉效果。
3.按钮交互类button:封装按钮位置、尺寸、文字,实现鼠标悬浮轻微放大、变色的动态交互效果,适配暂停、重启、退出功能。

屏幕截图 2026-06-15 215042

(8)平台生成与初始化逻辑
通过reset_game()重置并初始化完整游戏场景:
1.玩家初始生成在屏幕下方初始平台位置,重置速度、重力、镜头、分数、特效数据;
2.批量生成10层阶梯式平台,每层平台宽度随机、横向位置随机,纵向固定间距排布;
3.区分当前站立平台、下一目标平台,目标平台实现闪烁白边高亮提示,引导玩家跳跃方向,降低新手操作难度。

屏幕截图 2026-06-15 215128

(9)玩家运动系统设计
1.地面移动:地面状态下左右键全速移动,设置边界回弹效果,避免玩家卡死屏幕边缘;
2.空中微调:跳跃升空过程中可慢速左右微调落点,优化操作容错率;
3.跳跃机制:仅地面状态可触发跳跃,按下上方向键赋予向上初速度,配合重力实现起跳、升空、下落完整物理运动;
4.动态形变效果:起跳压缩、落地拉伸,模拟真实跳跃形变动画,提升手感真实度。

屏幕截图 2026-06-15 215255

(10)精准多层碰撞检测
代码实现精细化多规则碰撞判定,区别于简单碰撞逻辑:
1.下落状态下碰撞当前平台,锁定玩家落地,重置速度、恢复站立状态;
2.成功碰撞下一高亮平台,判定跳跃成功,加分、生成粒子特效、弹出随机评价文字(perfect/nice),切换下一关卡;
3.禁止误触判定:碰撞非目标、非当前平台,直接判定游戏失败;
4.边界死亡判定:玩家掉落镜头屏幕外,判定游戏结束。

屏幕截图 2026-06-15 215255

(11)镜头滚动机制
设置镜头触发阈值,当玩家跳跃至屏幕上三分之一区域时,自动向上滚动镜头,实现无限向上攀登的视觉效果,跟随玩家进度更新游戏视野。

屏幕截图 2026-06-15 215350

(12)ui与动态提示系统
1.左上角实时显示关卡进度(1-10)与当前得分,搭配半透明黑底,清晰醒目;
2.右上角常驻操作提示:移动、跳跃按键说明;
3.跳跃成功弹出上浮渐隐文字评价,自动向上漂移、透明度递减消失;
4.右上角内置暂停按钮,支持随时暂停/继续游戏。

屏幕截图 2026-06-15 215445

(13)程序安全退出
游戏窗口关闭事件触发后,执行pygame.quit()与sys.exit(),安全释放pygame资源、终止程序进程,避免后台残留运行。

屏幕截图 2026-06-15 215635

(14)完整源代码

点击查看代码
import pygame
import random
import sys

# 初始化pygame
pygame.init()

# 窗口尺寸
WIDTH, HEIGHT = 480, 720
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("跳一跳小游戏")

# 配色
MAIN_BLUE_TOP = (80, 160, 255)
MAIN_BLUE_BOTTOM = (120, 190, 255)
MAIN_PINK = (255, 150, 200)
LIGHT_PINK = (255, 185, 222)
WHITE = (255, 255, 255)
BTN_NORMAL = (220, 100, 160)
BTN_HOVER = (255, 70, 140)
BLACK_TRANS = (0, 0, 0, 110)

clock = pygame.time.Clock()
FPS = 60

# 玩家常量【新手适配】
player_size = 36
move_speed = 5
jump_force = -15
gravity = 0.75

# 字体
font_big = pygame.font.Font(None, 34)
font_small = pygame.font.Font(None, 25)
tip_font = pygame.font.Font(None, 22)
score_font = pygame.font.Font(None, 28)
btn_font = pygame.font.Font(None, 30)

# 镜头偏移量
camera_y = 0
CAMERA_TRIGGER_Y = HEIGHT * 0.35

# 全局变量
score = 0
is_paused = False

# 粒子类(落地特效)
class Particle:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.vx = random.randint(-3, 3)
        self.vy = random.randint(-4, -1)
        self.life = 25
        self.color = MAIN_PINK
    def update(self):
        self.x += self.vx
        self.y += self.vy
        self.vy += 0.2
        self.life -= 1
    def draw(self, cam_y):
        pygame.draw.circle(screen, self.color, (int(self.x), int(self.y) - cam_y), 4)

particles = []

# 漂浮背景装饰圆点
class BackDot:
    def __init__(self):
        self.x = random.randint(0, WIDTH)
        self.y = random.randint(-HEIGHT, HEIGHT)
        self.r = random.randint(2,5)
        self.speed = random.uniform(0.2, 0.6)
        self.alpha = random.randint(30,90)
    def update(self):
        self.y += self.speed
        if self.y > HEIGHT:
            self.y = -10
            self.x = random.randint(0, WIDTH)
    def draw(self):
        surf = pygame.Surface((self.r*2, self.r*2), pygame.SRCALPHA)
        pygame.draw.circle(surf, (*MAIN_PINK[:3], self.alpha), (self.r,self.r), self.r)
        screen.blit(surf, (self.x, self.y))

back_dots = [BackDot() for _ in range(22)]

# 按钮类(hover放大)
class Button:
    def __init__(self, x, y, w, h, text):
        self.x0 = x
        self.y0 = y
        self.w0 = w
        self.h0 = h
        self.rect = pygame.Rect(x, y, w, h)
        self.text = text
        self.hover = False
        self.scale = 1.0
    def draw(self):
        # 悬浮轻微放大
        if self.hover and self.scale < 1.06:
            self.scale += 0.008
        elif not self.hover and self.scale > 1.0:
            self.scale -= 0.008
        w = int(self.w0 * self.scale)
        h = int(self.h0 * self.scale)
        x = self.x0 - (w - self.w0)//2
        y = self.y0 - (h - self.h0)//2
        self.rect = pygame.Rect(x, y, w, h)

        color = BTN_HOVER if self.hover else BTN_NORMAL
        pygame.draw.rect(screen, color, self.rect, border_radius=8)
        txt_surf = btn_font.render(self.text, True, WHITE)
        txt_rect = txt_surf.get_rect(center=self.rect.center)
        screen.blit(txt_surf, txt_rect)
    def check_mouse(self, pos):
        self.hover = self.rect.collidepoint(pos)
        return self.hover

# 重置游戏
def reset_game():
    global player_x, player_y, vel_y, on_ground, current_stage, game_status, show_tip, tip_countdown, tip_y_offset, platforms, camera_y, particles, score, is_paused
    player_x = WIDTH // 2 - player_size // 2
    player_y = HEIGHT - 120
    vel_y = 0
    on_ground = True
    current_stage = 0
    game_status = "running"
    show_tip = ""
    tip_countdown = 0
    tip_y_offset = 0
    camera_y = 0
    particles = []
    score = 0
    is_paused = False
    platforms = []
    plat_height = 22
    start_y = HEIGHT - 85
    # 新手加宽平台
    for i in range(10):
        p_width = random.randint(85, 135)
        p_x = random.randint(15, WIDTH - p_width - 15)
        p_y = start_y - i * 112
        platforms.append([p_x, p_y, p_width, plat_height])

reset_game()
# 功能按钮
btn_restart = Button(WIDTH//2 - 110, HEIGHT//2 + 60, 100, 45, "Restart")
btn_quit = Button(WIDTH//2 + 10, HEIGHT//2 + 60, 100, 45, "Quit")
btn_pause = Button(WIDTH - 95, 12, 80, 32, "Pause")

# 主循环
while True:
    mouse_pos = pygame.mouse.get_pos()
    mouse_click = False

    # 渐变背景绘制
    gradient_surf = pygame.Surface((WIDTH, HEIGHT))
    for y in range(HEIGHT):
        ratio = y / HEIGHT
        r = int(MAIN_BLUE_TOP[0] * (1-ratio) + MAIN_BLUE_BOTTOM[0] * ratio)
        g = int(MAIN_BLUE_TOP[1] * (1-ratio) + MAIN_BLUE_BOTTOM[1] * ratio)
        b = int(MAIN_BLUE_TOP[2] * (1-ratio) + MAIN_BLUE_BOTTOM[2] * ratio)
        pygame.draw.line(gradient_surf, (r,g,b), (0,y), (WIDTH,y))
    screen.blit(gradient_surf, (0,0))

    # 绘制漂浮背景圆点
    for dot in back_dots:
        dot.update()
        dot.draw()

    # 事件监听
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            mouse_click = True
            # 暂停按钮点击
            if btn_pause.check_mouse(mouse_pos) and game_status == "running":
                is_paused = not is_paused

    # 暂停界面遮挡
    if is_paused and game_status == "running":
        pause_overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
        pause_overlay.fill((0,0,0,130))
        screen.blit(pause_overlay, (0,0))
        pause_text = font_big.render("Game Paused", True, WHITE)
        rect = pause_text.get_rect(center=(WIDTH//2, HEIGHT//2 - 30))
        screen.blit(pause_text, rect)
        hint_text = font_small.render("Click Pause again to continue", True, WHITE)
        rect2 = hint_text.get_rect(center=(WIDTH//2, HEIGHT//2 + 10))
        screen.blit(hint_text, rect2)
        btn_pause.check_mouse(mouse_pos)
        btn_pause.draw()
        pygame.display.update()
        clock.tick(FPS)
        continue

    if game_status == "running":
        keys = pygame.key.get_pressed()
        # 左右移动+边界回弹,不生硬卡死
        if keys[pygame.K_LEFT]:
            if player_x <= 3:
                player_x += 2
            else:
                player_x -= move_speed
        if keys[pygame.K_RIGHT]:
            if player_x + player_size >= WIDTH - 3:
                player_x -= 2
            else:
                player_x += move_speed
        # 空中小幅横向微调落点
        if not on_ground:
            if keys[pygame.K_LEFT] and player_x > 0:
                player_x -= move_speed//2
            if keys[pygame.K_RIGHT] and player_x + player_size < WIDTH:
                player_x += move_speed//2
        # 地面起跳
        if keys[pygame.K_UP] and on_ground:
            vel_y = jump_force
            on_ground = False

        # 重力更新
        if not on_ground:
            vel_y += gravity
            player_y += vel_y

        # 镜头滚动
        screen_player_y = player_y - camera_y
        if screen_player_y < CAMERA_TRIGGER_Y:
            scroll_offset = CAMERA_TRIGGER_Y - screen_player_y
            camera_y -= scroll_offset

        player_rect = pygame.Rect(player_x, player_y, player_size, player_size)
        target_next_idx = current_stage + 1

        # 停留在当前平台
        curr_px, curr_py, curr_pw, curr_ph = platforms[current_stage]
        curr_plat_rect = pygame.Rect(curr_px, curr_py, curr_pw, curr_ph)
        if vel_y > 0 and player_rect.colliderect(curr_plat_rect):
            player_y = curr_py - player_size
            vel_y = 0
            on_ground = True

        # 成功跳到下一阶
        land_success = False
        if target_next_idx < len(platforms):
            next_px, next_py, next_pw, next_ph = platforms[target_next_idx]
            next_plat_rect = pygame.Rect(next_px, next_py, next_pw, next_ph)
            if vel_y > 0 and player_rect.colliderect(next_plat_rect):
                player_y = next_py - player_size
                vel_y = 0
                on_ground = True
                land_success = True
                current_stage = target_next_idx
                score += 10
                show_tip = random.choice(["Perfect", "Nice"])
                tip_countdown = 90
                tip_y_offset = 0
                # 落地粒子
                for _ in range(8):
                    particles.append(Particle(player_x+player_size//2, player_y+player_size))
                if current_stage >= 9:
                    game_status = "win"

        # 落到非目标平台直接失败
        for check_idx in range(len(platforms)):
            if check_idx == current_stage or check_idx == target_next_idx:
                continue
            far_px, far_py, far_pw, far_ph = platforms[check_idx]
            far_rect = pygame.Rect(far_px, far_py, far_pw, far_ph)
            if vel_y > 0 and player_rect.colliderect(far_rect):
                game_status = "lose"
                break

        # 掉落出屏幕失败
        if player_y - camera_y > HEIGHT + 60:
            game_status = "lose"

    # 更新绘制粒子
    for p in particles[:]:
        p.update()
        if p.life <= 0:
            particles.remove(p)
        else:
            p.draw(camera_y)

    # 绘制平台 + 目标平台闪烁高亮
    blink = (pygame.time.get_ticks()//300) % 2 == 0
    for idx, p in enumerate(platforms):
        px, py, pw, ph = p
        draw_y = py - camera_y
        rect_draw = pygame.Rect(px, draw_y, pw, ph)
        if idx == current_stage:
            pygame.draw.rect(screen, MAIN_PINK, rect_draw, border_radius=8)
        elif idx == target_next_idx and blink:
            pygame.draw.rect(screen, LIGHT_PINK, rect_draw, border_radius=8)
            pygame.draw.rect(screen, WHITE, rect_draw, width=3, border_radius=8)
        else:
            pygame.draw.rect(screen, LIGHT_PINK, rect_draw, border_radius=8)

    # 玩家方块起跳压缩、落地拉伸动态形变
    draw_player_y = player_y - camera_y
    squash = 1.0
    if not on_ground and vel_y < -6:
        squash = 0.82
    elif on_ground and vel_y > 3:
        squash = 1.15
    p_w = int(player_size / squash)
    p_h = int(player_size * squash)
    p_x_draw = player_x + (player_size - p_w)//2
    p_y_draw = draw_player_y + (player_size - p_h)
    player_rect_draw = pygame.Rect(p_x_draw, p_y_draw, p_w, p_h)
    pygame.draw.rect(screen, MAIN_PINK, player_rect_draw, border_radius=9)

    # 上浮渐隐提示文字
    if tip_countdown > 0:
        tip_countdown -= 1
        tip_y_offset -= 1.2
        alpha = int(255 * (tip_countdown/90))
        tip_surface = font_big.render(show_tip, True, WHITE)
        tip_surface.set_alpha(alpha)
        tip_rect = tip_surface.get_rect(center=(WIDTH//2, 80 + tip_y_offset))
        screen.blit(tip_surface, tip_rect)

    # 左上角关卡+分数UI(半透明底色)
    info_text = f"Level:{current_stage+1}/10 | Score:{score}"
    info_surf = font_small.render(info_text, True, WHITE)
    bg_w = info_surf.get_width() + 10
    bg_h = info_surf.get_height() + 6
    info_bg = pygame.Surface((bg_w, bg_h), pygame.SRCALPHA)
    info_bg.fill(BLACK_TRANS)
    screen.blit(info_bg, (8,8))
    screen.blit(info_surf, (13,11))

    # 右上角操作提示
    oper_text = tip_font.render("← → Move | ↑ Jump", True, WHITE)
    oper_bg = pygame.Surface((oper_text.get_width()+10, oper_text.get_height()+6), pygame.SRCALPHA)
    oper_bg.fill(BLACK_TRANS)
    screen.blit(oper_bg, (WIDTH-oper_text.get_width()-18, 8))
    screen.blit(oper_text, (WIDTH-oper_text.get_width()-13, 11))

    # 绘制暂停按钮
    btn_pause.check_mouse(mouse_pos)
    btn_pause.draw()

    # 结束界面
    if game_status != "running":
        overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
        overlay.fill((0,0,0,95))
        screen.blit(overlay, (0,0))

        if game_status == "win":
            end_txt = font_big.render("You Win! Congratulations", True, WHITE)
            score_txt = score_font.render(f"Final Score: {score}", True, WHITE)
        else:
            end_txt = font_big.render("Keep trying next time", True, WHITE)
            score_txt = score_font.render(f"Score: {score}", True, WHITE)

        txt_rect = end_txt.get_rect(center=(WIDTH//2, HEIGHT//2 - 55))
        score_rect = score_txt.get_rect(center=(WIDTH//2, HEIGHT//2 - 15))
        screen.blit(end_txt, txt_rect)
        screen.blit(score_txt, score_rect)

        btn_restart.check_mouse(mouse_pos)
        btn_quit.check_mouse(mouse_pos)
        btn_restart.draw()
        btn_quit.draw()

        if mouse_click:
            if btn_restart.hover:
                reset_game()
            elif btn_quit.hover:
                pygame.quit()
                sys.exit()

    pygame.display.update()
    clock.tick(FPS)[]()
3、实验运行结果 最终成功完成可完整运行的阶梯跳一跳小游戏,实现全部预期功能:玩家移动顺滑、跳跃物理手感自然、平台随机生成合理、目标平台高亮指引清晰、碰撞判定精准、镜头跟随流畅、特效动画完整、分数与关卡统计正常,支持暂停、重启、退出功能,具备完整的失败与胜利判定机制,整体界面美观、交互流畅,完成本次实验开发目标。

https://www.bilibili.com/video/BV1b3jV6cEha/?share_source=copy_web&vd_source=6d79e990df9f4c31a101e20381b88873

4.遇到的问题和解决方法
问题1:代码未反应出较大错误,但是无法运行;
问题1解决方案:上网查阅资料后发现,需要先在pycharm内安装pygame,根据网络上分享的教程并在同学的倾情帮助下,将pygame安装完成后即可成功运行代码,游戏界面也可正常进行显示并可进行操作。
问题2:不知道如何用代码设置不同的颜色
问题2解决方案:通过b站博主的讲解,了解到rgb元组,可通过调整三个值的范围来设置红绿蓝等颜色。此外还有rgba元组(含透明度)。
问题3:代表玩家的红色矩形方块的跳跃高度过高,影响玩家体验
问题3解决方案:不断设置不同的跳跃初始力度参数,并运行测试,最终确定最利于玩家体验的参数。
问题4:觉得整个画面不够精致
问题四解决方案:查找资料看有什么方式可以让整个游戏的体验感更好,最终借助豆包完成想法。
5.全课总结感悟与意见建议
(1)总结感悟与收获
回顾这一学期的Python,我收获很多,也有很多不足。最刚开始接触编程时,我完全是零基础小白,连基础概念都不懂,只能跟着老师的讲课节奏慢慢摸索。经过一学期的学习,现在掌握一些了Python基础内容,也能完成一些简单的编程。感谢老师技术上的支持和同学方法上的提醒。
我觉得实验是我印象最深刻的一部分,可能也是亲身尝试的原因,我的代码经常因为各种问题运行错误,运行失败之后就需要不停找问题、找解决方法,接着继续失败继续解决问题,常常改很多次才能成功运行。虽然过程很磨人,但当代码最终运行成功时,都会很有成就感。同时我也能感觉到,每一次排查问题,都能填补我一点知识盲区,让我对Python的基础用法多一点熟悉。在实验的过程中python的逻辑化、条理化也给了我多一种的思考方式。这段学习过程也让我意识到Python的知识专业性很强,想要学通透需要花很多心思。
我自身编程基础较为薄弱,独立思考、自主排错的能力比较差。日常完成作业或是碰到复杂报错时,大多时候都需要借助AI寻找思路、解决问题,自主钻研、独立分析问题的能力还有很大差距。但是蛮好的是在向AI提出问题之后慢慢也能看懂很多问题和错误。
(2)意见和建议
Python知识点繁杂且细致,如果可以直接梳理出清晰知识点和表格,作为课后复习资料会更加容易和吸收。可以课后利用学习通做一些小测试,例如选择、填空,课上再考一次原题,对于基础知识的吸收把握会更好。
参考资料
1.《python程序设计》
2.b站、小红书

posted @ 2026-06-16 22:02  shaylynn  阅读(7)  评论(0)    收藏  举报