【OpenGL】10 完整游戏开发实战:基于OpenGL的2D/3D游戏框架、物理引擎集成与AI辅助编程指南

摘要: 本文系统地介绍了使用Python和OpenGL进行游戏开发的完整流程,从2D精灵渲染、精灵表动画到3D场景图管理和角色控制器,再到物理引擎的集成。同时,本文还将分享如何利用GPT-5.4大模型辅助游戏开发,提供实用的提示词工程建议。由于国内无法直接访问OpenAI官网,翻墙访问属于违法行为,建议开发者通过合法的国内镜像站使用GPT-5.4最新模型进行开发辅助。注册入口:AIGCBAR镜像站。如涉及API调用开发,可访问:API独立站

1. 引言

OpenGL作为跨平台的图形编程API,虽然是3D渲染的行业标准,但同样适用于高性能2D游戏开发。本文将带你从零构建完整的游戏框架,涵盖2D精灵系统、3D场景图、角色控制器以及简易物理引擎的集成。

2. 2D游戏开发实战

2.1 精灵(Sprite)系统核心概念

2D游戏渲染的核心是精灵(Sprite)。精灵本质上是一个带有纹理的四边形,通过正交投影直接映射屏幕坐标到归一化设备坐标(NDC),无需透视变换。

关键技术点:

  • 正交投影:将屏幕像素坐标直接映射到OpenGL的[-1, 1]范围
  • 精灵表(Sprite Sheet):将多个精灵图像打包在单张纹理中,减少Draw Call和纹理切换开销
  • 纹理坐标变换:通过调整UV坐标实现精灵表中的图像切换和帧动画

2.2 完整2D精灵渲染系统实现

python 复制代码
from OpenGL.GL import *
import numpy as np
from PIL import Image

class Sprite:
    """精灵类 - 表示游戏中的2D图像元素"""
    
    def __init__(self, texture, x=0, y=0, width=1, height=1):
        """
        初始化精灵
        
        参数:
            texture: 纹理对象
            x, y: 精灵在屏幕空间的左下角位置
            width, height: 精灵尺寸(像素单位)
        """
        self.texture = texture
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        
        # 变换属性
        self.rotation = 0.0  # 旋转角度(度)
        self.scale = 1.0     # 缩放比例
        self.color = [1.0, 1.0, 1.0, 1.0]  # RGBA颜色
        
        # 纹理区域(用于精灵表切图)
        self.tex_x = 0.0
        self.tex_y = 0.0
        self.tex_width = 1.0
        self.tex_height = 1.0
    
    def set_texture_region(self, x, y, width, height, sheet_width, sheet_height):
        """设置纹理区域(精灵表中的UV坐标)"""
        self.tex_x = x / sheet_width
        self.tex_y = y / sheet_height
        self.tex_width = width / sheet_width
        self.tex_height = height / sheet_height


class SpriteRenderer:
    """基于GPU instancing的高效精灵渲染器"""
    
    def __init__(self, shader):
        """初始化VAO/VBO"""
        self.shader = shader
        self.VAO = glGenVertexArrays(1)
        self._init_render_data()
    
    def _init_render_data(self):
        """初始化四边形顶点数据"""
        # 两个三角形组成四边形 (位置x, 位置y, 纹理u, 纹理v)
        vertices = np.array([
            0.0, 1.0, 0.0, 1.0,  # 左上
            1.0, 0.0, 1.0, 0.0,  # 右下
            0.0, 0.0, 0.0, 0.0,  # 左下
            0.0, 1.0, 0.0, 1.0,  # 左上
            1.0, 1.0, 1.0, 1.0,  # 右上
            1.0, 0.0, 1.0, 0.0   # 右下
        ], dtype=np.float32)
        
        VBO = glGenBuffers(1)
        
        glBindVertexArray(self.VAO)
        glBindBuffer(GL_ARRAY_BUFFER, VBO)
        glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_STATIC_DRAW)
        
        # 位置属性 (location = 0)
        glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 16, ctypes.c_void_p(0))
        glEnableVertexAttribArray(0)
        
        glBindVertexArray(0)
    
    def draw_sprite(self, sprite):
        """绘制单个精灵"""
        self.shader.use()
        
        # 构建Model矩阵 (TRS: Translate -> Rotate -> Scale)
        model = np.eye(4, dtype=np.float32)
        
        # 平移到指定位置
        model[0, 3] = sprite.x
        model[1, 3] = sprite.y
        
        # 应用缩放
        model[0, 0] = sprite.width * sprite.scale
        model[1, 1] = sprite.height * sprite.scale
        
        # 绕中心点旋转
        if sprite.rotation != 0:
            center_x = sprite.width / 2
            center_y = sprite.height / 2
            
            cos_r = np.cos(np.radians(sprite.rotation))
            sin_r = np.sin(np.radians(sprite.rotation))
            
            # 构建旋转矩阵
            rotation = np.eye(4, dtype=np.float32)
            rotation[0, 0] = cos_r
            rotation[0, 1] = -sin_r
            rotation[1, 0] = sin_r
            rotation[1, 1] = cos_r
            
            # 平移到原点 -> 旋转 -> 平移回来
            translate_center = np.eye(4, dtype=np.float32)
            translate_center[0, 3] = center_x
            translate_center[1, 3] = center_y
            
            translate_back = np.eye(4, dtype=np.float32)
            translate_back[0, 3] = -center_x
            translate_back[1, 3] = -center_y
            
            model = np.dot(model, np.dot(translate_center, 
                         np.dot(rotation, translate_back)))
        
        # 设置Uniform变量
        self.shader.set_mat4("model", model)
        self.shader.set_vec4("spriteColor", sprite.color)
        self.shader.set_vec4("texRegion", [
            sprite.tex_x, sprite.tex_y, 
            sprite.tex_width, sprite.tex_height
        ])
        
        # 绑定纹理并绘制
        sprite.texture.bind(0)
        self.shader.set_int("image", 0)
        
        glBindVertexArray(self.VAO)
        glDrawArrays(GL_TRIANGLES, 0, 6)
        glBindVertexArray(0)
    
    def cleanup(self):
        """清理GPU资源"""
        glDeleteVertexArrays(1, [self.VAO])


# GLSL着色器代码
SPRITE_VERTEX_SHADER = """
#version 330 core
layout (location = 0) in vec4 vertex; // xy:位置, zw:纹理坐标

out vec2 TexCoord;

uniform mat4 model;
uniform mat4 projection;
uniform vec4 texRegion; // xy:偏移, zw:缩放

void main() {
    // 应用精灵表UV变换
    TexCoord = vertex.zw * texRegion.zw + texRegion.xy;
    gl_Position = projection * model * vec4(vertex.xy, 0.0, 1.0);
}
"""

SPRITE_FRAGMENT_SHADER = """
#version 330 core
in vec2 TexCoord;
out vec4 FragColor;

uniform sampler2D image;
uniform vec4 spriteColor;

void main() {
    vec4 texColor = texture(image, TexCoord);
    FragColor = texColor * spriteColor; // 应用颜色着色
}
"""

2.3 精灵动画系统

python 复制代码
class SpriteAnimation:
    """基于精灵表的帧动画系统"""
    
    def __init__(self, sprite_sheet, frame_width, frame_height, 
                 frames_per_row, frame_count, frame_duration):
        """
        参数:
            sprite_sheet: 精灵表纹理对象
            frame_width/frame_height: 单帧像素尺寸
            frames_per_row: 每行排列的帧数
            frame_count: 总帧数
            frame_duration: 每帧持续时间(秒)
        """
        self.sprite_sheet = sprite_sheet
        self.frame_width = frame_width
        self.frame_height = frame_height
        self.frames_per_row = frames_per_row
        self.frame_count = frame_count
        self.frame_duration = frame_duration
        
        self.current_frame = 0
        self.elapsed_time = 0.0
        self.playing = True
        self.loop = True
    
    def update(self, delta_time):
        """更新动画状态"""
        if not self.playing:
            return
        
        self.elapsed_time += delta_time
        
        if self.elapsed_time >= self.frame_duration:
            self.elapsed_time -= self.frame_duration
            self.current_frame += 1
            
            if self.current_frame >= self.frame_count:
                if self.loop:
                    self.current_frame = 0
                else:
                    self.current_frame = self.frame_count - 1
                    self.playing = False
    
    def apply_to_sprite(self, sprite):
        """将当前帧应用到精灵的纹理区域"""
        row = self.current_frame // self.frames_per_row
        col = self.current_frame % self.frames_per_row
        
        x = col * self.frame_width
        y = row * self.frame_height
        
        sprite.set_texture_region(
            x, y, 
            self.frame_width, 
            self.frame_height,
            self.sprite_sheet.width,
            self.sprite_sheet.height
        )

3. 3D游戏开发框架

3.1 场景图(Scene Graph)架构

场景图是组织3D场景的树形数据结构,支持层级变换和复杂的空间关系:

python 复制代码
import glfw
from OpenGL.GL import *
import numpy as np
from abc import ABC, abstractmethod

class SceneNode:
    """3D场景节点基类"""
    
    def __init__(self, name="Node"):
        self.name = name
        self.children = []
        self.parent = None
        
        # 本地变换
        self.position = np.array([0.0, 0.0, 0.0], dtype=np.float32)
        self.rotation = np.array([0.0, 0.0, 0.0], dtype=np.float32)  # 欧拉角(度)
        self.scale = np.array([1.0, 1.0, 1.0], dtype=np.float32)
        
        # 世界变换缓存
        self._world_matrix = None
        self._dirty = True  # 脏标记,避免重复计算
    
    def add_child(self, child):
        """添加子节点,自动建立父子关系"""
        child.parent = self
        self.children.append(child)
        child._dirty = True
    
    def remove_child(self, child):
        """移除子节点"""
        if child in self.children:
            child.parent = None
            self.children.remove(child)
            child._dirty = True
    
    def get_world_matrix(self):
        """获取世界变换矩阵(惰性计算)"""
        if self._dirty or (self.parent and self.parent._dirty):
            self._world_matrix = self._compute_world_matrix()
            self._dirty = False
        return self._world_matrix
    
    def _compute_world_matrix(self):
        """递归计算世界矩阵"""
        local = self._get_local_matrix()
        if self.parent:
            parent_matrix = self.parent.get_world_matrix()
            return np.dot(parent_matrix, local)
        return local
    
    def _get_local_matrix(self):
        """构建本地TRS矩阵(YXZ旋转顺序)"""
        # 平移
        T = np.eye(4, dtype=np.float32)
        T[:3, 3] = self.position
        
        # 旋转(欧拉角转矩阵)
        rx, ry, rz = np.radians(self.rotation)
        
        # X轴旋转
        Rx = np.array([
            [1, 0, 0, 0],
            [0, np.cos(rx), -np.sin(rx), 0],
            [0, np.sin(rx), np.cos(rx), 0],
            [0, 0, 0, 1]
        ], dtype=np.float32)
        
        # Y轴旋转
        Ry = np.array([
            [np.cos(ry), 0, np.sin(ry), 0],
            [0, 1, 0, 0],
            [-np.sin(ry), 0, np.cos(ry), 0],
            [0, 0, 0, 1]
        ], dtype=np.float32)
        
        # Z轴旋转
        Rz = np.array([
            [np.cos(rz), -np.sin(rz), 0, 0],
            [np.sin(rz), np.cos(rz), 0, 0],
            [0, 0, 1, 0],
            [0, 0, 0, 1]
        ], dtype=np.float32)
        
        R = np.dot(Ry, np.dot(Rx, Rz))
        
        # 缩放
        S = np.diag([self.scale[0], self.scale[1], self.scale[2], 1.0])
        
        return np.dot(T, np.dot(R, S))
    
    def update(self, delta_time):
        """递归更新节点"""
        for child in self.children:
            child.update(delta_time)
    
    def render(self, shader, camera):
        """递归渲染"""
        for child in self.children:
            child.render(shader, camera)


