如何在python kivy中进行物体碰撞?

问题描述 投票:0回答:1

我想为 Android 手机和平板电脑创建 Luckman 品种的吃豆人。但我无法对迷宫进行碰撞。

我尝试按照这些文件中的方式进行操作https://drive.google.com/file/d/1pwCDpU1UPzB7V7TV7-WmbyDLkpIDODry/view。但由于我的迷宫不是作为图片而是作为 .kv 文件中的绘制对象,所以没有发生任何事情。

这是我的程序代码 main.py

from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.uix.widget import Widget
from kivy.uix.anchorlayout import AnchorLayout

from player import *
from kivy.clock import Clock

from kivy.core.window import Window

class GamePlay(Screen):
    width = Window.width
    height = Window.height

    pacman = Player()

    def __init__(self, **kwargs):
        super(GamePlay,self).__init__(**kwargs)

    def on_touch_down(self, touch):
        self.start_pos = touch.pos
        return True

    def on_touch_move(self, touch):
        # Calculate swipe distance and direction
        swipe_distance_x = abs(touch.pos[0] - self.start_pos[0])
        swipe_distance_y = abs(touch.pos[1] - self.start_pos[1])
        swipe_threshold = 50  # Adjust threshold based on your needs

        # Detect swipe directions
        if swipe_distance_y > swipe_threshold:
            if touch.pos[1] > self.start_pos[1]:
                self.pacman.velocity = (0, 1)
                self.pacman.number_update_pac_img = "up"
            else:
                self.pacman.velocity = (0, -1)
                self.pacman.number_update_pac_img = "down"
        elif swipe_distance_x > swipe_threshold:
            if touch.pos[0] > self.start_pos[0]:
                self.pacman.velocity = (1, 0)
                self.pacman.number_update_pac_img = "right"
            else:
                self.pacman.velocity = (-1, 0)
                self.pacman.number_update_pac_img = "left"

        return True

    def update(self, dt):
        self.pacman.move()

class LuckmanApp(App):
    def build(self):
        game = GamePlay()
        Clock.schedule_interval(game.update, 1.0/60.0)

        return game

if __name__ == '__main__':
    LuckmanApp().run()

luckman.kv

<Player>:
    Image:
        id: "pacman"
        source: root.pac_img
        allow_stretch: True
        pos: root.pos
        size: self.parent.width / 18, self.parent.height / 18

