You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何利用Pygame的surface.set_at()绘制窗口对角线直线?

解决方案:用set_at()绘制直线

你的代码会填满整个屏幕,是因为嵌套循环遍历了所有屏幕像素并逐一绘制,自然会覆盖整个区域。要绘制直线,你只需要计算出这条直线上的像素坐标,仅对这些坐标调用draw_pixel即可。

下面提供两种实现方式,适合你自己编写2D渲染器的需求:

方法一:基于直线方程的简单实现

利用直线的斜截式方程计算每个x对应的y坐标,取整后绘制像素。注意Pygame的坐标系左上角为(0,0),所以左下角坐标是(0, 屏幕高度-1),右上角是(屏幕宽度-1, 0)。

import pygame as pg

# 初始化Pygame和窗口
pg.init()
width, height = 800, 600
screen = pg.display.set_mode((width, height))
background_colour = (0, 0, 0)

def draw_pixel(x, y, color):
    screen.set_at((x, y), color)

running = True
# 定义直线起点(左下)和终点(右上)
start_x, start_y = 0, height - 1
end_x, end_y = width - 1, 0

# 计算直线斜率
if end_x != start_x:
    slope = (end_y - start_y) / (end_x - start_x)
else:
    # 垂直直线(当前需求不会触发,保留以增强健壮性)
    for y in range(min(start_y, end_y), max(start_y, end_y)+1):
        draw_pixel(start_x, y, (255, 0, 0))

while running:
    screen.fill(background_colour)
    # 遍历x坐标,计算对应y值并绘制
    for x in range(start_x, end_x + 1):
        y = start_y + slope * (x - start_x)
        y_rounded = round(y)
        # 确保y在屏幕范围内
        if 0 <= y_rounded < height:
            draw_pixel(x, y_rounded, (255, 0, 0))
    pg.display.update()
    
    # 处理退出事件,避免程序卡死
    for event in pg.event.get():
        if event.type == pg.QUIT:
            running = False

pg.quit()

方法二:Bresenham直线算法(推荐)

这是一种高效的整数坐标直线绘制算法,无需浮点运算,能避免浮点误差,适合像素级渲染:

import pygame as pg

pg.init()
width, height = 800, 600
screen = pg.display.set_mode((width, height))
background_colour = (0, 0, 0)

def draw_pixel(x, y, color):
    screen.set_at((x, y), color)

# Bresenham直线算法实现,返回直线上的所有像素坐标
def bresenham_line(x0, y0, x1, y1):
    points = []
    dx = abs(x1 - x0)
    dy = abs(y1 - y0)
    sx = 1 if x0 < x1 else -1
    sy = 1 if y0 < y1 else -1
    err = dx - dy

    while True:
        points.append((x0, y0))
        if x0 == x1 and y0 == y1:
            break
        e2 = 2 * err
        if e2 > -dy:
            err -= dy
            x0 += sx
        if e2 < dx:
            err += dx
            y0 += sy
    return points

running = True
start_x, start_y = 0, height - 1
end_x, end_y = width - 1, 0
# 预计算直线上的所有像素点
line_points = bresenham_line(start_x, start_y, end_x, end_y)

while running:
    screen.fill(background_colour)
    # 绘制直线上的每个像素
    for x, y in line_points:
        draw_pixel(x, y, (255, 0, 0))
    pg.display.update()
    
    for event in pg.event.get():
        if event.type == pg.QUIT:
            running = False

pg.quit()

额外提示

如果你不是必须自己实现像素级渲染,Pygame内置的pg.draw.line()函数可以直接完成直线绘制,用法更简单:

pg.draw.line(screen, (255, 0, 0), (0, height-1), (width-1, 0))

内容的提问来源于stack exchange,提问作者Giorgos Kanavos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 07:32:51