如何阻止形状变成另一个形状?

时间:2019-12-31 05:36:50

标签: python python-3.x tkinter collision-detection tkinter-canvas

例如,当您以马里奥的身份走动时,会遇到障碍。我需要做到这一点,以便您无法越过障碍。我查找了答案,让它检测到它粉碎成某种东西,只是无法阻止它。 c.find_overlapping()函数为我完成了所有这些工作。

这是我的代码:

    from tkinter import *
except ImportError:
    from Tkinter import *
shiva = Tk()
shiva.title("Super Mario Python Limited")
shiva.geometry("1000x2000")
c = Canvas(shiva, height = 2000, width = 1000, bg = "#a7f2e6", highlightthickness = 0)
c.pack()
topyellow = c.create_rectangle(20, 30, 200, 300, fill = "yellow")
mushroom = c.create_rectangle(500, 600, 600, 700, fill = "orange")
mario = c.create_rectangle(20, 600, 60, 650, fill = "red")


prevkey = ""
def move(event):
    global prevkey
    key = event.keysym
    if key == "Up":
        c.move(mario, 0, -10)
        prevkey == "Up"
    elif key == "Down":
        c.move(mario, 0, 10)
        prevkey = "Down"
    elif key == "Left":
        c.move(mario, -10, 0)
        prevkey = "Left"
    elif key == "Right":
        c.move(mario, 10, 0)
        prevkey = "Right"
c.bind_all("<Key>", move)
prevkey = ""
def make_collide(moveshape, othershape):
    global prevkey
    if c.find_overlapping(c.coords(othershape)[0], c.coords(othershape)[1], c.coords(othershape)[2], c.coords(othershape)[3]) == (int(othershape), int(moveshape)):
        def move(event):
            global prevkey
            key = event.keysym
            if key == str(prevkey):
                c.move(mario, 0, 0)
            else:
                if key == "Up":
                    c.move(moveshape, 0, -10)
                elif key == "Down":
                    c.move(moveshape, 0, 10)
                elif key == "Left":
                    c.move(moveshape, -10, 0)
                elif key == "Right":
                    c.move(moveshape, 10, 0)
        c.bind_all("<Key>", move)
    else:
        def move(event):
            global prevkey
            key = event.keysym
            if key == "Up":
                c.move(moveshape, 0, -10)
                prevkey = "Up"
            elif key == "Down":
                c.move(moveshape, 0, 10)
                prevkey = "Down"
            elif key == "Left":
                c.move(moveshape, -10, 0)
                prevkey = "Left"
            elif key == "Right":
                c.move(moveshape, 10, 0)
                prevkey = "Right"
        c.bind_all("<Key>", move)
def detect_touch1():
    make_collide(mario, topyellow)
    make_collide(mario, mushroom)
    shiva.after(20, detect_touch1)
detect_touch1()

我该如何做,以便当马里奥(Mario)撞到一块岩石时,他不仅会穿过岩石?

提前谢谢!!!!

1 个答案:

答案 0 :(得分:0)

在这里您可以看到执行此操作的方法,这有点混乱,但是我相信您可以理解它的工作原理。请查看所有canvas方法,以了解您可以轻松进行的(canvas)

from tkinter import *

shiva = Tk()
shiva.title("Super Mario Python Limited")
shiva.geometry("1000x2000")
c = Canvas(shiva, height = 2000, width = 1000, bg = "#a7f2e6", highlightthickness = 0)
c.pack()
topyellow = c.create_rectangle(20, 30, 200, 300, fill = "yellow")
mushroom = c.create_rectangle(500, 600, 600, 700, fill = "orange")
mario = c.create_rectangle(20, 600, 60, 650, fill = "red")


# initialize the bounding box of the player
surplus = 10
x, y, x1, y1 = c.coords(mario)
x_s, y_s, x1_s, y1_s = x - surplus, y - surplus, x1 +surplus, y1 +surplus

top_area = x, y_s, x1, y
right_area = x1, y, x1_s, y1
bottom_area = x, y1, x1, y1_s
left_area = x - surplus, y, x, y1

t = c.create_rectangle(*top_area, outline='red', fill="")
r = c.create_rectangle(*right_area, outline='red', fill="")
b = c.create_rectangle(*bottom_area, outline='red', fill="")
l = c.create_rectangle(*left_area, outline='red', fill="")

# add the rectangles that have the 'collision detector' functionality to a list for remove them if they are the dected as object with which the player collided
position_rectangles = [t, r, b, l]


prevkey = ""
def move(event):
    global prevkey
    key = event.keysym
    surplus = 10

    # get the new bounding boxs positions
    top_overl = list(c.find_overlapping(*c.coords(t)))
    right_overl = list(c.find_overlapping(*c.coords(r)))
    bottom_overl = list(c.find_overlapping(*c.coords(b)))
    left_overl = list(c.find_overlapping(*c.coords(l)))

    # remove from the detected object the player and the boxes
    for elem in position_rectangles + [mario]:
        if elem in top_overl:
            top_overl.remove(elem)
        if elem in right_overl:
            right_overl.remove(elem)
        if elem in bottom_overl:
            bottom_overl.remove(elem)
        if elem in left_overl:
            left_overl.remove(elem)

    # check if the player can move
    if key == "Up" and len(top_overl) == 0:
        for box in position_rectangles: # move the bounding boxs
            c.move(box, 0, -surplus)
        c.move(mario, 0, -surplus)
        prevkey == "Up"
    elif key == "Down"  and len(bottom_overl) == 0:
        for box in position_rectangles: # move the bounding boxs
            c.move(box, 0, surplus)
        c.move(mario, 0, surplus)
        prevkey = "Down"
    elif key == "Left"  and len(left_overl) == 0:
        for box in position_rectangles: # move the bounding boxs
            c.move(box, -surplus, 0)
        c.move(mario, -surplus, 0)
        prevkey = "Left"
    elif key == "Right"  and len(right_overl) == 0:
        for box in position_rectangles: # move the bounding boxs
            c.move(box, surplus, 0)
        c.move(mario, surplus, 0)
        prevkey = "Right"


c.bind_all("<Key>", move)
prevkey = ""

def make_collide(moveshape, othershape):
    global prevkey
    if c.find_overlapping(c.coords(othershape)[0], c.coords(othershape)[1], c.coords(othershape)[2], c.coords(othershape)[3]) == (int(othershape), int(moveshape)):
        c.bind_all("<Key>", move)
    else:
        c.bind_all("<Key>", move)
def detect_touch1():
    make_collide(mario, topyellow)
    make_collide(mario, mushroom)
    shiva.after(20, detect_touch1)
detect_touch1()
shiva.mainloop()

但是当要碰撞的物品很多时,也许此方法可能需要一些时间才能起作用,只需尝试一下并查看其行为即可