kivy überprüfen, ob ein kreis in einem anderen ist

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
MupfSpace
User
Beiträge: 169
Registriert: Montag 25. Dezember 2017, 20:26

Hallo,

ich möchte einen Joystick mit Python und Kivy programmieren, und bin gerade dabei, zu überprüfen, ob sich der innere Kreis, noch komplett im äußeren befindet, jedes mal wenn er verschoben wird und diesen, wenn er außerhalb ist, wieder zurück zusetzen.

Ich bin jetzt schon so weit, dass das ungefähr stimmt, allerdings ist es nicht ganz genau...

Das ist der Code den ich bisher habe:
(Die Formel für die Kreisberechnung habe ich übrigens beim Googlen gefunden. Es gab mehrere aber das war die einzige die überhaupt ansatzweise funktioniert hat)

Code: Alles auswählen

from kivy.uix.widget import Widget
from kivy.graphics import Color, Ellipse, Line
from kivy.lang import Builder
import math


kv = """
<Joystick>:
    size_hint: None, None
    Widget:
        id: background
        size_hint: None, None
        height: root.height * 3
        width: root.width * 3
        pos: (root.x / (4 / 3), root.y / (4 / 3))

    Widget:
        id: pad
        size_hint: None, None
        size: root.size
        x: root.x + root.width / 2
        y: root.y + root.height / 2

"""

Builder.load_string(kv)


def inside(circle1, circle2):
    r1 = circle1.size[0] / 2
    x1 = circle1.pos[0] + r1 / 2
    y1 = circle1.pos[1] + r1 / 2
    r2 = circle2.size[0] / 2
    x2 = circle2.pos[0] + r2 / 2
    y2 = circle2.pos[1] + r2 / 2
    dx = x1 - x2
    dy = y1 - y2
    distance = math.sqrt(dx * dx + dy * dy)

    return r2 > (distance + r1)


class Joystick(Widget):
    def __init__(self, **kwargs):
        super(Joystick, self).__init__(**kwargs)

        with self.ids.background.canvas:
            Color(0.5, 0.5, 0.5, 0.3)
            self.background = Ellipse(pos = (100, 100), size = (self.width * 2, self.height * 2))
            Color(1, 1, 1, 1)
            Line(circle = (self.x + self.width, self.y + self.height, self.width))
        
        with self.ids.pad.canvas:
            Color(1, 1, 1, 1)
            self.pad = Ellipse(pos = (self.x + self.width / 2, self.y + self.height / 2), size = self.size)

        self.pad_pos = self.pad.pos

    def on_touch_down(self, touch):
        self.last_x = touch.x
        self.last_y = touch.y

    def on_touch_move(self, touch):
        move_x =  touch.x - self.last_x
        move_y =  touch.y - self.last_y
        self.pad_pos = (self.pad_pos[0] + move_x, self.pad_pos[1] + move_y)
        print(inside(self.pad, self.background))
        self.last_x = touch.x
        self.last_y = touch.y

    @property
    def pad_pos(self):
        return self._pad_pos

    @pad_pos.setter
    def pad_pos(self, value):
        self._pad_pos = value
        self.pos = self._pad_pos
        self.pad.pos = self._pad_pos


def main():
    from kivy.app import App
    from kivy.uix.floatlayout import FloatLayout

    
    class GameToolsApp(App):
        def __init__(self, **kwargs):
            super(GameToolsApp, self).__init__(**kwargs)

        def build(self):
            layout = FloatLayout()
            self.joystick = Joystick(size = (50, 50), pos = (100, 100))

            layout.add_widget(self.joystick)

            return layout


    app = GameToolsApp()
    app.run()


if __name__ == "__main__":
    main()

Hier sind ein paar Beispiele für Fälle, in denen es gut funktioniert:

Bild

Bild

und Hier sind ein paar Beispiele für Fälle, in denen es noch nicht Funktioniert:

Bild in diesem Fall, gibt es mir True aus, obwohl der innere Kreis schon zum teil außerhalb des äußeren ist.

Bild hier sagt er False, obwohl der Kreis innerhalb des andern liegt.


Warum funktioniert das nicht?
Was muss ich machen, damit es funktioniert?

LG
Adrian
Benutzeravatar
Dennis89
User
Beiträge: 1555
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

ich verstehe nicht wieso du deine 'x1', 'y1' etc. durch zwei teilst?
Schau mal ob es so in allen Positionen stimmt:

Code: Alles auswählen

def inside(circle1, circle2):
    r1 = circle1.size[0] / 2
    x1 = circle1.pos[0] + r1
    y1 = circle1.pos[1] + r1
    r2 = circle2.size[0] / 2
    x2 = circle2.pos[0] + r2
    y2 = circle2.pos[1] + r2
    dx = x1 - x2
    dy = y1 - y2
    distance = math.sqrt((dx**2) + (dy**2))

    return r2 > (distance + r1)
Deine Bilder konnte man leider nicht sehen. Die musst du wo anders hochladen und uns den Link zeigen.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
MupfSpace
User
Beiträge: 169
Registriert: Montag 25. Dezember 2017, 20:26

Ja, das war das Problem 😅. Danke 😃
Keine Ahnung warum ich das mit dem / 2 gemacht habe. War ein komischer Denkfehler, aber jetzt funktioniert es ja...

PS:
Wegen den Bildern: ich habe die auf 10 verschiedenen Seiten hochgeladen bis es endlich einen link gab, der funktioniert hat. Der funktioniert bei mir aber auch nur wenn ich es am Computer anschaue und nicht am Handy.
Welche Seite ist den gut geeignet?
Benutzeravatar
__blackjack__
User
Beiträge: 14054
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@MupfSpace: Ich verwende in der Regel imgur.com.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten