在 Python 中使用 turtle 绘制像素的最有效方法是什么?

What would the most efficient way be to draw a pixel using turtle in Python?

如果我要绘制,比方说,马里奥的像素艺术,有很多正方形(见下面的像素艺术),最有效的方法是什么?我试过了,但是代码很长,连函数都尽量删减了。

Mario Image

这是我的代码,它可以工作,但效率不高:

import turtle
from turtle import *

speed(0)


def redSquare():
    fillcolor("red")
    begin_fill()
    for i in range(4):
        forward(30)
        right(90)
    end_fill()


def blueSquare():
    fillcolor("royalblue")
    begin_fill()
    for i in range(4):
        forward(30)
        right(90)
    end_fill()


def yellowSquare():
    fillcolor("yellow")
    begin_fill()
    for i in range(4):
        forward(30)
        right(90)
    end_fill()


def skinSquare():
    fillcolor("sandybrown")
    begin_fill()
    for i in range(4):
        forward(30)
        right(90)
    end_fill()


def brownSquare():
    fillcolor("saddlebrown")
    begin_fill()
    for i in range(4):
        forward(30)
        right(90)
    end_fill()


def blackSquare():
    fillcolor("black")
    begin_fill()
    for i in range(4):
        forward(30)
        right(90)
    end_fill()


penup()
goto(100, -150)
pendown()
brownSquare()

penup()
goto(70, -150)
pendown()
brownSquare()

penup()
goto(40, -150)
pendown()
brownSquare()

penup()
goto(10, -150)
pendown()
brownSquare()

penup()
goto(10, -120)
pendown()
brownSquare()

penup()
goto(40, -120)
pendown()
brownSquare()

penup()
goto(70, -120)
pendown()
brownSquare()

penup()
goto(40, -90)
pendown()
blueSquare()

penup()
goto(10, -90)
pendown()
blueSquare()

penup()
goto(-20, -90)
pendown()
blueSquare()

penup()
goto(-20, -60)
pendown()
blueSquare()

penup()
goto(-50, -60)
pendown()
blueSquare()

penup()
goto(10, -60)
pendown()
blueSquare()

penup()
goto(40, -60)
pendown()
blueSquare()

penup()
goto(70, -60)
pendown()
skinSquare()

penup()
goto(100, -60)
pendown()
skinSquare()

penup()
goto(100, -30)
pendown()
skinSquare()

penup()
goto(70, -30)
pendown()
skinSquare()

penup()
goto(40, -30)
pendown()
skinSquare()

penup()
goto(10, -30)
pendown()
blueSquare()

penup()
goto(-20, -30)
pendown()
blueSquare()

penup()
goto(-50, -30)
pendown()
blueSquare()

penup()
goto(-50, 0)
pendown()
blueSquare()

penup()
goto(-20, 0)
pendown()
yellowSquare()

penup()
goto(10, 0)
pendown()
blueSquare()

penup()
goto(40, 0)
pendown()
redSquare()

penup()
goto(70, 0)
pendown()
skinSquare()

penup()
goto(100, 0)
pendown()
skinSquare()

penup()
goto(100, 30)
pendown()
redSquare()

penup()
goto(70, 30)
pendown()
redSquare()

penup()
goto(40, 30)
pendown()
redSquare()

penup()
goto(10, 30)
pendown()
redSquare()

penup()
goto(-20, 30)
pendown()
blueSquare()

penup()
goto(-50, 30)
pendown()
blueSquare()

penup()
goto(-50, 60)
pendown()
redSquare()

penup()
goto(-20, 60)
pendown()
blueSquare()

penup()
goto(10, 60)
pendown()
redSquare()

penup()
goto(40, 60)
pendown()
redSquare()

penup()
goto(70, 60)
pendown()
redSquare()

penup()
goto(10, 90)
pendown()
redSquare()

penup()
goto(-20, 90)
pendown()
redSquare()

penup()
goto(-50, 90)
pendown()
redSquare()