<GamePlay>:
    canvas:
        Rectangle:
            source: "png/bg.png"
            size: self.size
    
    pacman: pacman_player

    FloatLayout:
        # Верхний вход
        canvas:
            Color:
                rgb: [0, 0, 1]
            # Верхний вход - правая стенка
            Rectangle:
                pos: self.width / 1.79, self.height
                size: self.width / -43.2, self.height / -6
            # Верхний вход - левая стенка
            Rectangle:
                pos: self.width / 2.274, self.height
                size: self.width / 43.2, self.height / -6
            # Верхний левый квадрат стенок
            Rectangle:
                pos: self.width / 2.274, self.height / 1.2
                size: self.width / -15, self.height / 96
            Rectangle:
                pos: self.width / 2.52, self.height / 1.2
                size: self.width / -43.2, self.height / 8
            Rectangle:
                pos: self.width / 2.52, self.height / 1.055
                size: self.width / -2.85, self.height / 96
            Rectangle:
                pos: self.width / 15, self.height / 1.0444
                size: self.width / -43.2, self.height / -4.7
            Rectangle:
                pos: self.width / 23.1, self.height / 1.34
                size: self.width / 7.3, self.height / -96
            Rectangle:
                pos: self.width / 2.6, self.height / 1.34
                size: self.width / -7.7, self.height / -96
            Rectangle:
                pos: self.width / 2.68, self.height / 1.359
                size: self.width / 11, self.height / 16.2
            # Верхний левый средний квадрат 
            Rectangle:
                pos: self.width / 7.29, self.height / 1.0948
                size: self.width / 22, self.height / -7.6
            Rectangle:
                pos: self.width / 3.92, self.height / 1.0948
                size: self.width / 22, self.height / -7.6

            # Верхний правый квадрат стенок
            Rectangle:
                pos: self.width / 1.8, self.height / 1.2
                size: self.width / 15, self.height / 96
            Rectangle:
                pos: self.width / 1.631, self.height / 1.2
                size: self.width / 43.2, self.height / 8
            Rectangle:
                pos: self.width / 1.631, self.height / 1.055
                size: self.width / 2.85, self.height / 96
            Rectangle:
                pos: self.width / 1.06, self.height / 1.0444
                size: self.width / 43.2, self.height / -4.7
            Rectangle:
                pos: self.width / 1.035, self.height / 1.34
                size: self.width / -7.3, self.height / -96
            Rectangle:
                pos: self.width / 1.6043, self.height / 1.34
                size: self.width / 7.7, self.height / -96
            Rectangle:
                pos: self.width / 1.57, self.height / 1.359
                size: self.width / -10, self.height / 16.2
            # Верхний правый  средний квадрат 
            Rectangle:
                pos: self.width / 1.207, self.height / 1.0948
                size: self.width / 22, self.height / -7.6
            Rectangle:
                pos: self.width / 1.324, self.height / 1.0948
                size: self.width / -22, self.height / -7.6


            # Нижний вход - правая стенка
            Rectangle:
                pos: self.width / 1.79, self.height * 0
                size: self.width / -43.2, self.height / 6
            # Нижний вход - левая стенка
            Rectangle:
                pos: self.width / 2.274, self.height * 0
                size: self.width / 43.2, self.height / 6
            # Нижний левый квадрат стенок
            Rectangle:
                pos: self.width / 2.274, self.height / 6.4
                size: self.width / -15, self.height / 96
            Rectangle:
                pos: self.width / 2.52, self.height / 6
                size: self.width / -43.2, self.height / -8
            Rectangle:
                pos: self.width / 2.52, self.height / 24
                size: self.width / -2.85, self.height / 96
            Rectangle:
                pos: self.width / 15, self.height / 24
                size: self.width / -43.2, self.height / 4.7
            Rectangle:
                pos: self.width / 23.1, self.height / 3.8
                size: self.width / 7.25, self.height / -96
            Rectangle:
                pos: self.width / 2.6, self.height / 3.8
                size: self.width / -7.7, self.height / -96
            Rectangle:
                pos: self.width / 2.68, self.height / 3.8
                size: self.width / 11, self.height / -16.2
            #Нижний Левый средний квадрат 
            Rectangle:
                pos: self.width / 7.29, self.height / 4.61
                size: self.width / 22, self.height / -7.6
            Rectangle:
                pos: self.width / 3.92, self.height / 4.61
                size: self.width / 22, self.height / -7.6

            # Нижний правый квадрат стенок
            Rectangle:
                pos: self.width / 1.8, self.height / 6.4
                size: self.width / 15, self.height / 96
            Rectangle:
                pos: self.width / 1.631, self.height / 6
                size: self.width / 43.2, self.height / -8
            Rectangle:
                pos: self.width / 1.631, self.height / 24
                size: self.width / 2.85, self.height / 96
            Rectangle:
                pos: self.width / 1.06, self.height / 24
                size: self.width / 43.2, self.height / 4.7
            Rectangle:
                pos: self.width / 1.035, self.height / 3.8
                size: self.width / -7.25, self.height / -96
            Rectangle:
                pos: self.width / 1.6043, self.height / 3.8
                size: self.width / 7.6, self.height / -96
            Rectangle:
                id: stop
                pos: self.width / 1.57, self.height / 3.8
                size: self.width / -10, self.height / -16.2
            #Нижний правый средний квадрат 
            Rectangle:
                pos: self.width / 1.207, self.height / 4.61
                size: self.width / 22, self.height / -7.6
            Rectangle:
                pos: self.width / 1.324, self.height / 4.61
                size: self.width / -22, self.height / -7.6


            #Центральные стороны

            #Центральная левая горизонтальная стенка
            Rectangle:
                pos: self.width / 6.31, self.height / 1.34
                size: self.width / 43.2, self.height / -2.05

            #Центральная правая горизонтальная стенка
            Rectangle:
                pos: self.width / 1.208, self.height / 1.34
                size: self.width / 43.2, self.height / -2.05
            
            #Центальная верхняя стенка
            Rectangle:
                pos: self.width / 3.92, self.height / 1.43
                size: self.width / 2., self.height / -96

            #Центр спавна призраков
            Rectangle:
                pos: self.width / 2.68, self.height / 1.555
                size: self.width / 11, self.height / 96
            Rectangle:
                pos: self.width / 1.57, self.height / 1.555
                size: self.width / -10, self.height / 96
            Rectangle:
                pos: self.width / 2.68, self.height / 1.65
                size: self.width / 43.2, self.height / 27
            Rectangle:
                pos: self.width / 1.57, self.height / 1.65
                size: self.width / -43.2, self.height / 27
            Rectangle:
                pos: self.width / 2.68, self.height / 1.65
                size: self.width / 3.79, self.height / -96
                
            #Центальная средняя стенка
            Rectangle:
                pos: self.width / 3.92, self.height / 1.786
                size: self.width / 2, self.height / -96
                
            #Центральная правая вертекальная стенка
            Rectangle:
                pos: self.width / 1.324, self.height / 1.68
                size: self.width / -22, self.height / 17.5
            #Центральная левая вертекальная стенка
            Rectangle:
                pos: self.width / 3.92, self.height / 1.68
                size: self.width / 22, self.height / 17.5
                
            #Центальная левая нижняя стенка
            Rectangle:
                pos: self.width / 6.31, self.height / 1.945
                size: self.width / 3.25, self.height / -96
            #Центальняя правая нижняя стенка
            Rectangle:
                pos: self.width / 1.208, self.height / 1.945
                size: self.width / -3.5, self.height / -96
            #Центральний нижний квадрат
            Rectangle:
                pos: self.width / 3.92, self.height / 3.8
                size: self.width / 2, self.height / 4.85

        Player:
            id: pacman_player
            pos: self.width / 2.13, self.height / 5.7

