Skip to content

游戏与图形

本章讲解Cython在游戏和图形领域的应用。物理模拟、碰撞检测、图像处理可达5-50x加速,是游戏开发的利器。

学习路径:游戏逻辑 → 图像处理 → 渲染辅助

核心应用:

  • 物理引擎:刚体模拟、碰撞检测
  • 图像处理:像素操作、滤镜
  • 顶点处理:骨骼动画、LOD

功能说明: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)] # 绕开墙壁的路径

功能说明:图像反色处理,逐像素操作。

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 result

功能说明: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-20xAABB检测
图像处理3-10x滤镜/变换
顶点处理5-15x骨骼动画
  1. 物理循环用nogil提升性能
  2. AABB碰撞检测足够大多数游戏需求
  3. 图像处理用typed memoryview避免复制
  4. LOD系统按距离切换,减少渲染开销

  1. 实现AABB碰撞检测并测试相交判断
  2. 创建A*寻路算法,测试不同地图
  3. 实现图像反色滤镜,对比NumPy性能
  4. 创建LOD系统,支持多级细节切换
  5. 实现简单的骨骼动画系统(父子骨骼)
  6. 实现高斯模糊滤镜(加权平均)