如何利用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
相关产品推荐
相关产品推荐