player.py

from kivy.uix.widget import Widget
from kivy.properties import StringProperty, NumericProperty, ReferenceListProperty
from kivy.vector import Vector

class Player(Widget):    
    pac_img = StringProperty("png/pacman/pacman_down.gif")

    number_update_pac_img = "None"

    velocity_x = NumericProperty(0)
    velocity_y = NumericProperty(0)
    velocity = ReferenceListProperty(velocity_x, velocity_y)

    def move(self):
        self.pos = Vector(*self.velocity) + self.pos

        #update pacman gifts
        if self.number_update_pac_img == "up":
            self.pac_img = "png/pacman/pacman_up.gif"
        if self.number_update_pac_img == "down":
            self.pac_img = "png/pacman/pacman_down.gif"
        if self.number_update_pac_img == "left":
            self.pac_img = "png/pacman/pacman_left.gif"
        if self.number_update_pac_img == "right":
            self.pac_img = "png/pacman/pacman_right.gif"
python kivy kivy-language pacman
1个回答
0
投票

如果对迷宫的每个部分都使用

Widget
,那么您可以使用
collide_widget()
Widget
方法来检测碰撞。首先定义矩形的类:

class MyRectangle(Widget):
    def on_size(self, *args):
        # Make sure sizes are positive
        if self.width < 0:
            self.x += self.width
            self.width = -self.width
        if self.height < 0:
            self.y += self.height
            self.height = -self.height

on_size()
只是为了确保尺寸大于 0,因为您的画布
Rectangles
有一些负尺寸。

然后,重写您的

luckman.kv
文件以使用
MyRectangle
类而不是
canvas
Rectangles
,如下所示:

<Player>:
    size_hint: None, None
    size: self.parent.width / 18, self.parent.height / 18
    Image:
        id: pacman
        source: root.pac_img
        allow_stretch: True
        pos: root.pos
        size: root.size