penup()
goto(-50, 120)
pendown()
skinSquare()

penup()
goto(-50, 120)
pendown()
skinSquare()

penup()
goto(-20, 120)
pendown()
skinSquare()

penup()
goto(10, 120)
pendown()
skinSquare()

penup()
goto(40, 120)
pendown()
skinSquare()

penup()
goto(70, 120)
pendown()
skinSquare()

penup()
goto(100, 150)
pendown()
blackSquare()

penup()
goto(70, 150)
pendown()
blackSquare()

penup()
goto(40, 150)
pendown()
blackSquare()

penup()
goto(10, 150)
pendown()
blackSquare()

penup()
goto(-20, 150)
pendown()
skinSquare()

penup()
goto(-50, 150)
pendown()
skinSquare()

penup()
goto(-50, 180)
pendown()
skinSquare()

penup()
goto(-20, 180)
pendown()
skinSquare()

penup()
goto(10, 180)
pendown()
skinSquare()

penup()
goto(40, 180)
pendown()
blackSquare()

penup()
goto(70, 180)
pendown()
skinSquare()

penup()
goto(100, 180)
pendown()
skinSquare()

penup()
goto(130, 180)
pendown()
skinSquare()

penup()
goto(100, 210)
pendown()
skinSquare()

penup()
goto(70, 210)
pendown()
skinSquare()

penup()
goto(40, 210)
pendown()
skinSquare()

penup()
goto(10, 210)
pendown()
blackSquare()

penup()
goto(-20, 210)
pendown()
skinSquare()

penup()
goto(-50, 210)
pendown()
skinSquare()

penup()
goto(-50, 240)
pendown()
skinSquare()

penup()
goto(-20, 240)
pendown()
skinSquare()

penup()
goto(10, 240)
pendown()
blackSquare()

penup()
goto(40, 240)
pendown()
skinSquare()

penup()
goto(100, 270)
pendown()
redSquare()

penup()
goto(70, 270)
pendown()
redSquare()

penup()
goto(40, 270)
pendown()
redSquare()

penup()
goto(10, 270)
pendown()
redSquare()

penup()
goto(-20, 270)
pendown()
redSquare()

penup()
goto(-50, 270)
pendown()
redSquare()

penup()
goto(-50, 300)
pendown()
redSquare()

penup()
goto(-20, 300)
pendown()
redSquare()

penup()
goto(10, 300)
pendown()
redSquare()

penup()
goto(-80, 300)
pendown()
redSquare()

penup()
goto(-110, 300)
pendown()
redSquare()

penup()
goto(-140, 300)
pendown()
redSquare()

penup()
goto(-80, 270)
pendown()
redSquare()

penup()
goto(-110, 270)
pendown()
redSquare()

penup()
goto(-140, 270)
pendown()
redSquare()

penup()
goto(-170, 270)
pendown()
redSquare()

penup()
goto(-170, 240)
pendown()
brownSquare()

penup()
goto(-140, 240)
pendown()
brownSquare()

penup()
goto(-110, 240)
pendown()
brownSquare()

penup()
goto(-80, 240)
pendown()
skinSquare()


penup()
goto(-80, 210)
pendown()
skinSquare()


penup()
goto(-110, 210)
pendown()
skinSquare()


penup()
goto(-140, 210)
pendown()
brownSquare()


penup()
goto(-170, 210)
pendown()
skinSquare()


penup()
goto(-200, 210)
pendown()
brownSquare()


penup()
goto(-200, 180)
pendown()
brownSquare()

penup()
goto(-170, 180)
pendown()
skinSquare()

penup()
goto(-140, 180)
pendown()
brownSquare()

penup()
goto(-110, 180)
pendown()
brownSquare()

penup()
goto(-80, 180)
pendown()
skinSquare()

penup()
goto(-80, 180)
pendown()
skinSquare()

penup()
goto(-80, 150)
pendown()
skinSquare()

penup()
goto(-110, 150)
pendown()
skinSquare()

