Python龟色变化

时间:2016-10-20 17:27:38

标签: python turtle-graphics

我正在玩蟒蛇龟模块,我试图制作一个不透明的方形网格,比如30x30可以根据某些属性改变颜色(无关紧要什么属性)我的问题是,无论如何要改变一旦它已经在画布上绘制出来的形状的颜色?

我尝试将所有方形形状添加到数组中,包括图章和多边形,但是一旦绘制它们,似乎无法改变它们的颜色。

我知道印章不起作用,因为它就像乌龟所在的足迹一样,但是有没有任何方法可以用多边形或其他一些我不知道的方法来实现这一点?

我没有添加任何代码片段,因为它是一个非常基本的问题,可以用于很多事情。

2 个答案:

答案 0 :(得分:2)

Yes, you can do it. The key to this, and many complicated turtle problems, is using stamps. They are individually, or collectively, removable. And since they take on the shape of the turtle itself, they can be images or arbitrary polygons of any size or color you wish:

from turtle import Turtle, Screen
from random import randrange, choice
from collections import namedtuple
from math import ceil

GRID = 15  # GRID by GRID of squares
SIZE = 30  # each square is SIZE by SIZE

INCREASE = 1.5  # how much to lighten the square's color
WHITE = [255, 255, 255]  # color at which we stop changing square
DELAY = 100  # time between calls to change() in milliseconds
DARK = 32 # range (ceil(INCREASE) .. DARK - 1) of dark colors

def change():
    block = choice(blocks)
    blocks.remove(block)

    color = [min(int(primary * INCREASE), WHITE[i]) for i, primary in enumerate(block.color)]  # lighten color

    turtle.color(color)
    turtle.setposition(block.position)
    turtle.clearstamp(block.stamp)

    stamp = turtle.stamp()

    if color != WHITE:
        blocks.append(Block(block.position, color, stamp))  # not white yet so keep changing this block

    if blocks:  # stop all changes if/when all blocks turn white
        screen.ontimer(change, DELAY)

HALF_SIZE = SIZE // 2

screen = Screen()
screen.colormode(WHITE[0])
screen.register_shape("block", ((HALF_SIZE, -HALF_SIZE), (HALF_SIZE, HALF_SIZE), (-HALF_SIZE, HALF_SIZE), (-HALF_SIZE, -HALF_SIZE)))
screen.tracer(GRID ** 2)  # ala @PyNuts

turtle = Turtle(shape="block", visible=False)
turtle.speed("fastest")
turtle.up()

Block = namedtuple('Block', ['position', 'color', 'stamp'])

blocks = list()

HALF_GRID = GRID // 2

for x in range(-HALF_GRID, HALF_GRID):
    for y in range(-HALF_GRID, HALF_GRID):
        turtle.goto(x * SIZE, y * SIZE)
        color = [randrange(ceil(INCREASE), DARK) for primary in WHITE]
        turtle.color(color)
        blocks.append(Block(turtle.position(), color, turtle.stamp()))

screen.ontimer(change, DELAY)

screen.exitonclick()

答案 1 :(得分:0)

Turtle的想法是,一旦绘制,图像变成像素,提交到画布 - 即使Turtle命令本身是“矢量”命令,当人们谈论“矢量”与“光栅”图形时。 / p>

这意味着Turtle绘图上下文无法知道“已经”绘制的内容 - 您无法引用已绘制的形状或多边形并更改其属性。 (更新:但是对于邮票--Turtle对象会记录有关这些邮件的信息 - 感谢@cdlane)

在这种情况下,您需要做的是在您的代码数据上添加关于您想要进一步修改的任何形状的数据 - 并在需要时重新绘制它们它。换句话说:您为矢量图形模型开发代码 - 允许您这样做。

但是,你应该注意,在{T}运行的tkinter Canvas widget之上(至少,我相信),它本身就是一个Vector模型 - 所以它可能更适合你的想法。但是,它的文档和工作方式可能很难掌握。

因此,回到“拥有自己的矢量图形实现”,你可以利用Python Object Orientation和数据模型来构建“history-turtle” - 它可以记录日志并重放相同位置的命令块上下文(但允许不同的颜色,宽度等,......设置)。

这是一个比说的更少的琐事,但是,这是一个样本:

from turtle import Turtle

"""
Python Turtle with logging and replay capabilities

Author: João S. O. Bueno <gwidion@gmail.com>
License: LGPL 3.0+

This implements HistoryTurtle - a subclass of
Python's turtle.Turtle wich features a simple
command history and   new `replay` and `log`
methods -
`turtle.replay(<start>, <end>)` will reissue
the commands logged in those positions of the history,
but with the current Pen settings.

The optional kwarg `position_independent` can be passed
as `True` to `replay` so that the turtle's position
and heading are not restored to the ones recorded
along with the command.

https://gist.github.com/jsbueno/cb413e985747392c460f39cc138436bc

"""


class Command:
    __slots__ = ( "method_name", "args", "kwargs", "pos", "heading")

    def __init__(self, method_name, args=(),
                 kwargs=None, pos=None, heading=None):
        self.method_name = method_name
        self.args = args
        self.kwargs = kwargs or {}
        self.pos = pos
        self.heading = heading

    def __repr__(self):
        return "<{0}> - {1}".format(self.pos, self.method_name)


class Instrumented:
    def __init__(self, turtle, method):
        self.turtle = turtle
        self.method = method

    def __call__(self, *args, **kwargs):
        command = Command(self.method.__name__, args, kwargs,
                          self.pos(), self.heading())
        result = self.method(*args, **kwargs)
        if (self.method.__name__ not in self.turtle.methods_to_skip or
                not kwargs.pop('skip_self', True)):
            self.turtle.history.append(command)
        return result

    def pos(self):
        return self.turtle._execute(Command('pos'), True)

    def heading(self):
        return self.turtle._execute(Command('heading'), True)


class HistoryTurtle(Turtle):

    methods_to_skip = ('replay', '_execute', 'log')

    def __init__(self, *args, **kw):
        self._inited = False
        super().__init__(*args, **kw)
        self.history = []
        self._replaying = [False]
        self._inited = True

    def __getattribute__(self, attr):
        result = super().__getattribute__(attr)
        if (not callable(result) or
                attr.startswith('_') or
                not self._inited or
                self._replaying[-1]):
            return result
        return Instrumented(self, result)

    def replay(self, start, end=None, *,
               position_independent=False,
               skip_self=True,
               restore=True
               ):
        results = []

        self._replaying.append(True)
        if restore:
            pos, heading, state = self.pos(), self.heading(), self.pen()['pendown']
        for command in self.history[start:end]:
            results.append(
                self._execute(command, position_independent))
        if restore:
            self.setpos(pos)
            self.setheading(heading)
            (self.pendown() if state else self.penup())
        self._replaying.pop()
        return results

    def log(self, start=0, end=None):
        for i, command in enumerate(self.history[start:end], start):
            print(i, command)

    def _execute(self, command, position_independent):
        """ Execute a method without triggering the log
        """
        # Warning: not thread-safe:
        self._replaying.append(True)
        method = getattr(self, command.method_name)
        if not position_independent:
            state = self.pen()['pendown']
            self.setpos(command.pos)
            self.setheading(command.heading)
            (self.pendown() if state else self.penup())
        result = method(*command.args, **command.kwargs)
        self._replaying.pop()
        return result