<GamePlay>:
    canvas:
        Rectangle:
            source: "png/bg.png"
            size: self.size
    
    pacman: pacman_player

    FloatLayout:
        id: flt
        # Верхний вход
        # canvas:
        #     Color:
        #         rgb: [0, 0, 1]
        # Верхний вход - правая стенка
        MyRectangle:
            pos: flt.width / 1.79, flt.height
            size: flt.width / -43.2, flt.height / -6
        # Верхний вход - левая стенка
        MyRectangle:
            pos: flt.width / 2.274, flt.height
            size: flt.width / 43.2, flt.height / -6
        # Верхний левый квадрат стенок
        MyRectangle:
            pos: flt.width / 2.274, flt.height / 1.2
            size: flt.width / -15, flt.height / 96
        MyRectangle:
            pos: flt.width / 2.52, flt.height / 1.2
            size: flt.width / -43.2, flt.height / 8
        MyRectangle:
            pos: flt.width / 2.52, flt.height / 1.055
            size: flt.width / -2.85, flt.height / 96
        MyRectangle:
            pos: flt.width / 15, flt.height / 1.0444
            size: flt.width / -43.2, flt.height / -4.7
        MyRectangle:
            pos: flt.width / 23.1, flt.height / 1.34
            size: flt.width / 7.3, flt.height / -96
        MyRectangle:
            pos: flt.width / 2.6, flt.height / 1.34
            size: flt.width / -7.7, flt.height / -96
        MyRectangle:
            pos: flt.width / 2.68, flt.height / 1.359
            size: flt.width / 11, flt.height / 16.2
        # Верхний левый средний квадрат 
        MyRectangle:
            pos: flt.width / 7.29, flt.height / 1.0948
            size: flt.width / 22, flt.height / -7.6
        MyRectangle:
            pos: flt.width / 3.92, flt.height / 1.0948
            size: flt.width / 22, flt.height / -7.6

        # Верхний правый квадрат стенок
        MyRectangle:
            pos: flt.width / 1.8, flt.height / 1.2
            size: flt.width / 15, flt.height / 96
        MyRectangle:
            pos: flt.width / 1.631, flt.height / 1.2
            size: flt.width / 43.2, flt.height / 8
        MyRectangle:
            pos: flt.width / 1.631, flt.height / 1.055
            size: flt.width / 2.85, flt.height / 96
        MyRectangle:
            pos: flt.width / 1.06, flt.height / 1.0444
            size: flt.width / 43.2, flt.height / -4.7
        MyRectangle:
            pos: flt.width / 1.035, flt.height / 1.34
            size: flt.width / -7.3, flt.height / -96
        MyRectangle:
            pos: flt.width / 1.6043, flt.height / 1.34
            size: flt.width / 7.7, flt.height / -96
        MyRectangle:
            pos: flt.width / 1.57, flt.height / 1.359
            size: flt.width / -10, flt.height / 16.2
        # Верхний правый  средний квадрат 
        MyRectangle:
            pos: flt.width / 1.207, flt.height / 1.0948
            size: flt.width / 22, flt.height / -7.6
        MyRectangle:
            pos: flt.width / 1.324, flt.height / 1.0948
            size: flt.width / -22, flt.height / -7.6


        # Нижний вход - правая стенка
        MyRectangle:
            pos: flt.width / 1.79, flt.height * 0
            size: flt.width / -43.2, flt.height / 6
        # Нижний вход - левая стенка
        MyRectangle:
            pos: flt.width / 2.274, flt.height * 0
            size: flt.width / 43.2, flt.height / 6
        # Нижний левый квадрат стенок
        MyRectangle:
            pos: flt.width / 2.274, flt.height / 6.4
            size: flt.width / -15, flt.height / 96
        MyRectangle:
            pos: flt.width / 2.52, flt.height / 6
            size: flt.width / -43.2, flt.height / -8
        MyRectangle:
            pos: flt.width / 2.52, flt.height / 24
            size: flt.width / -2.85, flt.height / 96
        MyRectangle:
            pos: flt.width / 15, flt.height / 24
            size: flt.width / -43.2, flt.height / 4.7
        MyRectangle:
            pos: flt.width / 23.1, flt.height / 3.8
            size: flt.width / 7.25, flt.height / -96
        MyRectangle:
            pos: flt.width / 2.6, flt.height / 3.8
            size: flt.width / -7.7, flt.height / -96
        MyRectangle:
            pos: flt.width / 2.68, flt.height / 3.8
            size: flt.width / 11, flt.height / -16.2
        #Нижний Левый средний квадрат 
        MyRectangle:
            pos: flt.width / 7.29, flt.height / 4.61
            size: flt.width / 22, flt.height / -7.6
        MyRectangle:
            pos: flt.width / 3.92, flt.height / 4.61
            size: flt.width / 22, flt.height / -7.6

        # Нижний правый квадрат стенок
        MyRectangle:
            pos: flt.width / 1.8, flt.height / 6.4
            size: flt.width / 15, flt.height / 96
        MyRectangle:
            pos: flt.width / 1.631, flt.height / 6
            size: flt.width / 43.2, flt.height / -8
        MyRectangle:
            pos: flt.width / 1.631, flt.height / 24
            size: flt.width / 2.85, flt.height / 96
        MyRectangle:
            pos: flt.width / 1.06, flt.height / 24
            size: flt.width / 43.2, flt.height / 4.7
        MyRectangle:
            pos: flt.width / 1.035, flt.height / 3.8
            size: flt.width / -7.25, flt.height / -96
        MyRectangle:
            pos: flt.width / 1.6043, flt.height / 3.8
            size: flt.width / 7.6, flt.height / -96
        MyRectangle:
            id: stop
            pos: flt.width / 1.57, flt.height / 3.8
            size: flt.width / -10, flt.height / -16.2
        #Нижний правый средний квадрат 
        MyRectangle:
            pos: flt.width / 1.207, flt.height / 4.61
            size: flt.width / 22, flt.height / -7.6
        MyRectangle:
            pos: flt.width / 1.324, flt.height / 4.61
            size: flt.width / -22, flt.height / -7.6


        #Центральные стороны

        #Центральная левая горизонтальная стенка
        MyRectangle:
            pos: flt.width / 6.31, flt.height / 1.34
            size: flt.width / 43.2, flt.height / -2.05

        #Центральная правая горизонтальная стенка
        MyRectangle:
            pos: flt.width / 1.208, flt.height / 1.34
            size: flt.width / 43.2, flt.height / -2.05
        
        #Центальная верхняя стенка
        MyRectangle:
            pos: flt.width / 3.92, flt.height / 1.43
            size: flt.width / 2., flt.height / -96

        #Центр спавна призраков
        MyRectangle:
            pos: flt.width / 2.68, flt.height / 1.555
            size: flt.width / 11, flt.height / 96
        MyRectangle:
            pos: flt.width / 1.57, flt.height / 1.555
            size: flt.width / -10, flt.height / 96
        MyRectangle:
            pos: flt.width / 2.68, flt.height / 1.65
            size: flt.width / 43.2, flt.height / 27
        MyRectangle:
            pos: flt.width / 1.57, flt.height / 1.65
            size: flt.width / -43.2, flt.height / 27
        MyRectangle:
            pos: flt.width / 2.68, flt.height / 1.65
            size: flt.width / 3.79, flt.height / -96
            
        #Центальная средняя стенка
        MyRectangle:
            pos: flt.width / 3.92, flt.height / 1.786
            size: flt.width / 2, flt.height / -96
            
        #Центральная правая вертекальная стенка
        MyRectangle:
            pos: flt.width / 1.324, flt.height / 1.68
            size: flt.width / -22, flt.height / 17.5
        #Центральная левая вертекальная стенка
        MyRectangle:
            pos: flt.width / 3.92, flt.height / 1.68
            size: flt.width / 22, flt.height / 17.5
            
        #Центальная левая нижняя стенка
        MyRectangle:
            pos: flt.width / 6.31, flt.height / 1.945
            size: flt.width / 3.25, flt.height / -96
        #Центальняя правая нижняя стенка
        MyRectangle:
            pos: flt.width / 1.208, flt.height / 1.945
            size: flt.width / -3.5, flt.height / -96
        #Центральний нижний квадрат
        MyRectangle:
            pos: flt.width / 3.92, flt.height / 3.8
            size: flt.width / 2, flt.height / 4.85

        Player:
            id: pacman_player
            pos: flt.width / 2.13, flt.height / 5.7
            
<MyRectangle>:
    size_hint: None, None
    canvas:
        Color:
            rgb: [0, 0, 1]
        Rectangle:
            pos: root.pos
            size: root.size

注意,

size
Player
是在
kv
中定义的,并且
Image
使用相同的尺寸。这对于
collide_widget()
方法很重要。

此外,

FloatLayout
现在有一个
id
以方便参考。
canvas
指令被
MyRectangle
实例替换,并且
<MyRectangle>
规则为
MyRectangle
的每个实例执行画布指令。

现在可以修改

update()
方法来检测碰撞:

def update(self, _dt):
    self.pacman.move()
    flt = self.ids.flt
    for w in flt.children:
        if w == self.pacman:
            continue
        if w.collide_widget(self.pacman):
            print('collision:', w.pos, w.size, self.pacman.pos, self.pacman.size)
            return
© www.soinside.com 2019 - 2024. All rights reserved.