【问题标题】:Extra pixels left and top of canvas python turtle画布蟒蛇龟左侧和顶部的额外像素
【发布时间】:2022-01-22 21:23:45
【问题描述】:

我不知道为什么,但是在画布的左侧和顶部,我在使用海龟创建我的蛇游戏时出现了奇怪的行为。左侧和顶部有一个 10 像素的边框。

主代码

import functools
from turtle import Screen
import time
from Snake import Snake


# initialize screen
win = Screen()
WIDTH = HEIGHT = 800
win.setup(width=WIDTH, height=HEIGHT)
win.bgcolor("black")
canvas = win.getcanvas()
root = canvas.winfo_toplevel()
root.overrideredirect(1)
win.tracer(0)

s = Snake()


def main():
    segments = s.init_segments()
    win.update()
    move_keys = ["Right", "Up", "Left", "Down"]
    running = True
    inc = 0

    for k in move_keys:
        win.onkeypress(functools.partial(s.move, segments, inc, k), key=k)
        inc += 90

    win.listen()

    while running:
        win.update()
        time.sleep(0.1)
        s.move(segments, segments[0].heading(), "none")

        if s.crashed(win.window_width(), win.window_height(), segments):
            running = False
            break

    win.exitonclick()


main()

蛇码

from turtle import Turtle
class Snake:

    def init_segments(self):
        segs = []
        x_pos = 0
        for i in range(3):
            t = Turtle(shape="square")
            t.color("white")
            t.penup()
            t.speed(1)
            segs.append(t)
            if t != segs[0]:
                x_pos -= 20
                t.goto(x_pos, 0)
        return segs

    def __no_turn(self, h, d):
        if h - d == -180 or h - d == 180:
            return True
        else:
            return False

    def __no_skip(self, k, dir):
        if (k == "Right" and dir == 0 or k == "Up" and dir == 90
                or k == "Left" and dir == 180 or k == "Down" and dir == 270):
            return False
        else:
            return True

    def move(self, t_list , dir, k):
        for seg_num in range(len(t_list) - 1, -1, -1):
            if self.__no_turn(t_list[0].heading(), dir):
                continue
            elif seg_num > 0:
                if self.__no_skip(k, dir):
                    t_list[seg_num].goto(t_list[seg_num - 1].position())
            else:
                t_list[seg_num].setheading(dir)
                if self.__no_skip(k, dir):
                    t_list[seg_num].forward(20)


    def crashed(self, window_width, window_height, t_list):
        head_position = t_list[0].position()
        body_positions = []
        hw = window_width/2
        hh = window_height/2
        for i in range(len(t_list)):
            body_positions.append(t_list[i].position())

        body_positions.pop(0)
        for i in range(len(body_positions)):
            if head_position == body_positions[i]:
                return True

        if head_position[0] >= hw:
            print(f"Head Position: {head_position[0]} ... Wall Position: {hw}")
            return True

        elif head_position[0] <= -hw:
            print(f"Head Position: {head_position[0]} ... Wall Position: {-hw}")
            return True

        elif head_position[1] >= hh:
            print(f"Head Position: {head_position[1]} ... Wall Position: {hh}")
            return True

        elif head_position[1] <= -hh:
            print(f"Head Position: {head_position[1]} ... Wall Position: {-hh}")
            return True

添加了此文件中的打印行以尝试找出发生了什么。

请帮助我了解发生了什么。

谢谢。

编辑: 另外我之前没有注意到,但是底部和右侧有一个1px的边框。

第二次编辑以进一步说明问题。

我不久前添加了药丸的代码。我所做的是,我一次生成所有药丸并隐藏它们,因为你无法在不清除屏幕的情况下摧毁乌龟,而且每次都获取乌龟的位置并在屏幕上重新绘制乌龟的位置会很奇怪之前是 0.1 秒。然后我得到了这个结果。

如您所见,药丸正在屏幕外生成。

以下是我用来生成所有药丸的代码,类似于我用来确定屏幕边缘的代码。

hw = int(WIDTH/2)
hh = int(HEIGHT/2)
p_list = []
for i in range(-hw, hw, 20):
    for j in range(-hh, hh, 20):
        p = Pill((i, j))
        p.show_pill(segments)
        p_list.append(p)

当我重新订购 win.update() 时会发生什么

正如您在此处看到的,右侧现在将整个片段压入其中。如果您仔细观察,您会在这张图片中看到蛇的白色覆盖了未覆盖的空间的额外像素上一张图片,它停在圆圈的最后一个像素上。 您还会在第二张图片和这张图片中看到,底部有一排圆圈从窗口边框的边缘向外窥视。

【问题讨论】:

    标签: python-3.x turtle-graphics


    【解决方案1】:

    如果您在s.move(segments, segments[0].heading(), "none") 之后而不是之前移动win.update(),它将在所有四面墙中以相同的方式发生(即)崩溃。

    如果您不希望在碰撞时头部被撞到墙上,请相应地修改碰撞边界检查。

    【讨论】:

    • 不,正在发生其他事情。我可以发布另一个屏幕截图,其中包含更多代码来说明。
    • 当然。 1 px 白色部分来自 TKinter/Turtle 接口实现。休息一下,对我来说只要改变这个顺序就可以了,除了你所指的这个 1px 部分。想知道为什么这种重新排序没有帮助。
    • 因为我重新订购了。我会在我的编辑中展示给你看。
    • 我知道了。随着重新排序,更改边界检查而不是右墙的硬件检查 (hw-20) 等等。
    • 明白我的目标是只有在我到达边缘后才会崩溃。如果你玩蛇,你会在边缘看到药丸仍然产生,这意味着你有一些时间来转动你的蛇(我可以为此编写代码(可能))。其次,为什么乌龟图形窗口的边缘不在-hw,hw,-hh,hh?这是我试图理解的部分。为什么它有那个边框,因为即使我使用你的方法,我的蛇从左侧和顶部坠毁 10 像素,从右侧和底部坠毁 1-2 像素。和我的一模一样,只是它不允许你打开边缘。
    【解决方案2】:

    我终于明白为什么会这样了。

    第一个问题:我之前被引导相信所有海龟形状都是平等的。不,他们不是。虽然海龟的默认大小可能是 20 像素乘 20 像素,但正方形和圆形都默认为 21 像素,因为它们需要一个不是偶数的中心点,以便它可以在海龟坐标系的 4 个象限之间平分(它有一个像素作为 x 和 y 轴)。

    如何解决:

    • 将画布设为 21 像素的倍数。
    • 请记住,当画布分成两部分时,每个边缘都有一半的海龟,这算作一个完整的海龟,但海龟只在画布上完成,所以我们坐在一列和一行额外的海龟上.
    • 删除最后一列和最后一行海龟,并将整个网格移动一个海龟。

    如果操作正确,您将得到以下结果。不幸的是,右边和底部的 2px 将被切断,因为它用于 Turtle 的 UI。顶部和左侧面临类似的问题,即单行像素用于 Turtle 的 UI

    蛇本身以类似的方式完成,不是将起始段移动 20 像素,而是先将其移动 11 像素,然后附加蛇的其他部分。我通过删除我最初移动它的 11px 来计算它的位置。除了 Turtle 的 ui 带走的东西之外,这实际上解决了蛇的大部分问题。

    【讨论】:

      猜你喜欢
      • 2019-08-14
      • 1970-01-01
      • 2021-04-20
      • 1970-01-01
      • 1970-01-01
      • 2018-08-24
      • 2018-03-03
      • 1970-01-01
      • 2012-01-04
      相关资源
      最近更新 更多