class MeshNode(SceneNode):
    """可渲染的网格节点"""
    
    def __init__(self, mesh, material=None, name="Mesh"):
        super().__init__(name)
        self.mesh = mesh
        self.material = material
    
    def render(self, shader, camera):
        """渲染网格并递归子节点"""
        shader.use()
        
        # 设置MVP矩阵
        model = self.get_world_matrix()
        view = camera.get_view_matrix()
        projection = camera.get_projection_matrix()
        
        shader.set_mat4("model", model)
        shader.set_mat4("view", view)
        shader.set_mat4("projection", projection)
        shader.set_vec3("viewPos", camera.position)
        
        # 应用材质
        if self.material:
            self.material.apply(shader)
        
        self.mesh.draw()
        super().render(shader, camera)

3.2 角色控制器与摄像机系统

python 复制代码
class CharacterController:
    """第一/三人称角色控制器"""
    
    def __init__(self, node, camera=None):
        """
        参数:
            node: 角色根节点
            camera: 可选的跟随摄像机(第三人称)
        """
        self.node = node
        self.camera = camera
        
        # 移动参数
        self.walk_speed = 3.0
        self.run_speed = 6.0
        self.jump_force = 8.0
        self.gravity = 20.0
        
        # 物理状态
        self.velocity = np.zeros(3, dtype=np.float32)
        self.is_grounded = True
        self.is_running = False
        
        # 输入状态
        self.move_input = np.zeros(2, dtype=np.float32)
        self.jump_pressed = False
    
    def update(self, delta_time):
        """每帧更新角色状态"""
        # 归一化输入方向
        move_dir = np.array([
            self.move_input[0], 0.0, self.move_input[1]
        ], dtype=np.float32)
        
        if np.linalg.norm(move_dir) > 0:
            move_dir /= np.linalg.norm(move_dir)
        
        # 计算目标速度
        speed = self.run_speed if self.is_running else self.walk_speed
        target_vel = move_dir * speed
        target_vel[1] = self.velocity[1]  # 保持垂直速度
        
        # 平滑插值(惯性效果)
        self.velocity[0] += (target_vel[0] - self.velocity[0]) * 10.0 * delta_time
        self.velocity[2] += (target_vel[2] - self.velocity[2]) * 10.0 * delta_time
        
        # 重力模拟
        if not self.is_grounded:
            self.velocity[1] -= self.gravity * delta_time
        
        # 跳跃
        if self.jump_pressed and self.is_grounded:
            self.velocity[1] = self.jump_force
            self.is_grounded = False
            self.jump_pressed = False
        
        # 更新位置
        self.node.position += self.velocity * delta_time
        
        # 简单地面碰撞
        if self.node.position[1] < 0:
            self.node.position[1] = 0
            self.velocity[1] = 0
            self.is_grounded = True
        
        # 面向移动方向
        if np.linalg.norm(move_dir) > 0.1:
            angle = np.arctan2(move_dir[0], move_dir[2])
            self.node.rotation[1] = np.degrees(angle)
        
        # 更新摄像机跟随
        if self.camera:
            self.camera.set_target(self.node.position + np.array([0, 1.5, 0]))
    
    def handle_input(self, key, action):
        """GLFW键盘输入处理"""
        if action == glfw.PRESS:
            if key == glfw.KEY_W:
                self.move_input[1] += 1
            elif key == glfw.KEY_S:
                self.move_input[1] -= 1
            elif key == glfw.KEY_A:
                self.move_input[0] -= 1
            elif key == glfw.KEY_D:
                self.move_input[0] += 1
            elif key == glfw.KEY_SPACE:
                self.jump_pressed = True
            elif key == glfw.KEY_LEFT_SHIFT:
                self.is_running = True
        
        elif action == glfw.RELEASE:
            if key == glfw.KEY_W:
                self.move_input[1] -= 1
            elif key == glfw.KEY_S:
                self.move_input[1] += 1
            elif key == glfw.KEY_A:
                self.move_input[0] += 1
            elif key == glfw.KEY_D:
                self.move_input[0] -= 1
            elif key == glfw.KEY_LEFT_SHIFT:
                self.is_running = False

3.3 游戏主循环框架

python 复制代码
class Game:
    """OpenGL游戏主类"""
    
    def __init__(self, width=1280, height=720):
        self.width = width
        self.height = height
        self.window = None
        self.scene_root = None
        self.camera = None
        self.shader = None
        self.delta_time = 0.0
        self.last_time = 0.0
    
    def init(self):
        """初始化GLFW和OpenGL"""
        if not glfw.init():
            raise RuntimeError("GLFW初始化失败")
        
        # OpenGL 3.3 Core Profile
        glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
        glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3)
        glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
        
        self.window = glfw.create_window(
            self.width, self.height, "3D Game Framework", None, None
        )
        if not self.window:
            glfw.terminate()
            raise RuntimeError("窗口创建失败")
        
        glfw.make_context_current(self.window)
        
        # 设置回调
        glfw.set_key_callback(self.window, self._key_callback)
        glfw.set_framebuffer_size_callback(self.window, self._resize_callback)
        
        # OpenGL状态
        glEnable(GL_DEPTH_TEST)
        glEnable(GL_CULL_FACE)
        
        self._init_scene()
    
    def _init_scene(self):
        """初始化场景"""
        self.scene_root = SceneNode("Root")
        self.camera = ThirdPersonCamera(
            target=np.array([0.0, 1.0, 0.0]),
            distance=5.0
        )
        self.camera.set_aspect_ratio(self.width, self.height)
        
        # 加载着色器
        self.shader = Shader(BASIC_VERTEX_SHADER, BASIC_FRAGMENT_SHADER)
    
    def run(self):
        """主游戏循环"""
        self.last_time = glfw.get_time()
        
        while not glfw.window_should_close(self.window):
            current_time = glfw.get_time()
            self.delta_time = current_time - self.last_time
            self.last_time = current_time
            
            self._update(self.delta_time)
            self._render()
            
            glfw.swap_buffers(self.window)
            glfw.poll_events()
        
        self._cleanup()
    
    def _update(self, delta_time):
        """更新逻辑"""
        self.scene_root.update(delta_time)
        self.camera.update(delta_time)
    
    def _render(self):
        """渲染场景"""
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glClearColor(0.2, 0.3, 0.4, 1.0)
        
        self.scene_root.render(self.shader, self.camera)
    
    def _cleanup(self):
        """清理资源"""
        glfw.terminate()
    
    def _key_callback(self, window, key, scancode, action, mods):
        if key == glfw.KEY_ESCAPE and action == glfw.PRESS:
            glfw.set_window_should_close(window, True)
    
    def _resize_callback(self, window, width, height):
        self.width = width
        self.height = height
        glViewport(0, 0, width, height)
        if self.camera:
            self.camera.set_aspect_ratio(width, height)


# 3D基础光照着色器
BASIC_VERTEX_SHADER = """
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoord;

out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main() {
    FragPos = vec3(model * vec4(aPos, 1.0));
    Normal = mat3(transpose(inverse(model))) * aNormal;
    TexCoord = aTexCoord;
    gl_Position = projection * view * vec4(FragPos, 1.0);
}
"""

BASIC_FRAGMENT_SHADER = """
#version 330 core
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoord;

out vec4 FragColor;

uniform vec3 lightPos = vec3(10.0, 10.0, 10.0);
uniform vec3 viewPos;
uniform vec3 lightColor = vec3(1.0, 1.0, 1.0);
uniform vec3 objectColor = vec3(0.7, 0.7, 0.7);

void main() {
    // 环境光
    float ambientStrength = 0.1;
    vec3 ambient = ambientStrength * lightColor;
    
    // 漫反射 (Lambert)
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(lightPos - FragPos);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = diff * lightColor;
    
    // 镜面反射 (Phong)
    float specularStrength = 0.5;
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32.0);
    vec3 specular = specularStrength * spec * lightColor;
    
    vec3 result = (ambient + diffuse + specular) * objectColor;
    FragColor = vec4(result, 1.0);
}
"""

4. 物理引擎集成

4.1 简易物理系统实现

对于轻量级游戏,可以实现简易的物理系统而非引入完整的PhysX或Bullet:

python 复制代码
class PhysicsBody:
    """刚体物理组件"""
    
    def __init__(self, mass=1.0, position=None, velocity=None):
        self.mass = mass
        self.inv_mass = 1.0 / mass if mass > 0 else 0.0
        
        self.position = position if position else np.zeros(3, dtype=np.float32)
        self.velocity = velocity if velocity else np.zeros(3, dtype=np.float32)
        self.acceleration = np.zeros(3, dtype=np.float32)
        
        self.rotation = np.zeros(3, dtype=np.float32)
        self.angular_velocity = np.zeros(3, dtype=np.float32)
        
        # 累积力和力矩
        self.force = np.zeros(3, dtype=np.float32)
        self.torque = np.zeros(3, dtype=np.float32)
        
        # 阻尼
        self.linear_damping = 0.05
        self.angular_damping = 0.05
        
        self.collider = None
    
    def apply_force(self, force, point=None):
        """施加力(可选作用点计算力矩)"""
        self.force += force
        if point is not None:
            r = point - self.position
            self.torque += np.cross(r, force)
    
    def apply_impulse(self, impulse, point=None):
        """施加冲量(即时速度变化)"""
        self.velocity += impulse * self.inv_mass
        if point is not None:
            r = point - self.position
            self.angular_velocity += np.cross(r, impulse) * self.inv_mass
    
    def integrate(self, delta_time):
        """Semi-Implicit Euler积分"""
        # 线性运动
        self.acceleration = self.force * self.inv_mass
        self.velocity += self.acceleration * delta_time
        self.velocity *= (1.0 - self.linear_damping * delta_time)
        self.position += self.velocity * delta_time
        
        # 角运动
        self.angular_velocity *= (1.0 - self.angular_damping * delta_time)
        self.rotation += self.angular_velocity * delta_time
        
        # 清除力累积
        self.force.fill(0)
        self.torque.fill(0)