penup()
goto(-140, 150)
pendown()
skinSquare()

penup()
goto(-170, 150)
pendown()
brownSquare()

penup()
goto(-200, 150)
pendown()
brownSquare()

penup()
goto(-140, 120)
pendown()
skinSquare()

penup()
goto(-110, 120)
pendown()
skinSquare()

penup()
goto(-80, 120)
pendown()
skinSquare()

penup()
goto(-80, 90)
pendown()
redSquare()

penup()
goto(-110, 90)
pendown()
blueSquare()

penup()
goto(-140, 90)
pendown()
redSquare()

penup()
goto(-170, 90)
pendown()
redSquare()

penup()
goto(-200, 60)
pendown()
redSquare()

penup()
goto(-170, 60)
pendown()
redSquare()

penup()
goto(-140, 60)
pendown()
redSquare()

penup()
goto(-110, 60)
pendown()
blueSquare()

penup()
goto(-80, 60)
pendown()
redSquare()

penup()
goto(-80, 30)
pendown()
blueSquare()

penup()
goto(-110, 30)
pendown()
blueSquare()

penup()
goto(-140, 30)
pendown()
redSquare()

penup()
goto(-170, 30)
pendown()
redSquare()

penup()
goto(-200, 30)
pendown()
redSquare()

penup()
goto(-230, 30)
pendown()
redSquare()

penup()
goto(-230, 0)
pendown()
skinSquare()

penup()
goto(-200, 0)
pendown()
skinSquare()

penup()
goto(-170, 0)
pendown()
redSquare()

penup()
goto(-140, 0)
pendown()
blueSquare()

penup()
goto(-110, 0)
pendown()
yellowSquare()

penup()
goto(-80, 0)
pendown()
blueSquare()

penup()
goto(-80, -30)
pendown()
blueSquare()

penup()
goto(-110, -30)
pendown()
blueSquare()

penup()
goto(-140, -30)
pendown()
blueSquare()

penup()
goto(-170, -30)
pendown()
skinSquare()

penup()
goto(-200, -30)
pendown()
skinSquare()

penup()
goto(-230, -30)
pendown()
skinSquare()

penup()
goto(-230, -60)
pendown()
skinSquare()

penup()
goto(-200, -60)
pendown()
skinSquare()

penup()
goto(-170, -60)
pendown()
blueSquare()

penup()
goto(-140, -60)
pendown()
blueSquare()

penup()
goto(-110, -60)
pendown()
blueSquare()

penup()
goto(-80, -60)
pendown()
blueSquare()

penup()
goto(-110, -90)
pendown()
blueSquare()

penup()
goto(-140, -90)
pendown()
blueSquare()

penup()
goto(-170, -90)
pendown()
blueSquare()

penup()
goto(-140, -120)
pendown()
brownSquare()

penup()
goto(-170, -120)
pendown()
brownSquare()

penup()
goto(-200, -120)
pendown()
brownSquare()

penup()
goto(-230, -150)
pendown()
brownSquare()

penup()
goto(-200, -150)
pendown()
brownSquare()

penup()
goto(-170, -150)
pendown()
brownSquare()

penup()
goto(-140, -150)
pendown()
brownSquare()

exitonclick()

您可以像这样定义一个名为 square 的函数:

def square():
       for x in range(4):
             t.forward(20)
             t.right(90)

绘制一个 20x20 的正方形。

现在您可以使用它来绘制任何颜色,如下例所示,这将形成一条 4 像素的水平线,例如俄罗斯方块:

def Tetris_Piece_1():
  for x in range(4):
      t.begin_fill()
      square()
      t.color("Blue")
      t.end_fill()
      t.color("Black")
      t.forward(20) 

