【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跳跃体验!
"""
相关推荐
ShineWinsu几秒前
AI训练硬件指南:GPU算力梯队与任务匹配框架
人工智能
rabbit_pro2 分钟前
Python调用onnx模型
开发语言·python
范桂飓4 分钟前
精选 Skills 清单
人工智能
码农的日常搅屎棍16 分钟前
AIAgent开发新选择:OpenHarness极简入门指南
人工智能
AC赳赳老秦18 分钟前
OpenClaw生成博客封面图+标题,适配CSDN视觉搜索,提升点击量
运维·人工智能·python·自动化·php·deepseek·openclaw
萝卜小白27 分钟前
算法实习Day04-MinerU2.5-pro
人工智能·算法·机器学习
geneculture29 分钟前
从人际间性到人机间性:进入人机互助新时代——兼论融智学视域下人类认知第二次大飞跃的理论奠基与实践场域
人工智能·融智学的重要应用·哲学与科学统一性·融智时代(杂志)·人际间性·人机间性·人际间文性
东方品牌观察33 分钟前
观澜社张庆解析AI:便利与挑战并存
人工智能
w_t_y_y36 分钟前
Agent 开发框架(一)有哪些框架&&A2A协议
人工智能
龙亘川1 小时前
医院通用人工智能平台设计与落地实践(2026)—— 面向智慧医院的 AI 操作系统架构解析
人工智能·医院通用人工智能平台技术白皮书