class PhysicsWorld:
    """物理世界管理器"""
    
    def __init__(self):
        self.bodies = []
        self.gravity = np.array([0.0, -9.81, 0.0], dtype=np.float32)
    
    def add_body(self, body):
        self.bodies.append(body)
    
    def step(self, delta_time):
        """物理模拟步进"""
        # 施加重力
        for body in self.bodies:
            if body.mass > 0:
                body.apply_force(self.gravity * body.mass)
        
        # 积分
        for body in self.bodies:
            body.integrate(delta_time)
        
        # 碰撞检测与解析
        self._resolve_collisions()
    
    def _resolve_collisions(self):
        """简化的球体碰撞检测"""
        for i in range(len(self.bodies)):
            for j in range(i + 1, len(self.bodies)):
                body_a = self.bodies[i]
                body_b = self.bodies[j]
                
                if body_a.collider and body_b.collider:
                    collision = self._check_sphere_collision(body_a, body_b)
                    if collision:
                        self._apply_collision_response(body_a, body_b, collision)
    
    def _check_sphere_collision(self, a, b):
        """检测两个球体碰撞"""
        if not isinstance(a.collider, SphereCollider) or \
           not isinstance(b.collider, SphereCollider):
            return None
        
        dist = np.linalg.norm(a.position - b.position)
        min_dist = a.collider.radius + b.collider.radius
        
        if dist < min_dist:
            normal = (b.position - a.position)
            normal = normal / np.linalg.norm(normal) if np.linalg.norm(normal) > 0 else np.array([0, 1, 0])
            return {
                'normal': normal,
                'depth': min_dist - dist,
                'point': a.position + normal * a.collider.radius
            }
        return None
    
    def _apply_collision_response(self, a, b, col):
        """应用冲量碰撞响应"""
        normal = col['normal']
        depth = col['depth']
        
        # 位置分离(防止穿透)
        total_inv_mass = a.inv_mass + b.inv_mass
        if total_inv_mass > 0:
            separation = normal * depth / total_inv_mass
            a.position -= separation * a.inv_mass
            b.position += separation * b.inv_mass
        
        # 计算相对速度
        rel_vel = a.velocity - b.velocity
        vel_along_normal = np.dot(rel_vel, normal)
        
        if vel_along_normal > 0:  # 物体正在分离
            return
        
        # 冲量计算(考虑弹性系数)
        restitution = 0.5
        j = -(1 + restitution) * vel_along_normal
        j /= total_inv_mass
        
        impulse = normal * j
        a.velocity += impulse * a.inv_mass
        b.velocity -= impulse * b.inv_mass


class SphereCollider:
    """球形碰撞体"""
    def __init__(self, radius):
        self.radius = radius
        self.body = None

5. GPT-5.4辅助游戏开发的提示词工程

5.1 代码生成提示词模板

在使用AI辅助OpenGL游戏开发时,精准的提示词能显著提升代码质量。以下是经过验证的提示词模板:

场景1:生成特定功能的渲染类

markdown 复制代码
请使用Python和OpenGL 3.3 Core Profile编写一个[2D粒子系统/3D地形渲染器]。

要求:
1. 使用现代OpenGL(VAO/VBO/Shader),不要使用固定管线
2. 包含完整的类结构,包括__init__、update、render和cleanup方法
3. 使用NumPy进行矩阵运算,PyOpenGL绑定
4. 添加类型提示和详细的中文注释
5. 考虑性能优化(如实例化渲染、批量绘制)
6. 提供对应的GLSL顶点着色器和片段着色器代码

上下文:
- 游戏框架使用GLFW窗口系统
- 已有Shader类封装了着色器编译和uniform设置
- 坐标系:Y轴向上,右手坐标系

场景2:调试复杂渲染问题

markdown 复制代码
我在OpenGL渲染中遇到了[闪烁/黑屏/纹理错乱]问题。

代码上下文:
[粘贴相关代码]

现象描述:
1. [具体描述错误现象]
2. [是否伴随GL_ERROR]
3. [帧率是否受影响]

请分析可能的原因并提供:
1. 系统的排查步骤(使用glGetError、RenderDoc等工具)
2. 代码中潜在问题的定位
3. 修复后的代码片段
4. 预防此类问题的最佳实践

场景3:性能优化建议

markdown 复制代码
请分析以下OpenGL渲染代码的性能瓶颈,并提供优化方案:
[粘贴性能敏感的渲染代码]

当前性能数据:
-  draw call数量:XXX
-  顶点数:XXX
-  帧率:XXX FPS

请提供:
1. 瓶颈分析(CPU/GPU边界、状态切换、带宽等)
2. 具体优化策略(合批、实例化、LOD、遮挡剔除等)
3. 优化后的伪代码或关键代码片段
4. 预期的性能提升幅度

5.2 提示词优化策略

1. 上下文给足原则

  • 始终说明OpenGL版本(如3.3 Core Profile)
  • 指定Python库版本(PyOpenGL、GLFW、Pygame等)
  • 提供已有的基础类结构(Shader、Camera、Texture等)

2. 约束明确原则

  • 明确禁止过时技术(如glBegin/glEnd、固定管线)
  • 指定代码风格(PEP8、类型提示、命名规范)
  • 要求错误处理(GL状态检查、资源清理)

3. 迭代优化流程

复制代码
第一轮:生成基础框架代码
第二轮:要求添加异常处理和资源管理
第三轮:要求优化性能(如减少CPU-GPU数据传输)
第四轮:要求添加详细注释和文档字符串

4. 代码审查提示词

markdown 复制代码
请审查以下OpenGL Python代码的质量:

1.  资源管理:是否正确释放VAO/VBO/Texture/Shader?
2.  错误处理:是否检查glGetError和着色器编译日志?
3.  性能隐患:是否存在冗余的状态切换或CPU端循环?
4.  可维护性:是否遵循单一职责原则,类结构是否清晰?
5.  兼容性:是否考虑了不同显卡驱动的兼容性?

请对每一点给出评分(1-10分)和具体改进建议。

6. 结语

本文完整演示了基于Python和OpenGL的游戏开发框架,涵盖从2D精灵渲染到3D场景管理,再到简易物理引擎的集成。掌握这些底层图形学原理,不仅能帮助你构建自定义游戏引擎,更能深入理解Unity、Unreal等商业引擎的工作原理。

代码创作使用AI声明:

由于国内无法直接访问OpenAI官网,通过翻墙方式访问属于违法行为 ,广大开发者应当严格遵守国家法律法规。对于希望使用GPT-5.4等先进AI模型辅助游戏开发的开发者,建议通过合法的国内镜像站进行注册和使用,这些平台提供合规的接入服务,能够安全、稳定地使用GPT-5.4最新模型的强大能力进行代码生成、调试辅助和架构设计。

国内开发者合法使用入口:AIGCBAR镜像站(提供GPT-5.4最新模型的合规访问服务)

如需在游戏引擎中集成AI生成功能或自动化工具链,涉及API调用开发的,可访问:API独立站

未来,随着实时光线追踪、AI生成内容(AIGC)等技术的发展,Python在游戏原型开发和工具链建设中的优势将更加明显。希望本文能为你的游戏开发之旅提供坚实的技术基础,同时提醒各位开发者务必通过合法渠道使用境外AI服务,共同维护良好的互联网环境。

完整代码实现(仿CF跳跳乐游戏):

python 复制代码
import pygame
import math
import random
import time
import threading
import psutil
import gc
import sys
import os
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GL.shaders import compileProgram, compileShader
from OpenGL.GLU import *
import numpy as np

# 资源限制配置 - 分配2G内存和2G GPU
MAX_MEMORY_MB = 2048  # 2GB内存
MAX_VRAM_MB = 2048  # 2GB GPU显存
MEMORY_CHECK_INTERVAL = 1.0

# 游戏配置
WINDOW_WIDTH = 1280
WINDOW_HEIGHT = 720
FPS = 60

# 物理常量 - CF跳跳乐风格调整
GRAVITY = -22.0
JUMP_FORCE = 12.0
MOVE_SPEED = 0.2
MOUSE_SENSITIVITY = 0.4

# 关卡配置 - 16个关卡,减小间距
TOTAL_LEVELS = 16
LEVEL_LENGTH = 120.0  # 减小关卡长度
LEVEL_SPACING = 5.0  # 关卡间距改为8米
TIME_LIMIT = 300.0

# CF跳跳乐风格颜色配置
COLORS = {
    'platform': (0.3, 0.7, 0.3),  # 草绿色平台
    'slope': (0.6, 0.4, 0.2),  # 棕色斜坡
    'bridge': (0.8, 0.6, 0.4),  # 木桥色
    'narrow': (0.7, 0.3, 0.3),  # 红色窄桥
    'checkpoint': (1.0, 1.0, 0.2),  # 黄色检查点
    'finish': (0.2, 1.0, 0.8),  # 青色终点
    'bounce': (1.0, 0.6, 0.2),  # 橙色弹跳
    'safe': (0.4, 0.8, 1.0),  # 蓝色安全区
    'spiral': (0.8, 0.2, 0.8),  # 紫色螺旋
    'railing': (0.9, 0.9, 0.9),  # 白色护栏
}


class ResourceManager:
    """GPU资源管理器"""

    def __init__(self):
        self.memory_usage = 0
        self.vram_usage = 0
        self.monitoring = True
        self.gpu_textures = []
        self.gpu_buffers = []
        self.start_monitoring()

    def start_monitoring(self):
        def monitor():
            while self.monitoring:
                try:
                    process = psutil.Process()
                    memory_info = process.memory_info()
                    self.memory_usage = memory_info.rss / (1024 * 1024)

                    # 模拟GPU显存使用情况
                    self.vram_usage = len(self.gpu_textures) * 4 + len(self.gpu_buffers) * 2

                    # 内存管理
                    if self.memory_usage > MAX_MEMORY_MB * 0.9:
                        gc.collect()

                    # GPU显存管理
                    if self.vram_usage > MAX_VRAM_MB * 0.9:
                        self.cleanup_gpu_resources()

                    time.sleep(MEMORY_CHECK_INTERVAL)
                except:
                    pass

        self.monitor_thread = threading.Thread(target=monitor, daemon=True)
        self.monitor_thread.start()

    def cleanup_gpu_resources(self):
        """清理GPU资源"""
        for texture in self.gpu_textures[-10:]:
            if glIsTexture(texture):
                glDeleteTextures(1, [texture])
        self.gpu_textures = self.gpu_textures[:-10]

    def register_gpu_texture(self, texture_id):
        """注册GPU纹理"""
        self.gpu_textures.append(texture_id)

    def register_gpu_buffer(self, buffer_id):
        """注册GPU缓冲区"""
        self.gpu_buffers.append(buffer_id)

    def get_usage_info(self):
        return {
            'memory_mb': self.memory_usage,
            'vram_mb': self.vram_usage,
            'gpu_textures': len(self.gpu_textures),
            'gpu_buffers': len(self.gpu_buffers)
        }


class Vector3:
    """优化的3D向量类"""

    def __init__(self, x=0.0, y=0.0, z=0.0):
        self.x = float(x)
        self.y = float(y)
        self.z = float(z)

    def __add__(self, other):
        return Vector3(self.x + other.x, self.y + other.y, self.z + other.z)

    def __sub__(self, other):
        return Vector3(self.x - other.x, self.y - other.y, self.z - other.z)

    def __mul__(self, scalar):
        return Vector3(self.x * scalar, self.y * scalar, self.z * scalar)

    def __truediv__(self, scalar):
        return Vector3(self.x / scalar, self.y / scalar, self.z / scalar)

    def dot(self, other):
        return self.x * other.x + self.y * other.y + self.z * other.z

    def cross(self, other):
        return Vector3(
            self.y * other.z - self.z * other.y,
            self.z * other.x - self.x * other.z,
            self.x * other.y - self.y * other.x
        )

    def length(self):
        return math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z)

    def length_squared(self):
        return self.x * self.x + self.y * self.y + self.z * self.z

    def normalize(self):
        length = self.length()
        if length > 0:
            return Vector3(self.x / length, self.y / length, self.z / length)
        return Vector3(0, 0, 0)

    def copy(self):
        return Vector3(self.x, self.y, self.z)