而且我认为它不能再优化了,另请查看本教程:(https://replit.com/talk/learn/How-to-draw-Pixel-Art-on-Python-with-Turtle/7556)

最快的方法可能是定义一个函数,在当前海龟位置绘制适当大小的像素形状,然后在一对嵌套的 for 循环中重复调用。

这是一个例子:

import turtle

COLORS = {0: 'white',
          1: 'red',
          2: 'blue',
          3: 'green',
          4: 'black',
          5: 'yellow',
          6: 'orange'}

PIXELS = [[0, 0, 0, 0, 0, 0, 0, 0],
          [0, 0, 1, 1, 1, 1, 0, 0],
          [0, 0, 0, 4, 0, 4, 0, 0],
          [0, 0, 0, 2, 3, 0, 0, 0],
          [0, 0, 0, 3, 2, 0, 0, 0],
          [0, 5, 4, 4, 4, 4, 4, 0],
          [0, 0, 6, 6, 6, 6, 0, 0],
          [0, 0, 0, 0, 0, 0, 0, 0]]

WIDTH, HEIGHT = len(PIXELS[0]), len(PIXELS)

scn = turtle.Screen()
pen = turtle.Turtle()

def pixel():
    for i in range(4):
        pen.forward(30)
        pen.left(90)
    pen.forward(30)


if __name__ == "__main__" :
    scn.setup(600, 600)
    pen.speed(0)
    pen.hideturtle()
    for i in range(WIDTH):
        pen.up()
        pen.setpos(0, 30*i)  # Row position.
        pen.down()
        row = PIXELS[i]
        for j in range(HEIGHT):
            col = COLORS[row[j]]
            pen.fillcolor(col)
            pen.begin_fill()
            pixel()
            pen.end_fill()

    print('done - press any key to exit')
    turtle.onkeypress(exit)
    turtle.listen()
    turtle.done()

结果:

what would the most efficient way be to do this?

我同意@martineau 的一般方法 (+1),但由于您想要最有效的方法,我会更改一些内容。我会使用 stamping 而不是 drawing 来减少代码量并加快速度。我还会使用字母串来表示颜色像素,而不是整数数组。而且我会将图像倒置而不是倒置。我发现这使得作为盲打员输入图像更容易,并且即使以编码形式也更容易可视化图像。我会 tracer() 解决这个问题:

from turtle import Screen, Turtle

PIXEL_SIZE = 30
CURSOR_SIZE = 20

COLORS = {
    'B': 'blue',
    'K': 'black',
    'O': 'orange',
    'R': 'red',
    'T': 'brown',
    'W': 'white',
    'Y': 'yellow',
}

PIXELS = [
    "WWWRRRRRRWWWW",
    "WWRRRRRRRRRRW",
    "WWTTTOOOKOWWW",
    "WTOTOOOOKOOOW",
    "WTOTTOOOOKOOO",
    "WTTOOOOOKKKKW",
    "WWWOOOOOOOOWW",
    "WWRRBRRRRWWWW",
    "WRRRBRRBRRRWW",
    "RRRRBBBBRRRRW",
    "OORBYBBYBROOW",
    "OOOBBBBBBOOOW",
    "OOBBBBBBBBOOW",
    "WWBBBWWBBBWWW",
    "WTTTWWWWTTTWW",
    "TTTTWWWWTTTTW",
]

WIDTH, HEIGHT = len(PIXELS[0]), len(PIXELS)

screen = Screen()
screen.setup((WIDTH + 3) * PIXEL_SIZE, (HEIGHT + 3) * PIXEL_SIZE)
screen.tracer(False)

turtle = Turtle()
turtle.hideturtle()
turtle.shape('square')
turtle.shapesize(PIXEL_SIZE / CURSOR_SIZE)
turtle.penup()

x0 = -WIDTH/2 * PIXEL_SIZE
y0 = HEIGHT/2 * PIXEL_SIZE

for i, row in enumerate(PIXELS):
    turtle.setposition(x0, y0 - i * PIXEL_SIZE)

    for pixel in row:
        turtle.color(COLORS[pixel])
        turtle.stamp()
        turtle.forward(PIXEL_SIZE)

screen.tracer(True)
screen.exitonclick()

这种方法甚至适用于文字像素: