摘要: 本文系统地介绍了使用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跳跃体验!
"""