class FirstPersonCamera:
    """增强的第一人称相机"""

    def __init__(self, position=Vector3(0, 2, 0)):
        self.position = position
        self.yaw = -90.0
        self.pitch = 0.0

        # 相机向量
        self.front = Vector3(0, 0, -1)
        self.up = Vector3(0, 1, 0)
        self.right = Vector3(1, 0, 0)
        self.world_up = Vector3(0, 1, 0)

        # 鼠标控制
        self.last_mouse_x = WINDOW_WIDTH / 2
        self.last_mouse_y = WINDOW_HEIGHT / 2
        self.first_mouse = True

        # 相机效果
        self.shake_intensity = 0.0
        self.shake_duration = 0.0
        self.shake_offset = Vector3(0, 0, 0)
        self.fov = 75.0

        self.update_camera_vectors()

    def update_camera_vectors(self):
        """更新相机方向向量"""
        front = Vector3()
        front.x = math.cos(math.radians(self.yaw)) * math.cos(math.radians(self.pitch))
        front.y = math.sin(math.radians(self.pitch))
        front.z = math.sin(math.radians(self.yaw)) * math.cos(math.radians(self.pitch))

        self.front = front.normalize()
        self.right = self.front.cross(self.world_up).normalize()
        self.up = self.right.cross(self.front).normalize()

    def process_mouse_movement(self, xpos, ypos, constrain_pitch=True):
        """处理鼠标移动"""
        if self.first_mouse:
            self.last_mouse_x = xpos
            self.last_mouse_y = ypos
            self.first_mouse = False
            return

        xoffset = xpos - self.last_mouse_x
        yoffset = self.last_mouse_y - ypos

        self.last_mouse_x = xpos
        self.last_mouse_y = ypos

        xoffset *= MOUSE_SENSITIVITY
        yoffset *= MOUSE_SENSITIVITY

        self.yaw += xoffset
        self.pitch += yoffset

        if constrain_pitch:
            self.pitch = max(-89.0, min(89.0, self.pitch))

        self.update_camera_vectors()

    def get_view_matrix(self):
        """获取视图矩阵"""
        final_pos = self.position + self.shake_offset
        target = final_pos + self.front

        gluLookAt(
            final_pos.x, final_pos.y, final_pos.z,
            target.x, target.y, target.z,
            self.up.x, self.up.y, self.up.z
        )

    def add_shake(self, intensity, duration):
        """添加相机震动"""
        self.shake_intensity = intensity
        self.shake_duration = duration

    def update(self, dt):
        """更新相机"""
        if self.shake_duration > 0:
            self.shake_duration -= dt
            self.shake_offset = Vector3(
                (random.random() - 0.5) * self.shake_intensity,
                (random.random() - 0.5) * self.shake_intensity,
                (random.random() - 0.5) * self.shake_intensity
            )
        else:
            self.shake_offset = Vector3(0, 0, 0)


class EnhancedWaterRenderer:
    """增强的GPU水面渲染器"""

    def __init__(self, level=-2.0, size=300.0):
        self.level = level
        self.size = size
        self.animation_time = 0.0
        self.wave_speed = 3.0
        self.wave_height = 1.2
        self.grid_resolution = 80  # 适中的分辨率

        self.shader_program = None
        self.setup_water_shader()
        self.create_water_mesh()

    def setup_water_shader(self):
        """设置水面着色器 - 兼容版本"""
        vertex_shader_source = """
        varying vec3 world_pos;
        varying vec3 normal;

        uniform float time;
        uniform float wave_height;
        uniform float wave_speed;

        void main() {
            vec4 pos = gl_Vertex;

            // 多层波浪效果
            float wave1 = sin(pos.x * 0.1 + time * wave_speed) * wave_height;
            float wave2 = cos(pos.z * 0.15 + time * wave_speed * 0.8) * wave_height * 0.6;
            float wave3 = sin((pos.x + pos.z) * 0.08 + time * wave_speed * 1.2) * wave_height * 0.4;

            pos.y += wave1 + wave2 + wave3;
            world_pos = pos.xyz;

            // 计算动态法线
            float dx = cos(pos.x * 0.1 + time * wave_speed) * 0.1 * wave_height;
            float dz = -sin(pos.z * 0.15 + time * wave_speed * 0.8) * 0.15 * wave_height * 0.6;
            normal = normalize(vec3(-dx, 1.0, -dz));

            gl_Position = gl_ModelViewProjectionMatrix * pos;
        }
        """

        fragment_shader_source = """
        varying vec3 world_pos;
        varying vec3 normal;

        uniform float time;

        void main() {
            // 水面基色
            vec3 deep_water = vec3(0.0, 0.2, 0.5);
            vec3 shallow_water = vec3(0.2, 0.5, 0.8);
            vec3 foam_color = vec3(0.8, 0.9, 1.0);

            // 基础水色混合
            float depth_factor = smoothstep(-3.0, 0.0, world_pos.y);
            vec3 water_color = mix(deep_water, shallow_water, depth_factor);

            // 光照计算
            vec3 light_dir = normalize(vec3(1.0, 2.0, 1.0));
            float light_intensity = max(0.3, dot(normal, light_dir));

            // 反射效果
            vec3 view_dir = normalize(vec3(0.0, 1.0, 0.0) - world_pos);
            vec3 reflect_dir = reflect(-light_dir, normal);
            float specular = pow(max(dot(view_dir, reflect_dir), 0.0), 32.0);

            // 泡沫效果
            float foam = sin(world_pos.x * 0.2 + time * 2.0) * cos(world_pos.z * 0.3 + time * 1.5);
            foam = smoothstep(0.4, 1.0, foam) * 0.3;

            // 波纹效果
            float ripple = sin(length(world_pos.xz) * 0.3 - time * 3.0) * 0.15;

            // 最终颜色合成
            vec3 final_color = water_color * light_intensity;
            final_color = mix(final_color, foam_color, foam);
            final_color += vec3(specular * 0.6);
            final_color += vec3(ripple * 0.1);

            // 透明度
            float alpha = 0.8 + ripple * 0.1;

            gl_FragColor = vec4(final_color, alpha);
        }
        """

        try:
            # 编译顶点着色器
            vertex_shader = glCreateShader(GL_VERTEX_SHADER)
            glShaderSource(vertex_shader, vertex_shader_source)
            glCompileShader(vertex_shader)

            # 检查编译状态
            status = glGetShaderiv(vertex_shader, GL_COMPILE_STATUS)
            if not status:
                error = glGetShaderInfoLog(vertex_shader)
                print(f"顶点着色器编译错误: {error}")
                return

            # 编译片段着色器
            fragment_shader = glCreateShader(GL_FRAGMENT_SHADER)
            glShaderSource(fragment_shader, fragment_shader_source)
            glCompileShader(fragment_shader)

            # 检查编译状态
            status = glGetShaderiv(fragment_shader, GL_COMPILE_STATUS)
            if not status:
                error = glGetShaderInfoLog(fragment_shader)
                print(f"片段着色器编译错误: {error}")
                return

            # 创建着色器程序
            self.shader_program = glCreateProgram()
            glAttachShader(self.shader_program, vertex_shader)
            glAttachShader(self.shader_program, fragment_shader)
            glLinkProgram(self.shader_program)

            # 检查链接状态
            status = glGetProgramiv(self.shader_program, GL_LINK_STATUS)
            if not status:
                error = glGetProgramInfoLog(self.shader_program)
                print(f"着色器程序链接错误: {error}")
                self.shader_program = None
                return

            # 获取uniform位置
            self.time_uniform = glGetUniformLocation(self.shader_program, "time")
            self.wave_height_uniform = glGetUniformLocation(self.shader_program, "wave_height")
            self.wave_speed_uniform = glGetUniformLocation(self.shader_program, "wave_speed")

            print("✅ 水面着色器编译成功")

        except Exception as e:
            print(f"❌ 水面着色器编译失败: {e}")
            self.shader_program = None

    def create_water_mesh(self):
        """创建水面网格"""
        self.vertices = []
        self.indices = []

        step = self.size / self.grid_resolution

        # 生成顶点
        for i in range(self.grid_resolution + 1):
            for j in range(self.grid_resolution + 1):
                x = -self.size / 2 + i * step
                z = -self.size / 2 + j * step
                y = self.level

                self.vertices.extend([x, y, z])

        # 生成索引
        for i in range(self.grid_resolution):
            for j in range(self.grid_resolution):
                top_left = i * (self.grid_resolution + 1) + j
                top_right = top_left + 1
                bottom_left = (i + 1) * (self.grid_resolution + 1) + j
                bottom_right = bottom_left + 1

                self.indices.extend([top_left, bottom_left, top_right])
                self.indices.extend([top_right, bottom_left, bottom_right])

        # 创建GPU缓冲区
        try:
            self.VAO = glGenVertexArrays(1)
            self.VBO = glGenBuffers(1)
            self.EBO = glGenBuffers(1)

            glBindVertexArray(self.VAO)

            # 顶点缓冲区
            glBindBuffer(GL_ARRAY_BUFFER, self.VBO)
            vertices_array = np.array(self.vertices, dtype=np.float32)
            glBufferData(GL_ARRAY_BUFFER, vertices_array.nbytes, vertices_array, GL_STATIC_DRAW)
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * 4, ctypes.c_void_p(0))
            glEnableVertexAttribArray(0)

            # 索引缓冲区
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.EBO)
            indices_array = np.array(self.indices, dtype=np.uint32)
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_array.nbytes, indices_array, GL_STATIC_DRAW)

            glBindVertexArray(0)
            print("✅ 水面网格创建成功")

        except Exception as e:
            print(f"❌ 水面网格创建失败: {e}")
            self.VAO = None

    def update(self, dt):
        """更新水面"""
        self.animation_time += dt

    def render(self):
        """渲染水面"""
        # 启用混合
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

        if self.shader_program and self.VAO:
            # 使用着色器
            glUseProgram(self.shader_program)

            # 设置uniform变量
            if self.time_uniform != -1:
                glUniform1f(self.time_uniform, self.animation_time)
            if self.wave_height_uniform != -1:
                glUniform1f(self.wave_height_uniform, self.wave_height)
            if self.wave_speed_uniform != -1:
                glUniform1f(self.wave_speed_uniform, self.wave_speed)

            # 渲染网格
            glBindVertexArray(self.VAO)
            glDrawElements(GL_TRIANGLES, len(self.indices), GL_UNSIGNED_INT, None)
            glBindVertexArray(0)

            glUseProgram(0)
        else:
            # 回退渲染
            self.render_fallback()

        glDisable(GL_BLEND)

    def render_fallback(self):
        """回退渲染方法"""
        glPushMatrix()
        glTranslatef(0, self.level, 0)
        glScalef(self.size, 1.0, self.size)

        # 动态水面颜色
        wave_factor = math.sin(self.animation_time * 2) * 0.1 + 0.1
        glColor4f(0.2 + wave_factor, 0.5 + wave_factor, 0.8 + wave_factor, 0.7)

        # 网格水面
        glBegin(GL_QUADS)
        s = 0.5
        glVertex3f(-s, 0, -s)
        glVertex3f(s, 0, -s)
        glVertex3f(s, 0, s)
        glVertex3f(-s, 0, s)
        glEnd()

        glPopMatrix()


