游戏与图形
本章讲解Cython在游戏和图形领域的应用。物理模拟、碰撞检测、图像处理可达5-50x加速,是游戏开发的利器。
学习路径:游戏逻辑 → 图像处理 → 渲染辅助
核心应用:
- 物理引擎:刚体模拟、碰撞检测
- 图像处理:像素操作、滤镜
- 顶点处理:骨骼动画、LOD
16.1 游戏逻辑
Section titled “16.1 游戏逻辑”功能说明:2D物理刚体,速度、加速度、位置更新。
cdef struct Vector2D: double x double y
cdef class PhysicsBody: cdef Vector2D _position cdef Vector2D _velocity cdef Vector2D _acceleration cdef double _mass
def __init__(self, double x, double y, double mass): self._position.x = x self._position.y = y self._velocity.x = 0.0 self._velocity.y = 0.0 self._acceleration.x = 0.0 self._acceleration.y = 0.0 self._mass = mass
cpdef void apply_force(self, double fx, double fy): """施加力:F = ma -> a = F/m""" self._acceleration.x += fx / self._mass self._acceleration.y += fy / self._mass
cpdef void update(self, double dt): """更新位置和速度""" self._velocity.x += self._acceleration.x * dt self._velocity.y += self._acceleration.y * dt self._position.x += self._velocity.x * dt self._position.y += self._velocity.y * dt
cpdef (double, double) get_position(self): return (self._position.x, self._position.y)输出示例:
>>> body = PhysicsBody(0.0, 0.0, 1.0)>>> body.apply_force(10.0, 0.0) # 施加水平力>>> body.update(0.1) # 0.1秒后>>> body.get_position()(1.0, 0.0)功能说明:AABB(轴对齐边界盒)碰撞检测。
cdef class AABB: cdef double _min_x cdef double _min_y cdef double _max_x cdef double _max_y
def __init__(self, double min_x, double min_y, double max_x, double max_y): self._min_x = min_x self._min_y = min_y self._max_x = max_x self._max_y = max_y
cpdef bint intersects(self, AABB other): """检测两个AABB是否相交""" return (self._min_x < other._max_x and self._max_x > other._min_x and self._min_y < other._max_y and self._max_y > other._min_y)
cpdef (double, double, double, double) get_bounds(self): return (self._min_x, self._min_y, self._max_x, self._max_y)输出示例:
>>> a = AABB(0, 0, 10, 10)>>> b = AABB(5, 5, 15, 15)>>> a.intersects(b)True>>> c = AABB(20, 20, 30, 30)>>> a.intersects(c)False功能说明:A*寻路算法,网格地图最短路径。
import heapq
cdef class AStarPathfinder: cdef int _width cdef int _height cdef list _grid
def __init__(self, int width, int height): self._width = width self._height = height self._grid = [[0] * width for _ in range(height)]
cpdef void set_wall(self, int x, int y): if 0 <= x < self._width and 0 <= y < self._height: self._grid[y][x] = 1
cpdef list find_path(self, int start_x, int start_y, int end_x, int end_y): cdef list open_set = [(0, start_x, start_y)] cdef dict came_from = {} cdef dict g_score = {(start_x, start_y): 0} cdef dict f_score = {(start_x, start_y): abs(end_x - start_x) + abs(end_y - start_y)}
while open_set: _, current_x, current_y = heapq.heappop(open_set)
if current_x == end_x and current_y == end_y: return self._reconstruct_path(came_from, current_x, current_y)
cdef list neighbors = [ (current_x+1, current_y), (current_x-1, current_y), (current_x, current_y+1), (current_x, current_y-1) ]
for nx, ny in neighbors: if not (0 <= nx < self._width and 0 <= ny < self._height): continue if self._grid[ny][nx] == 1: continue
cdef double tentative_g = g_score[(current_x, current_y)] + 1 cdef tuple key = (nx, ny)
if key not in g_score or tentative_g < g_score[key]: came_from[key] = (current_x, current_y) g_score[key] = tentative_g f_score[key] = tentative_g + abs(end_x - nx) + abs(end_y - ny) heapq.heappush(open_set, (f_score[key], nx, ny))
return []
cdef list _reconstruct_path(self, dict came_from, int x, int y): cdef list path = [(x, y)] cdef tuple current = (x, y) while current in came_from: current = came_from[current] path.insert(0, current) return path输出示例:
>>> pf = AStarPathfinder(10, 10)>>> pf.set_wall(5, 5)>>> pf.find_path(0, 0, 9, 9)[(0, 0), (1, 0), ..., (9, 9)] # 绕开墙壁的路径16.2 图像处理
Section titled “16.2 图像处理”功能说明:图像反色处理,逐像素操作。
import numpy as np
cpdef np.ndarray[np.uint8_t, ndim=3] invert_colors( np.ndarray[np.uint8_t, ndim=3] image): """反色处理:255 - pixel""" cdef int height = image.shape[0] cdef int width = image.shape[1] cdef int channels = image.shape[2] cdef np.ndarray result = np.empty_like(image) cdef int i, j, k
for i in range(height): for j in range(width): for k in range(channels): result[i, j, k] = 255 - image[i, j, k]
return result输出示例:
>>> img = np.array([[[100, 100, 100]]], dtype=np.uint8)>>> invert_colors(img)array([[[155, 155, 155]]], dtype=uint8)功能说明:简单模糊滤镜,窗口均值。
cpdef np.ndarray apply_blur( np.ndarray[np.uint8_t, ndim=3] image, int kernel_size=3): """简单模糊滤镜(均值滤波)""" cdef int height = image.shape[0] cdef int width = image.shape[1] cdef np.ndarray result = np.zeros_like(image) cdef int i, j, ki, kj cdef int offset = kernel_size // 2 cdef double total
for i in range(height): for j in range(width): total = 0.0 cdef int count = 0 for ki in range(max(0, i-offset), min(height, i+offset+1)): for kj in range(max(0, j-offset), min(width, j+offset+1)): total += image[ki, kj, 0] count += 1 result[i, j, 0] = <int>(total / count) result[i, j, 1] = result[i, j, 0] result[i, j, 2] = result[i, j, 0]
return result功能说明:二维点旋转和图像旋转。
cpdef (double, double) rotate_point( double x, double y, double cx, double cy, double angle): """旋转点绕中心""" cdef double dx = x - cx cdef double dy = y - cy cdef double cos_a = angle.cos() cdef double sin_a = angle.sin()
return ( cx + dx * cos_a - dy * sin_a, cy + dx * sin_a + dy * cos_a )
cpdef np.ndarray rotate_image( np.ndarray[np.uint8_t, ndim=2] image, double angle): """旋转图像(最近邻采样)""" cdef int h = image.shape[0] cdef int w = image.shape[1] cdef np.ndarray result = np.zeros_like(image) cdef int i, j cdef double new_x, new_y cdef double cx = w / 2.0 cdef double cy = h / 2.0
for i in range(h): for j in range(w): new_x, new_y = rotate_point(j, i, cx, cy, angle) if 0 <= new_x < w and 0 <= new_y < h: result[<int>new_y, <int>new_x] = image[i, j]
return result16.3 渲染辅助
Section titled “16.3 渲染辅助”功能说明:3D网格顶点数据管理。
cdef struct Vertex: double x, y, z double r, g, b, a double u, v
cdef class Mesh: cdef list _vertices cdef list _indices cdef list _transformed
def __init__(self): self._vertices = [] self._indices = []
cpdef void add_vertex(self, Vertex v): self._vertices.append(v)
cpdef void add_triangle(self, int i1, int i2, int i3): self._indices.extend([i1, i2, i3])
cpdef list get_transformed_vertices(self): return self._vertices功能说明:骨骼层级和矩阵管理。
cdef class Bone: cdef str _name cdef int _parent_index cdef list _children
def __init__(self, str name, int parent=-1): self._name = name self._parent_index = parent self._children = []
cpdef void add_child(self, int child_index): self._children.append(child_index)
cdef class Skeleton: cdef list _bones cdef list _matrices
def __init__(self): self._bones = [] self._matrices = []
cpdef int add_bone(self, str name, int parent=-1): cdef Bone bone = Bone(name, parent) self._bones.append(bone) return len(self._bones) - 1
cpdef void update_matrices(self): """更新骨骼矩阵""" pass功能说明:多细节层次系统,根据距离切换模型。
cdef class LODLevel: cdef int _distance cdef object _mesh
def __init__(self, int distance, object mesh): self._distance = distance self._mesh = mesh
cdef class LODSystem: cdef list _levels cdef int _current_level
def __init__(self): self._levels = [] self._current_level = 0
cpdef void add_level(self, int distance, object mesh): self._levels.append(LODLevel(distance, mesh))
cpdef object get_mesh_for_distance(self, int distance): cdef int best = 0 cdef int i for i in range(len(self._levels)): if self._levels[i]._distance <= distance: best = i return self._levels[best]._mesh| 领域 | Cython加速 | 适用场景 |
|---|---|---|
| 物理模拟 | 10-50x | 刚体碰撞 |
| 碰撞检测 | 5-20x | AABB检测 |
| 图像处理 | 3-10x | 滤镜/变换 |
| 顶点处理 | 5-15x | 骨骼动画 |
- 物理循环用
nogil提升性能 - AABB碰撞检测足够大多数游戏需求
- 图像处理用typed memoryview避免复制
- LOD系统按距离切换,减少渲染开销
- 实现AABB碰撞检测并测试相交判断
- 创建A*寻路算法,测试不同地图
- 实现图像反色滤镜,对比NumPy性能
- 创建LOD系统,支持多级细节切换
- 实现简单的骨骼动画系统(父子骨骼)
- 实现高斯模糊滤镜(加权平均)