class GPURenderUtils:
    """GPU渲染工具类"""

    cube_vao = None
    cube_indices_count = 0

    @staticmethod
    def initialize_gpu_objects():
        """初始化GPU对象"""
        if GPURenderUtils.cube_vao is None:
            GPURenderUtils.cube_vao, GPURenderUtils.cube_indices_count = GPURenderUtils.create_cube_vao()

    @staticmethod
    def create_cube_vao(size=1.0):
        """创建立方体VAO"""
        s = size / 2.0

        # 顶点数据:位置(3) + 法线(3)
        vertices = np.array([
            # 前面
            -s, -s, s, 0, 0, 1,
            s, -s, s, 0, 0, 1,
            s, s, s, 0, 0, 1,
            -s, s, s, 0, 0, 1,
            # 后面
            -s, -s, -s, 0, 0, -1,
            -s, s, -s, 0, 0, -1,
            s, s, -s, 0, 0, -1,
            s, -s, -s, 0, 0, -1,
            # 顶面
            -s, s, -s, 0, 1, 0,
            -s, s, s, 0, 1, 0,
            s, s, s, 0, 1, 0,
            s, s, -s, 0, 1, 0,
            # 底面
            -s, -s, -s, 0, -1, 0,
            s, -s, -s, 0, -1, 0,
            s, -s, s, 0, -1, 0,
            -s, -s, s, 0, -1, 0,
            # 右面
            s, -s, -s, 1, 0, 0,
            s, s, -s, 1, 0, 0,
            s, s, s, 1, 0, 0,
            s, -s, s, 1, 0, 0,
            # 左面
            -s, -s, -s, -1, 0, 0,
            -s, -s, s, -1, 0, 0,
            -s, s, s, -1, 0, 0,
            -s, s, -s, -1, 0, 0,
        ], dtype=np.float32)

        indices = np.array([
            0, 1, 2, 2, 3, 0,  # 前面
            4, 5, 6, 6, 7, 4,  # 后面
            8, 9, 10, 10, 11, 8,  # 顶面
            12, 13, 14, 14, 15, 12,  # 底面
            16, 17, 18, 18, 19, 16,  # 右面
            20, 21, 22, 22, 23, 20,  # 左面
        ], dtype=np.uint32)

        try:
            VAO = glGenVertexArrays(1)
            VBO = glGenBuffers(1)
            EBO = glGenBuffers(1)

            glBindVertexArray(VAO)

            glBindBuffer(GL_ARRAY_BUFFER, VBO)
            glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_STATIC_DRAW)

            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO)
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.nbytes, indices, GL_STATIC_DRAW)

            # 位置属性
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * 4, ctypes.c_void_p(0))
            glEnableVertexAttribArray(0)
            # 法线属性
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * 4, ctypes.c_void_p(3 * 4))
            glEnableVertexAttribArray(1)

            glBindVertexArray(0)
            return VAO, len(indices)

        except Exception as e:
            print(f"创建立方体VAO失败: {e}")
            return None, 0

    @staticmethod
    def render_cube_vao():
        """渲染立方体VAO"""
        if GPURenderUtils.cube_vao:
            glBindVertexArray(GPURenderUtils.cube_vao)
            glDrawElements(GL_TRIANGLES, GPURenderUtils.cube_indices_count, GL_UNSIGNED_INT, None)
            glBindVertexArray(0)
        else:
            # 回退到immediate mode
            GPURenderUtils.draw_cube_immediate(1.0)

    @staticmethod
    def draw_cube_immediate(size=1.0):
        """immediate mode立方体渲染(回退方案)"""
        s = size / 2.0

        glBegin(GL_QUADS)

        # 前面
        glNormal3f(0, 0, 1)
        glVertex3f(-s, -s, s)
        glVertex3f(s, -s, s)
        glVertex3f(s, s, s)
        glVertex3f(-s, s, s)

        # 后面
        glNormal3f(0, 0, -1)
        glVertex3f(-s, -s, -s)
        glVertex3f(-s, s, -s)
        glVertex3f(s, s, -s)
        glVertex3f(s, -s, -s)

        # 顶面
        glNormal3f(0, 1, 0)
        glVertex3f(-s, s, -s)
        glVertex3f(-s, s, s)
        glVertex3f(s, s, s)
        glVertex3f(s, s, -s)

        # 底面
        glNormal3f(0, -1, 0)
        glVertex3f(-s, -s, -s)
        glVertex3f(s, -s, -s)
        glVertex3f(s, -s, s)
        glVertex3f(-s, -s, s)

        # 右面
        glNormal3f(1, 0, 0)
        glVertex3f(s, -s, -s)
        glVertex3f(s, s, -s)
        glVertex3f(s, s, s)
        glVertex3f(s, -s, s)

        # 左面
        glNormal3f(-1, 0, 0)
        glVertex3f(-s, -s, -s)
        glVertex3f(-s, -s, s)
        glVertex3f(-s, s, s)
        glVertex3f(-s, s, -s)

        glEnd()

    @staticmethod
    def set_color(color):
        """设置颜色"""
        if len(color) == 3:
            glColor3f(*color)
        elif len(color) == 4:
            glColor4f(*color)


class PhysicsBody:
    """优化的物理刚体"""

    def __init__(self, position, mass=1.0):
        self.position = position
        self.velocity = Vector3(0, 0, 0)
        self.on_ground = False
        self.mass = mass
        self.air_resistance = 0.99

    def apply_gravity(self, dt):
        """应用重力"""
        if not self.on_ground:
            self.velocity.y += GRAVITY * dt

    def update_position(self, dt):
        """更新位置"""
        self.position = self.position + self.velocity * dt

        # 空气阻力
        self.velocity.x *= self.air_resistance
        self.velocity.z *= self.air_resistance

    def apply_force(self, force):
        """施加力"""
        acceleration = force / self.mass
        self.velocity = self.velocity + acceleration


class CFPlatform:
    """CF跳跳乐风格平台"""

    def __init__(self, position, size, platform_type="static", color=None, rotation=Vector3(0, 0, 0)):
        self.position = position
        self.original_position = position.copy()
        self.size = size
        self.platform_type = platform_type
        self.rotation = rotation
        self.animation_time = 0.0
        self.has_railing = False
        self.railing_height = 2.0

        # 运动参数
        self.move_distance = 0.0
        self.move_speed = 1.0
        self.move_direction = 1
        self.bounce_power = 18.0
        self.float_amplitude = 1.5

        # 设置颜色
        if color:
            self.color = color
        elif platform_type == "slope":
            self.color = COLORS['slope']
        elif platform_type == "bridge":
            self.color = COLORS['bridge']
        elif platform_type == "narrow":
            self.color = COLORS['narrow']
        elif platform_type == "bounce":
            self.color = COLORS['bounce']
        elif platform_type == "checkpoint":
            self.color = COLORS['checkpoint']
        elif platform_type == "finish":
            self.color = COLORS['finish']
        elif platform_type == "safe":
            self.color = COLORS['safe']
            self.has_railing = True
        elif platform_type == "spiral":
            self.color = COLORS['spiral']
        else:
            self.color = COLORS['platform']

    def update(self, dt):
        """更新平台"""
        self.animation_time += dt

        if self.platform_type == "floating":
            float_offset = math.sin(self.animation_time * 2) * self.float_amplitude
            self.position.y = self.original_position.y + float_offset

        elif self.platform_type == "bounce":
            bounce_offset = abs(math.sin(self.animation_time * 4)) * 0.5
            self.position.y = self.original_position.y + bounce_offset

    def render(self):
        """渲染平台"""
        glPushMatrix()
        glTranslatef(self.position.x, self.position.y, self.position.z)
        glRotatef(self.rotation.x, 1, 0, 0)
        glRotatef(self.rotation.y, 0, 1, 0)
        glRotatef(self.rotation.z, 0, 0, 1)
        glScalef(self.size.x, self.size.y, self.size.z)

        GPURenderUtils.set_color(self.color)
        GPURenderUtils.render_cube_vao()

        glPopMatrix()

        # 渲染护栏
        if self.has_railing:
            self.render_railings()

    def render_railings(self):
        """渲染护栏"""
        railing_width = 0.2
        railing_positions = [
            Vector3(self.position.x - self.size.x / 2, self.position.y + self.railing_height / 2, self.position.z),
            Vector3(self.position.x + self.size.x / 2, self.position.y + self.railing_height / 2, self.position.z),
            Vector3(self.position.x, self.position.y + self.railing_height / 2, self.position.z - self.size.z / 2),
            Vector3(self.position.x, self.position.y + self.railing_height / 2, self.position.z + self.size.z / 2),
        ]

        GPURenderUtils.set_color(COLORS['railing'])
        for pos in railing_positions:
            glPushMatrix()
            glTranslatef(pos.x, pos.y, pos.z)
            glScalef(railing_width, self.railing_height, railing_width)
            GPURenderUtils.render_cube_vao()
            glPopMatrix()

    def check_collision(self, position, player_size):
        """检查碰撞"""
        platform_min = Vector3(
            self.position.x - self.size.x / 2,
            self.position.y - self.size.y / 2,
            self.position.z - self.size.z / 2
        )
        platform_max = Vector3(
            self.position.x + self.size.x / 2,
            self.position.y + self.size.y / 2,
            self.position.z + self.size.z / 2
        )

        player_min = Vector3(
            position.x - player_size.x / 2,
            position.y - player_size.y / 2,
            position.z - player_size.z / 2
        )
        player_max = Vector3(
            position.x + player_size.x / 2,
            position.y + player_size.y / 2,
            position.z + player_size.z / 2
        )

        return (player_max.x > platform_min.x and player_min.x < platform_max.x and
                player_max.y > platform_min.y and player_min.y < platform_max.y and
                player_max.z > platform_min.z and player_min.z < platform_max.z)

    def get_bounce_force(self):
        """获取弹跳力"""
        if self.platform_type == "bounce":
            return self.bounce_power
        return 0


class Player:
    """CF跳跳乐风格玩家"""

    def __init__(self, position=Vector3(0, 3, 0)):
        self.physics_body = PhysicsBody(position, 1.0)
        self.size = Vector3(0.6, 1.6, 0.6)

        # 游戏状态
        self.is_alive = True
        self.checkpoint_position = position.copy()
        self.current_checkpoint = 0
        self.current_level = 1

        # CF跳跳乐特色能力
        self.can_double_jump = True
        self.jump_count = 0
        self.max_jumps = 2
        self.in_water = False
        self.water_timer = 0.0
        self.max_water_time = 3.0

        # 统计
        self.level_start_time = time.time()
        self.falls = 0
        self.jumps = 0
        self.distance_traveled = 0.0
        self.perfect_landings = 0

    def update(self, dt, platforms, water_level=-2.0):
        """更新玩家"""
        if not self.is_alive:
            return

        old_position = self.physics_body.position.copy()

        # 应用物理
        self.physics_body.apply_gravity(dt)
        self.physics_body.update_position(dt)

        # 碰撞检测
        self.handle_collisions(platforms)

        # 检查水中
        if self.physics_body.position.y < water_level:
            if not self.in_water:
                self.in_water = True
                self.water_timer = 0.0
                print("💧 掉入水中!")

            self.water_timer += dt
            if self.water_timer > self.max_water_time:
                self.fall_in_water()
        else:
            self.in_water = False

        # 计算移动距离
        distance_moved = (self.physics_body.position - old_position).length()
        self.distance_traveled += distance_moved

    def handle_collisions(self, platforms):
        """处理碰撞"""
        player_pos = self.physics_body.position
        self.physics_body.on_ground = False

        for platform in platforms:
            if platform.check_collision(player_pos, self.size):
                if (player_pos.y > platform.position.y and
                        self.physics_body.velocity.y <= 0):

                    self.physics_body.position.y = platform.position.y + platform.size.y / 2 + self.size.y / 2
                    self.physics_body.velocity.y = 0
                    self.physics_body.on_ground = True
                    self.jump_count = 0

                    # 检查完美落地
                    if abs(self.physics_body.velocity.y) < 1.0:
                        self.perfect_landings += 1

                    # 检查弹跳
                    bounce_force = platform.get_bounce_force()
                    if bounce_force > 0:
                        self.physics_body.velocity.y = bounce_force
                        print("🚀 弹跳!")

    def jump(self):
        """跳跃"""
        if (self.physics_body.on_ground or
                (self.can_double_jump and self.jump_count < self.max_jumps)):

            self.physics_body.velocity.y = JUMP_FORCE
            self.jump_count += 1
            self.jumps += 1

            if self.jump_count == 1:
                print("🦘 跳跃!")
            else:
                print("🦘 二段跳!")

    def move(self, direction, dt):
        """移动"""
        if self.is_alive and not self.in_water:
            move_force = direction * MOVE_SPEED
            self.physics_body.apply_force(move_force)

    def fall_in_water(self):
        """掉入水中"""
        self.falls += 1
        self.respawn()
        print(f"🔄 重生!(第 {self.falls} 次掉落)")

    def respawn(self):
        """重生"""
        self.physics_body.position = self.checkpoint_position.copy()
        self.physics_body.velocity = Vector3(0, 0, 0)
        self.is_alive = True
        self.in_water = False
        self.water_timer = 0.0

    def reach_checkpoint(self, checkpoint_number, position, level_number):
        """到达检查点"""
        if checkpoint_number > self.current_checkpoint or level_number > self.current_level:
            self.current_checkpoint = checkpoint_number
            self.current_level = level_number
            self.checkpoint_position = position.copy()
            print(f"🏁 到达关卡 {level_number} 检查点 {checkpoint_number}!")

    def get_camera_position(self):
        """获取第一人称相机位置"""
        return Vector3(
            self.physics_body.position.x,
            self.physics_body.position.y + 0.8,
            self.physics_body.position.z
        )


class CFGameLevel:
    """CF跳跳乐风格16关卡系统 - 优化间距"""

    def __init__(self):
        self.current_level = 1
        self.platforms = []
        self.water = EnhancedWaterRenderer()
        self.checkpoints = []
        self.level_configs = self.create_level_configs()

        self.generate_all_levels()

    def create_level_configs(self):
        """创建16关卡配置"""
        return [
            {"name": "新手村", "theme": "基础跳跃", "difficulty": 1},
            {"name": "独木桥", "theme": "平衡挑战", "difficulty": 2},
            {"name": "阶梯山", "theme": "爬坡挑战", "difficulty": 2},
            {"name": "弹跳乐园", "theme": "弹跳平台", "difficulty": 3},
            {"name": "窄桥惊魂", "theme": "精确跳跃", "difficulty": 3},
            {"name": "螺旋塔", "theme": "螺旋上升", "difficulty": 4},
            {"name": "浮岛迷宫", "theme": "浮动平台", "difficulty": 4},
            {"name": "护栏小径", "theme": "安全区域", "difficulty": 3},
            {"name": "Z字跳跃", "theme": "折线路径", "difficulty": 4},
            {"name": "双层挑战", "theme": "多层平台", "difficulty": 5},
            {"name": "极限窄桥", "theme": "超窄跳跃", "difficulty": 5},
            {"name": "混合试炼", "theme": "综合挑战", "difficulty": 5},
            {"name": "高空漫步", "theme": "高空平台", "difficulty": 6},
            {"name": "终极螺旋", "theme": "复杂螺旋", "difficulty": 6},
            {"name": "大师之路", "theme": "专家级别", "difficulty": 7},
            {"name": "传奇终点", "theme": "最终挑战", "difficulty": 8},
        ]

    def generate_all_levels(self):
        """生成所有16个关卡 - 紧凑间距"""
        print("🏗️ 正在生成16个CF跳跳乐关卡...")

        current_x = 0

        for level_num in range(1, TOTAL_LEVELS + 1):
            current_x = self.generate_level(level_num, current_x)
            current_x += LEVEL_SPACING  # 使用较小的关卡间距

        print(f"✅ 所有16个关卡生成完成!")
        print(f"   总平台数量: {len(self.platforms)}")
        print(f"   总检查点数量: {len(self.checkpoints)}")

    def generate_level(self, level_num, start_x):
        """生成单个关卡 - 紧凑布局"""
        config = self.level_configs[level_num - 1]
        print(f"   生成关卡 {level_num}: {config['name']} - {config['theme']}")

        current_x = start_x

        if level_num == 1:  # 新手村
            current_x = self.generate_tutorial_level(current_x, level_num)
        elif level_num == 2:  # 独木桥
            current_x = self.generate_bridge_level(current_x, level_num)
        elif level_num == 3:  # 阶梯山
            current_x = self.generate_slope_level(current_x, level_num)
        elif level_num == 4:  # 弹跳乐园
            current_x = self.generate_bounce_level(current_x, level_num)
        elif level_num == 5:  # 窄桥惊魂
            current_x = self.generate_narrow_level(current_x, level_num)
        elif level_num == 6:  # 螺旋塔
            current_x = self.generate_spiral_level(current_x, level_num)
        elif level_num == 7:  # 浮岛迷宫
            current_x = self.generate_floating_level(current_x, level_num)
        elif level_num == 8:  # 护栏小径
            current_x = self.generate_safe_level(current_x, level_num)
        elif level_num == 9:  # Z字跳跃
            current_x = self.generate_zigzag_level(current_x, level_num)
        elif level_num == 10:  # 双层挑战
            current_x = self.generate_double_level(current_x, level_num)
        elif level_num == 11:  # 极限窄桥
            current_x = self.generate_extreme_narrow_level(current_x, level_num)
        elif level_num == 12:  # 混合试炼
            current_x = self.generate_mixed_level(current_x, level_num)
        elif level_num == 13:  # 高空漫步
            current_x = self.generate_high_altitude_level(current_x, level_num)
        elif level_num == 14:  # 终极螺旋
            current_x = self.generate_ultimate_spiral_level(current_x, level_num)
        elif level_num == 15:  # 大师之路
            current_x = self.generate_master_level(current_x, level_num)
        elif level_num == 16:  # 传奇终点
            current_x = self.generate_legendary_level(current_x, level_num)

        return current_x

    def generate_tutorial_level(self, start_x, level_num):
        """生成新手教学关卡"""
        current_x = start_x

        # 起始平台
        start_platform = CFPlatform(
            Vector3(current_x, 0, 0),
            Vector3(6, 1, 6),
            "safe"
        )
        self.platforms.append(start_platform)
        current_x += 8

        # 基础跳跃练习 - 间距减小
        for i in range(4):
            platform = CFPlatform(
                Vector3(current_x + i * 3, 1 + i * 0.3, 0),
                Vector3(2.5, 0.5, 2.5),
                "static"
            )
            self.platforms.append(platform)
        current_x += 15

        # 检查点
        checkpoint = CFPlatform(
            Vector3(current_x, 2.5, 0),
            Vector3(4, 1, 4),
            "checkpoint"
        )
        self.platforms.append(checkpoint)
        self.checkpoints.append((level_num, 1, Vector3(current_x, 3.5, 0)))

        return current_x + 3

    def generate_bridge_level(self, start_x, level_num):
        """生成独木桥关卡"""
        current_x = start_x

        # 长独木桥 - 间距紧凑
        bridge_sections = 6
        for i in range(bridge_sections):
            platform = CFPlatform(
                Vector3(current_x + i * 1.8, 3, 0),
                Vector3(1.8, 0.3, 0.8),
                "bridge"
            )
            self.platforms.append(platform)
        current_x += bridge_sections * 1.8 + 2

        # 检查点
        checkpoint = CFPlatform(
            Vector3(current_x, 3, 0),
            Vector3(3, 1, 3),
            "checkpoint"
        )
        self.platforms.append(checkpoint)
        self.checkpoints.append((level_num, 1, Vector3(current_x, 4, 0)))

        return current_x + 3

    def generate_slope_level(self, start_x, level_num):
        """生成爬坡关卡"""
        current_x = start_x

        # 斜坡阶梯 - 间距减小
        for i in range(5):
            platform = CFPlatform(
                Vector3(current_x + i * 2.5, 1 + i * 1.2, 0),
                Vector3(3, 0.5, 2),
                "slope",
                rotation=Vector3(0, 0, 10)
            )
            self.platforms.append(platform)
        current_x += 15

        # 检查点
        checkpoint = CFPlatform(
            Vector3(current_x, 7, 0),
            Vector3(4, 1, 4),
            "checkpoint"
        )
        self.platforms.append(checkpoint)
        self.checkpoints.append((level_num, 1, Vector3(current_x, 8, 0)))

        return current_x + 3

    def generate_bounce_level(self, start_x, level_num):
        """生成弹跳关卡"""
        current_x = start_x

        # 弹跳平台序列 - 间距减小
        for i in range(4):
            platform = CFPlatform(
                Vector3(current_x + i * 4, 2 + i * 1.5, 0),
                Vector3(2, 0.5, 2),
                "bounce"
            )
            self.platforms.append(platform)
        current_x += 18

        # 检查点
        checkpoint = CFPlatform(
            Vector3(current_x, 8, 0),
            Vector3(4, 1, 4),
            "checkpoint"
        )
        self.platforms.append(checkpoint)
        self.checkpoints.append((level_num, 1, Vector3(current_x, 9, 0)))

        return current_x + 3

    def generate_narrow_level(self, start_x, level_num):
        """生成窄桥关卡"""
        current_x = start_x

        # 超窄跳跃 - 间距减小
        for i in range(6):
            platform = CFPlatform(
                Vector3(current_x + i * 2.5, 5, 0),
                Vector3(0.8, 0.3, 0.8),
                "narrow"
            )
            self.platforms.append(platform)
        current_x += 18

        # 检查点
        checkpoint = CFPlatform(
            Vector3(current_x, 5, 0),
            Vector3(3, 1, 3),
            "checkpoint"
        )
        self.platforms.append(checkpoint)
        self.checkpoints.append((level_num, 1, Vector3(current_x, 6, 0)))

        return current_x + 3

    def generate_spiral_level(self, start_x, level_num):
        """生成螺旋关卡"""
        current_x = start_x
        center_x = current_x + 6  # 减小螺旋半径

        # 螺旋上升路径
        radius = 5  # 减小半径
        for i in range(8):  # 减少平台数量
            angle = i * 45  # 每45度一个平台
            x = center_x + math.cos(math.radians(angle)) * radius
            z = math.sin(math.radians(angle)) * radius
            y = 2 + i * 1.0

            platform = CFPlatform(
                Vector3(x, y, z),
                Vector3(2, 0.5, 2),
                "spiral"
            )
            self.platforms.append(platform)

        current_x = center_x + radius + 3

        # 检查点
        checkpoint = CFPlatform(
            Vector3(current_x, 10, 0),
            Vector3(4, 1, 4),
            "checkpoint"
        )
        self.platforms.append(checkpoint)
        self.checkpoints.append((level_num, 1, Vector3(current_x, 11, 0)))

        return current_x + 3

    def generate_floating_level(self, start_x, level_num):
        """生成浮动平台关卡"""
        current_x = start_x

        # 浮动平台 - 间距减小
        for i in range(5):
            platform = CFPlatform(
                Vector3(current_x + i * 3, 6, random.uniform(-2, 2)),
                Vector3(2, 0.5, 2),
                "floating"
            )
            self.platforms.append(platform)
        current_x += 18

        # 检查点
        checkpoint = CFPlatform(
            Vector3(current_x, 6, 0),
            Vector3(4, 1, 4),
            "checkpoint"
        )
        self.platforms.append(checkpoint)
        self.checkpoints.append((level_num, 1, Vector3(current_x, 7, 0)))

        return current_x + 3

    def generate_safe_level(self, start_x, level_num):
        """生成护栏安全关卡"""
        current_x = start_x

        # 带护栏的安全平台 - 间距减小
        for i in range(4):
            platform = CFPlatform(
                Vector3(current_x + i * 4, 4, 0),
                Vector3(3.5, 0.5, 2.5),
                "safe"
            )
            self.platforms.append(platform)
        current_x += 18

        # 检查点
        checkpoint = CFPlatform(
            Vector3(current_x, 4, 0),
            Vector3(5, 1, 5),
            "checkpoint"
        )
        self.platforms.append(checkpoint)
        self.checkpoints.append((level_num, 1, Vector3(current_x, 5, 0)))

        return current_x + 3

    def generate_zigzag_level(self, start_x, level_num):
        """生成Z字形关卡"""
        current_x = start_x

        # Z字形路径 - 间距减小
        for i in range(6):
            z_offset = 3 if i % 2 == 0 else -3  # 减小Z偏移
            platform = CFPlatform(
                Vector3(current_x + i * 2.5, 6, z_offset),
                Vector3(2, 0.5, 2),
                "static"
            )
            self.platforms.append(platform)
        current_x += 18

        # 检查点
        checkpoint = CFPlatform(
            Vector3(current_x, 6, 0),
            Vector3(4, 1, 4),
            "checkpoint"
        )
        self.platforms.append(checkpoint)
        self.checkpoints.append((level_num, 1, Vector3(current_x, 7, 0)))

        return current_x + 3

    def generate_double_level(self, start_x, level_num):
        """生成双层关卡"""
        current_x = start_x

        # 双层平台结构 - 间距减小
        for i in range(4):
            # 下层
            lower_platform = CFPlatform(
                Vector3(current_x + i * 3, 3, -1.5),
                Vector3(2, 0.5, 2),
                "static"
            )
            self.platforms.append(lower_platform)

            # 上层
            upper_platform = CFPlatform(
                Vector3(current_x + i * 3, 7, 1.5),
                Vector3(2, 0.5, 2),
                "static"
            )
            self.platforms.append(upper_platform)

        current_x += 15

        # 检查点
        checkpoint = CFPlatform(
            Vector3(current_x, 7, 0),
            Vector3(4, 1, 4),
            "checkpoint"
        )
        self.platforms.append(checkpoint)
        self.checkpoints.append((level_num, 1, Vector3(current_x, 8, 0)))

        return current_x + 3

    def generate_extreme_narrow_level(self, start_x, level_num):
        """生成极限窄桥关卡"""
        current_x = start_x

        # 极窄跳跃 - 间距减小
        for i in range(8):
            platform = CFPlatform(
                Vector3(current_x + i * 2, 8, 0),
                Vector3(0.6, 0.3, 0.6),
                "narrow"
            )
            self.platforms.append(platform)
        current_x += 18

        # 检查点
        checkpoint = CFPlatform(
            Vector3(current_x, 8, 0),
            Vector3(3, 1, 3),
            "checkpoint"
        )
        self.platforms.append(checkpoint)
        self.checkpoints.append((level_num, 1, Vector3(current_x, 9, 0)))

        return current_x + 3

    def generate_mixed_level(self, start_x, level_num):
        """生成混合挑战关卡"""
        current_x = start_x

        # 混合各种平台类型 - 间距减小
        platform_types = ["static", "bounce", "narrow", "slope", "floating"]
        for i in range(6):
            platform_type = platform_types[i % len(platform_types)]
            platform = CFPlatform(
                Vector3(current_x + i * 2.8, 5 + i * 0.6, random.uniform(-1.5, 1.5)),
                Vector3(1.5, 0.5, 1.5),
                platform_type
            )
            self.platforms.append(platform)
        current_x += 20

        # 检查点
        checkpoint = CFPlatform(
            Vector3(current_x, 8, 0),
            Vector3(4, 1, 4),
            "checkpoint"
        )
        self.platforms.append(checkpoint)
        self.checkpoints.append((level_num, 1, Vector3(current_x, 9, 0)))

        return current_x + 3

    def generate_high_altitude_level(self, start_x, level_num):
        """生成高空漫步关卡"""
        current_x = start_x

        # 高空平台 - 间距减小
        for i in range(5):
            platform = CFPlatform(
                Vector3(current_x + i * 3.5, 12 + i * 1.5, 0),
                Vector3(2, 0.5, 2),
                "static"
            )
            self.platforms.append(platform)
        current_x += 20

        # 检查点
        checkpoint = CFPlatform(
            Vector3(current_x, 18, 0),
            Vector3(4, 1, 4),
            "checkpoint"
        )
        self.platforms.append(checkpoint)
        self.checkpoints.append((level_num, 1, Vector3(current_x, 19, 0)))

        return current_x + 3

    def generate_ultimate_spiral_level(self, start_x, level_num):
        """生成终极螺旋关卡"""
        current_x = start_x
        center_x = current_x + 8

        # 复杂螺旋 - 减小规模
        for i in range(12):
            angle = i * 30  # 每30度一个平台
            radius = 6 - i * 0.2  # 螺旋收缩
            x = center_x + math.cos(math.radians(angle)) * radius
            z = math.sin(math.radians(angle)) * radius
            y = 10 + i * 1.2

            platform = CFPlatform(
                Vector3(x, y, z),
                Vector3(1.5, 0.3, 1.5),
                "spiral"
            )
            self.platforms.append(platform)

        current_x = center_x + 8

        # 检查点
        checkpoint = CFPlatform(
            Vector3(current_x, 25, 0),
            Vector3(4, 1, 4),
            "checkpoint"
        )
        self.platforms.append(checkpoint)
        self.checkpoints.append((level_num, 1, Vector3(current_x, 26, 0)))

        return current_x + 3

    def generate_master_level(self, start_x, level_num):
        """生成大师之路关卡"""
        current_x = start_x

        # 大师级复杂路径 - 间距减小
        for i in range(8):
            x = current_x + i * 2.2
            y = 15 + math.sin(i * 0.5) * 2
            z = math.cos(i * 0.3) * 3

            platform = CFPlatform(
                Vector3(x, y, z),
                Vector3(1, 0.3, 1),
                "narrow"
            )
            self.platforms.append(platform)
        current_x += 20

        # 检查点
        checkpoint = CFPlatform(
            Vector3(current_x, 15, 0),
            Vector3(4, 1, 4),
            "checkpoint"
        )
        self.platforms.append(checkpoint)
        self.checkpoints.append((level_num, 1, Vector3(current_x, 16, 0)))

        return current_x + 3

    def generate_legendary_level(self, start_x, level_num):
        """生成传奇终点关卡"""
        current_x = start_x

        # 最终挑战 - 间距减小
        for i in range(10):
            x = current_x + i * 1.8
            y = 20 + i * 1.0
            z = math.sin(i * 0.4) * 4

            size = max(0.8, 2 - i * 0.1)  # 平台逐渐变小
            platform = CFPlatform(
                Vector3(x, y, z),
                Vector3(size, 0.3, size),
                "narrow" if i > 6 else "static"
            )
            self.platforms.append(platform)
        current_x += 20

        # 最终终点
        finish = CFPlatform(
            Vector3(current_x, 30, 0),
            Vector3(8, 2, 8),
            "finish"
        )
        self.platforms.append(finish)
        self.checkpoints.append((level_num, 1, Vector3(current_x, 32, 0)))

        return current_x + 5

    def update(self, dt):
        """更新关卡"""
        for platform in self.platforms:
            platform.update(dt)
        self.water.update(dt)

    def render(self):
        """渲染关卡"""
        # 渲染增强水面
        self.water.render()

        # 渲染所有平台
        for platform in self.platforms:
            platform.render()


class CFJumpGame:
    """CF跳跳乐主游戏类"""

    def __init__(self):
        print("🎮 初始化CF跳跳乐游戏...")

        pygame.init()
        self.screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT), DOUBLEBUF | OPENGL)
        pygame.display.set_caption("CF跳跳乐 - 16关卡挑战")

        # 隐藏鼠标并锁定
        pygame.mouse.set_visible(False)
        pygame.event.set_grab(True)

        self.setup_opengl()

        # 初始化GPU对象
        GPURenderUtils.initialize_gpu_objects()

        # 资源管理
        self.resource_manager = ResourceManager()

        # 游戏对象
        self.camera = FirstPersonCamera()
        self.player = Player()
        self.level = CFGameLevel()

        # 游戏状态
        self.running = True
        self.paused = False
        self.game_completed = False
        self.mouse_captured = True

        # 键盘状态
        self.keys = {
            'W': False, 'A': False, 'S': False, 'D': False
        }

        # 计时
        self.level_timer = 0.0
        self.time_limit = TIME_LIMIT

        # 性能监控
        self.fps_counter = 0
        self.fps_timer = 0.0
        self.current_fps = 0

        # 时间管理
        self.clock = pygame.time.Clock()
        self.last_time = time.time()

        print("✅ CF跳跳乐游戏初始化完成!")
        self.print_instructions()

    def setup_opengl(self):
        """设置OpenGL渲染"""
        # 启用深度测试
        glEnable(GL_DEPTH_TEST)
        glDepthFunc(GL_LESS)

        # 启用面剔除
        glEnable(GL_CULL_FACE)
        glCullFace(GL_BACK)
        glFrontFace(GL_CCW)

        # 启用光照
        glEnable(GL_LIGHTING)
        glEnable(GL_LIGHT0)
        glEnable(GL_COLOR_MATERIAL)
        glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)

        # 高级光照设置
        light_pos = [100.0, 100.0, 100.0, 1.0]
        light_ambient = [0.5, 0.5, 0.5, 1.0]
        light_diffuse = [1.0, 1.0, 1.0, 1.0]
        light_specular = [1.0, 1.0, 1.0, 1.0]

        glLightfv(GL_LIGHT0, GL_POSITION, light_pos)
        glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient)
        glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse)
        glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular)

        # 材质设置
        glMaterialfv(GL_FRONT, GL_SPECULAR, [1.0, 1.0, 1.0, 1.0])
        glMaterialf(GL_FRONT, GL_SHININESS, 64.0)

        # 天空渐变背景
        glClearColor(0.6, 0.8, 1.0, 1.0)

        # 设置投影
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(75.0, WINDOW_WIDTH / WINDOW_HEIGHT, 0.1, 500.0)
        glMatrixMode(GL_MODELVIEW)

        print("✅ GPU渲染设置完成")

    def print_instructions(self):
        """打印游戏说明"""
        print("\n" + "=" * 60)
        print("🎮 CF跳跳乐 - 16关卡挑战 🎮")
        print("=" * 60)
        print("🎯 目标:通过16个CF风格跳跃关卡!")
        print("⏰ 时间限制:5分钟")
        print("💧 小心不要掉入水中!")
        print()
        print("🗺️ 关卡预览:")
        for i, config in enumerate(self.level.level_configs, 1):
            print(f"   {i:2d}. {config['name']} - {config['theme']} (难度:{config['difficulty']})")
        print()
        print("🎮 控制方法:")
        print("   W/A/S/D - 移动")
        print("   空格 - 跳跃 (支持二段跳)")
        print("   鼠标 - 转动视角")
        print("   ESC - 暂停")
        print("   R - 重生")
        print("   Q - 退出")
        print()
        print("🏆 开始CF跳跳乐挑战!")
        print("=" * 60)

    def handle_events(self):
        """处理事件"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running = False

            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_w:
                    self.keys['W'] = True
                elif event.key == pygame.K_a:
                    self.keys['A'] = True
                elif event.key == pygame.K_s:
                    self.keys['S'] = True
                elif event.key == pygame.K_d:
                    self.keys['D'] = True
                elif event.key == pygame.K_SPACE:
                    self.player.jump()
                elif event.key == pygame.K_ESCAPE:
                    self.toggle_pause()
                elif event.key == pygame.K_q:
                    self.running = False
                elif event.key == pygame.K_r:
                    self.player.respawn()

            elif event.type == pygame.KEYUP:
                if event.key == pygame.K_w:
                    self.keys['W'] = False
                elif event.key == pygame.K_a:
                    self.keys['A'] = False
                elif event.key == pygame.K_s:
                    self.keys['S'] = False
                elif event.key == pygame.K_d:
                    self.keys['D'] = False

            elif event.type == pygame.MOUSEMOTION and self.mouse_captured and not self.paused:
                mouse_x, mouse_y = pygame.mouse.get_pos()
                self.camera.process_mouse_movement(mouse_x, mouse_y)

    def toggle_pause(self):
        """切换暂停状态"""
        self.paused = not self.paused
        self.mouse_captured = not self.paused
        pygame.mouse.set_visible(self.paused)
        pygame.event.set_grab(self.mouse_captured)

        if self.paused:
            print("⏸️ 游戏暂停")
        else:
            print("▶️ 游戏继续")
            pygame.mouse.set_pos(WINDOW_WIDTH // 2, WINDOW_HEIGHT // 2)
            self.camera.first_mouse = True

    def update(self, dt):
        """更新游戏状态"""
        if self.paused or self.game_completed:
            return

        # 更新计时器
        self.level_timer += dt

        # 检查时间限制
        remaining_time = self.time_limit - self.level_timer
        if remaining_time <= 60 and remaining_time > 59:
            print("⚠️ 警告:还有1分钟!")
            self.camera.add_shake(0.3, 0.5)

        if remaining_time <= 0:
            print("⏰ 时间到!挑战失败!")
            self.player.fall_in_water()
            self.level_timer = 0.0

        # FPS计算
        self.fps_counter += 1
        self.fps_timer += dt
        if self.fps_timer >= 1.0:
            self.current_fps = self.fps_counter
            self.fps_counter = 0
            self.fps_timer = 0.0

        # 处理玩家移动
        self.handle_player_movement(dt)

        # 更新游戏对象
        self.player.update(dt, self.level.platforms, self.level.water.level)
        self.level.update(dt)
        self.camera.update(dt)

        # 更新第一人称相机位置
        self.camera.position = self.player.get_camera_position()

        # 检查检查点
        self.check_checkpoints()

        # 检查终点
        self.check_finish_line()

    def handle_player_movement(self, dt):
        """处理玩家移动"""
        move_direction = Vector3(0, 0, 0)

        if self.keys['W']:
            move_direction = move_direction + self.camera.front
        if self.keys['S']:
            move_direction = move_direction - self.camera.front
        if self.keys['A']:
            move_direction = move_direction - self.camera.right
        if self.keys['D']:
            move_direction = move_direction + self.camera.right

        move_direction.y = 0

        if move_direction.length() > 0:
            move_direction = move_direction.normalize()
            self.player.move(move_direction, dt)

    def check_checkpoints(self):
        """检查检查点"""
        for level_num, checkpoint_num, checkpoint_pos in self.level.checkpoints:
            distance = (self.player.physics_body.position - checkpoint_pos).length()
            if distance < 5.0:
                self.player.reach_checkpoint(checkpoint_num, checkpoint_pos, level_num)

    def check_finish_line(self):
        """检查终点"""
        finish_platform = None
        for platform in self.level.platforms:
            if platform.platform_type == "finish":
                finish_platform = platform
                break

        if finish_platform:
            distance = (self.player.physics_body.position - finish_platform.position).length()
            if distance < 8.0:
                self.complete_game()

    def complete_game(self):
        """完成游戏"""
        if not self.game_completed:
            self.game_completed = True
            completion_time = self.level_timer

            print("\n" + "🎉" * 40)
            print("🏆 恭喜!CF跳跳乐16关卡全部通关!")
            print(f"⏱️ 完成时间: {completion_time:.2f}秒")
            print(f"🦶 总跳跃次数: {self.player.jumps}")
            print(f"💧 掉落次数: {self.player.falls}")
            print(f"📏 移动距离: {self.player.distance_traveled:.1f}米")
            print(f"🎯 完美落地: {self.player.perfect_landings}次")
            print(f"🏁 最高关卡: {self.player.current_level}")

            # 计算评分
            time_bonus = max(0, 1500 - int(completion_time * 2))
            jump_penalty = self.player.jumps * 1
            fall_penalty = self.player.falls * 100
            perfect_bonus = self.player.perfect_landings * 10
            final_score = max(0, time_bonus - jump_penalty - fall_penalty + perfect_bonus)

            print(f"🎯 最终得分: {final_score}")

            if final_score >= 1200:
                print("🥇 评级:CF跳跳乐传奇大师!")
            elif final_score >= 1000:
                print("🥈 评级:CF跳跃专家!")
            elif final_score >= 800:
                print("🥉 评级:CF跳跃高手!")
            elif final_score >= 600:
                print("🏅 评级:CF跳跃达人!")
            else:
                print("📋 评级:CF跳跃新手")

            print("🎉" * 40)

    def render(self):
        """渲染游戏"""
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        # 设置第一人称视图
        glLoadIdentity()
        self.camera.get_view_matrix()

        # 渲染关卡
        self.level.render()

        pygame.display.flip()
        self.print_game_info()

    def print_game_info(self):
        """输出游戏信息"""
        if hasattr(self, '_last_info_update'):
            if time.time() - self._last_info_update < 1.0:
                return

        remaining_time = max(0, self.time_limit - self.level_timer)
        resource_info = self.resource_manager.get_usage_info()

        info = (f"\r[FPS:{self.current_fps:3d}] [时间:{remaining_time:5.1f}s] "
                f"[关卡:{self.player.current_level}/16] [检查点:{self.player.current_checkpoint}] "
                f"[跳跃:{self.player.jumps}] [掉落:{self.player.falls}] "
                f"[内存:{resource_info['memory_mb']:.0f}MB] [VRAM:{resource_info['vram_mb']:.0f}MB]")

        print(info, end="")
        self._last_info_update = time.time()

    def run(self):
        """主游戏循环"""
        try:
            while self.running:
                current_time = time.time()
                dt = current_time - self.last_time
                self.last_time = current_time

                dt = min(dt, 1.0 / 30.0)

                self.handle_events()
                self.update(dt)
                self.render()
                self.clock.tick(FPS)

        except Exception as e:
            print(f"\n❌ 游戏运行出错: {e}")
            import traceback
            traceback.print_exc()

        finally:
            self.cleanup()

    def cleanup(self):
        """清理资源"""
        print("\n🧹 正在清理CF跳跳乐资源...")
        self.resource_manager.monitoring = False
        print("🎮 感谢游玩CF跳跳乐!再见!")
        pygame.quit()


def main():
    """主函数"""
    try:
        print("🚀 正在启动CF跳跳乐...")

        # 检查系统要求
        available_memory = psutil.virtual_memory().available / (1024 ** 3)
        if available_memory < 2:
            print(f"⚠️ 警告:可用内存不足 {available_memory:.1f}GB")
        else:
            print(f"✅ 可用内存: {available_memory:.1f}GB")

        game = CFJumpGame()
        game.run()

    except ImportError as e:
        print(f"❌ 缺少必要的库: {e}")
        print("请运行: pip install pygame PyOpenGL PyOpenGL_accelerate numpy psutil")
    except Exception as e:
        print(f"❌ 游戏启动失败: {e}")
        import traceback
        traceback.print_exc()


if __name__ == "__main__":
    main()

# =============================================================================
# 🎮 CF跳跳乐参数调整区域 - 优化版
# =============================================================================
"""
🔧 CF跳跳乐游戏参数调整指南 - 已优化间距和水面效果:

🏗️ 关卡间距优化:
- LEVEL_SPACING: 当前8.0,关卡间距大幅减小
- 各关卡内平台间距减小到1.8-3.5米
- 螺旋半径减小,高度压缩
- 所有跳跃距离更加紧凑

💧 水面效果增强:
- 修复了着色器兼容性问题
- 增加了回退渲染方案
- 动态波浪效果更明显
- 透明度和光照效果优化

🚀 GPU渲染优化:
- 所有几何体使用VAO/VBO
- 着色器错误处理优化
- GPU资源管理系统
- 回退渲染机制确保兼容性

🏃 移动控制参数:
- MOVE_SPEED: 当前4.0,建议范围 3.0-6.0
- MOUSE_SENSITIVITY: 当前0.4,建议范围 0.2-0.8
- JUMP_FORCE: 当前12.0,建议范围 8.0-16.0
- GRAVITY: 当前-22.0,建议范围 -15.0 到 -30.0

⚙️ 快速预设配置:

🔰 新手模式(宽松间距):
MOVE_SPEED = 3.0
MOUSE_SENSITIVITY = 0.3
JUMP_FORCE = 14.0
GRAVITY = -18.0
LEVEL_SPACING = 10.0
TIME_LIMIT = 600.0

🎯 标准模式(当前设置):
MOVE_SPEED = 4.0
MOUSE_SENSITIVITY = 0.4
JUMP_FORCE = 12.0
GRAVITY = -22.0
LEVEL_SPACING = 8.0
TIME_LIMIT = 300.0

🏆 专家模式(紧凑间距):
MOVE_SPEED = 5.5
MOUSE_SENSITIVITY = 0.6
JUMP_FORCE = 10.0
GRAVITY = -26.0
LEVEL_SPACING = 6.0
TIME_LIMIT = 180.0

💧 水面效果参数:
- wave_speed: 当前3.0,波浪速度 (1.0-5.0)
- wave_height: 当前1.2,波浪高度 (0.5-2.0)
- grid_resolution: 当前80,网格分辨率 (40-128)

🎨 GPU渲染参数:
- MAX_MEMORY_MB: 2048MB (2GB内存)
- MAX_VRAM_MB: 2048MB (2GB显存)
- 自动GPU资源管理和清理

💡 关键优化:
1. 平台间距减小50%,连接更紧密
2. 水面着色器兼容性修复
3. GPU渲染管线优化
4. 错误恢复机制完善

修改参数后重新运行即可体验优化后的CF跳跃体验!
"""
相关推荐
刘简爱学习2 小时前
弱监督互斥多类脑肿瘤图像分割的类间可分离性损失
人工智能·深度学习·计算机视觉
AI英德西牛仔2 小时前
AI复制的文字带星号
人工智能·ai·chatgpt·豆包·deepseek·ds随心转
卖报的大地主2 小时前
扩散薛定谔桥(Diffusion Schrödinger Bridge)
人工智能
向成科技2 小时前
当“超轻量AI”遇上“最强国产芯”
人工智能·物联网·ai·芯片·国产化·硬件·主板
远见阁2 小时前
智能体是如何“思考”的:ReAct模式
人工智能·ai·ai智能体
L-影2 小时前
为什么你的数据里藏着“隐形圈子”?聊聊AI中的聚类
人工智能·ai·数据挖掘·聚类
江瀚视野2 小时前
小马智行Robotaxi营收增超1.2倍,小马的成绩单该咋看?
人工智能
Tony Bai2 小时前
Rust 看了流泪,AI 看了沉默:扒开 Go 泛型最让你抓狂的“残疾”类型推断
开发语言·人工智能·后端·golang·rust
2301_764441332 小时前
AI动态编排革命:Skill与Dify工作流终极对决
人工智能·机器学习