3

私はKivyが初めてで、ラベルの追加と削除に関する本当の答えが見つかりません。私は Pong のチュートリアル (ご想像のとおり) を自分なりに進めて、4 人用に調整しました。Winner!今、テキストを表示するラベルを追加し、そのテキストをクリックしてゲームを再起動しようとしています。

そこまでは、動作しています。問題は、新しいゲームが開始された後、ラベルが再び消えないことです。また、書式設定がわかりません。ラベルを大きくしたり、パネル内で下に移動したりすることができないようです。

とにかく(修正されたら)ゲームをプレイしたいと思うので、すべてのコードを投稿します.

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.properties import NumericProperty, ReferenceListProperty,\
    ObjectProperty
from kivy.vector import Vector
from kivy.clock import Clock
from random import randint


class PongPaddle(Widget):
    score = NumericProperty(0)
    orientation = ObjectProperty([0, 0])
    can_move = ObjectProperty(0)

    def bounce_ball(self, ball):
        if self.collide_widget(ball):
            vx, vy = ball.velocity
            if self.orientation[0] == 25:                
                offset = (ball.center_y - self.center_y) / (self.height / 2)
                bounced = Vector(-1 * vx, vy)
                vel = bounced * 1.1
                ball.velocity = vel.x, vel.y + offset
            else:
                offset = (ball.center_x - self.center_x) / (self.width / 2)
                bounced = Vector(vx, -1 * vy)
                vel = bounced * 1.1
                ball.velocity = vel.x + offset, vel.y


class PongBall(Widget):
    velocity_x = NumericProperty(0)
    velocity_y = NumericProperty(0)
    velocity = ReferenceListProperty(velocity_x, velocity_y)

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

class PongGame(Widget):
    ball = ObjectProperty(None)
    player1 = ObjectProperty(None)
    player2 = ObjectProperty(None)
    player3 = ObjectProperty(None)
    player4 = ObjectProperty(None)

    def initialize(self):
        SCORE = 1
        self.player1.orientation = [25, 200]
        self.player2.orientation = [25, 200]
        self.player3.orientation = [200, 25]
        self.player4.orientation = [200, 25]
        self.player1.score = SCORE
        self.player2.score = SCORE
        self.player3.score = SCORE
        self.player4.score = SCORE
        self.player1.can_move = 1
        self.player2.can_move = 1
        self.player3.can_move = 1
        self.player4.can_move = 1
        self.serve_ball()

    def serve_ball(self, vel=(4, 0)):
        self.ball.center = self.center
        self.ball.velocity = vel

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

        #bounce of paddles
        self.player1.bounce_ball(self.ball)
        self.player2.bounce_ball(self.ball)
        self.player3.bounce_ball(self.ball)
        self.player4.bounce_ball(self.ball)

        #bounce ball off bottom or top
        if ((self.ball.y < self.y) and not self.player3.can_move) \
           or ((self.ball.top > self.top) and not self.player4.can_move):
            self.ball.velocity_y *= -1
        if ((self.ball.x < self.x) and not self.player1.can_move) \
           or ((self.ball.right > self.width) and not self.player2.can_move):
            self.ball.velocity_x *= -1

        #went off to a side to score point?
        if self.ball.x < self.x and self.player1.can_move == 1:
            self.player1.score -= 1
            self.serve_ball(vel=(4, randint(1, 4)))
            if self.player1.score <= 0:
                self.player1.can_move = 0
        elif self.ball.x > self.width and self.player2.can_move == 1:
            self.player2.score -= 1
            self.serve_ball(vel=(-4, randint(1, 4)))
            if self.player2.score <= 0:
                self.player2.can_move = 0
        elif self.ball.y > self.height and self.player4.can_move == 1:
            self.player4.score -= 1
            self.serve_ball(vel = (randint(1, 4), -4))
            if self.player4.score <= 0:
                self.player4.can_move = 0
        elif self.ball.y < self.y and self.player3.can_move == 1:
            self.player3.score -= 1
            self.serve_ball(vel = (randint(1, 4), 4))
            if self.player3.score <= 0:
                self.player3.can_move = 0

        if self.player1.can_move + self.player2.can_move + \
           self.player3.can_move + self.player4.can_move == 1:
            self.ball.velocity = (0, 0)
            global win_label
            win_label = Label(size_hint=(None, None),
                              text='[ref=winner]Winner![/ref]',
                              markup=True, text_size=(70, None))
            #win_label.texture_update()
            win_label.pos = (self.width / 2, self.height / 2 - 70)
##            win_label.size =  win_label.texture_size[0] + 20, \
##                             win_label.texture_size[1] + 20
            win_label.bind(on_ref_press=self.click_win_label)
            win_label.texture_update()
            self.add_widget(win_label)

    def click_win_label(self, instance, value):
        self.initialize()
        self.remove_widget(win_label)


    def on_touch_move(self, touch):
        if touch.x < self.width / 3 and touch.y > self.height / 6 \
            and touch.y < 5 * self.height / 6 and self.player1.can_move:
            self.player1.center_y = touch.y
        if touch.x > self.width - self.width / 3 and touch.y > self.height / 6 \
            and touch.y < 5 * self.height / 6 and self.player2.can_move:
            self.player2.center_y = touch.y
        if touch.y < self.height / 3 and touch.x > self.width / 6 \
            and touch.x < 5 * self.width / 6 and self.player3.can_move:
            self.player3.center_x = touch.x
        if touch.y > 2* self.height / 3 and touch.x > self.width / 6 \
            and touch.x < 5 * self.width / 6 and self.player4.can_move:
            self.player4.center_x = touch.x


class PongApp(App):
    def build(self):
        game = PongGame()
        game.initialize()
        game.serve_ball()
        Clock.schedule_interval(game.update, 1.0 / 60.0)
        return game


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

そして .kv ファイル:

#:kivy 1.0.9

<PongBall>:
    size: 50, 50 
    canvas:
        Ellipse:
            pos: self.pos
            size: self.size          

<PongPaddle>:
    size: root.orientation[0], root.orientation[1]
    canvas:
        Rectangle:
            pos:self.pos
            size:self.size

<PongGame>:
    ball: pong_ball
    player1: player_left
    player2: player_right
    player3: player_top
    player4: player_bottom


    Label:
        font_size: 50  
        center_x: root.width / 6
        top: root.top - root.height / 2 + 50
        text: str(root.player1.score)

    Label:
        font_size: 50  
        center_x: root.width * 5 / 6
        top: root.top - root.height / 2 + 50
        text: str(root.player2.score)

    Label:
        font_size: 50
        center_x: root.width / 2
        top: root.height / 6
        text: str(root.player3.score)

    Label:
        font_size: 50
        center_x: root.width / 2
        top: 5 * root.height / 6
        text: str(root.player4.score)

    PongBall:
        id: pong_ball
        center: self.parent.center

    PongPaddle:
        id: player_left
        x: root.x
        center_y: root.center_y

    PongPaddle:
        id: player_right
        x: root.width-self.width
        center_y: root.center_y

    PongPaddle:
        id: player_top
        y: root.y
        center_x: root.center_x

    PongPaddle:
        id: player_bottom
        y: root.height - self.height
        center_x: root.center_x
4

1 に答える 1

1

Label削除されています。問題は、それらを無限に追加していることです:)更新メソッドはここで1/60秒ごとに呼び出されるようにスケジュールされているためです:

Clock.schedule_interval(game.update, 1.0 / 60.0)

コンピューターがフリーズしない場合は、ウィジェットを追加する前にスケジュールを解除する必要があります。

Clock.unschedule(self.update)

以下のコードは機能します。グローバル変数を使用しないことをお勧めします (これは非常に悪い習慣です)。私もそれを修正しました。この場合、パラメーターinstanceにはまったく同じself.win_label. また、センタリングの方法を変更します ( self.win_label.center = self.center)。最後に、またはのような他のメソッドをバインドできるため、 a の[Button][1]代わりに aを使用する方が簡単です。実際には、これには必要ありません。単純にバインドできます。Labelon_presson_releaserefon_touch_down

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.properties import NumericProperty, ReferenceListProperty,\
    ObjectProperty
from kivy.vector import Vector
from kivy.clock import Clock
from random import randint


class PongPaddle(Widget):
    score = NumericProperty(0)
    orientation = ObjectProperty([0, 0])
    can_move = ObjectProperty(0)

    def bounce_ball(self, ball):
        if self.collide_widget(ball):
            vx, vy = ball.velocity
            if self.orientation[0] == 25:                
                offset = (ball.center_y - self.center_y) / (self.height / 2)
                bounced = Vector(-1 * vx, vy)
                vel = bounced * 1.1
                ball.velocity = vel.x, vel.y + offset
            else:
                offset = (ball.center_x - self.center_x) / (self.width / 2)
                bounced = Vector(vx, -1 * vy)
                vel = bounced * 1.1
                ball.velocity = vel.x + offset, vel.y


class PongBall(Widget):
    velocity_x = NumericProperty(0)
    velocity_y = NumericProperty(0)
    velocity = ReferenceListProperty(velocity_x, velocity_y)

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

class PongGame(Widget):
    ball = ObjectProperty(None)
    player1 = ObjectProperty(None)
    player2 = ObjectProperty(None)
    player3 = ObjectProperty(None)
    player4 = ObjectProperty(None)

    def initialize(self):
        SCORE = 1
        self.player1.orientation = [25, 200]
        self.player2.orientation = [25, 200]
        self.player3.orientation = [200, 25]
        self.player4.orientation = [200, 25]
        self.player1.score = SCORE
        self.player2.score = SCORE
        self.player3.score = SCORE
        self.player4.score = SCORE
        self.player1.can_move = 1
        self.player2.can_move = 1
        self.player3.can_move = 1
        self.player4.can_move = 1
        self.serve_ball()

    def serve_ball(self, vel=(4, 0)):
        self.ball.center = self.center
        self.ball.velocity = vel

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

        #bounce of paddles
        self.player1.bounce_ball(self.ball)
        self.player2.bounce_ball(self.ball)
        self.player3.bounce_ball(self.ball)
        self.player4.bounce_ball(self.ball)

        #bounce ball off bottom or top
        if ((self.ball.y < self.y) and not self.player3.can_move) \
           or ((self.ball.top > self.top) and not self.player4.can_move):
            self.ball.velocity_y *= -1
        if ((self.ball.x < self.x) and not self.player1.can_move) \
           or ((self.ball.right > self.width) and not self.player2.can_move):
            self.ball.velocity_x *= -1

        #went off to a side to score point?
        if self.ball.x < self.x and self.player1.can_move == 1:
            self.player1.score -= 1
            self.serve_ball(vel=(4, randint(1, 4)))
            if self.player1.score <= 0:
                self.player1.can_move = 0
        elif self.ball.x > self.width and self.player2.can_move == 1:
            self.player2.score -= 1
            self.serve_ball(vel=(-4, randint(1, 4)))
            if self.player2.score <= 0:
                self.player2.can_move = 0
        elif self.ball.y > self.height and self.player4.can_move == 1:
            self.player4.score -= 1
            self.serve_ball(vel = (randint(1, 4), -4))
            if self.player4.score <= 0:
                self.player4.can_move = 0
        elif self.ball.y < self.y and self.player3.can_move == 1:
            self.player3.score -= 1
            self.serve_ball(vel = (randint(1, 4), 4))
            if self.player3.score <= 0:
                self.player3.can_move = 0

        if self.player1.can_move + self.player2.can_move + \
           self.player3.can_move + self.player4.can_move == 1:
            self.ball.velocity = (0, 0)
            Clock.unschedule(self.update)

            self.win_label = Label(size_hint=(None, None),
                              text='[ref=winner]Winner![/ref]',
                              markup=True, font_size=70, color=[1,0,0,1])
            #win_label.texture_update()
            #self.win_label.pos = (self.width / 2, self.height / 2 - 70)
            self.win_label.center = self.center
##            win_label.size =  win_label.texture_size[0] + 20, \
##                             win_label.texture_size[1] + 20
            self.win_label.bind(on_ref_press=self.click_win_label)
            self.win_label.texture_update()
            self.add_widget(self.win_label)


    def click_win_label(self, instance, value):
        self.remove_widget(self.win_label)
        #self.remove_widget(instance) # this should also work:
        self.initialize()
        Clock.schedule_interval(self.update, 1.0 / 60.0)



    def on_touch_move(self, touch):
        if touch.x < self.width / 3 and touch.y > self.height / 6 \
            and touch.y < 5 * self.height / 6 and self.player1.can_move:
            self.player1.center_y = touch.y
        if touch.x > self.width - self.width / 3 and touch.y > self.height / 6 \
            and touch.y < 5 * self.height / 6 and self.player2.can_move:
            self.player2.center_y = touch.y
        if touch.y < self.height / 3 and touch.x > self.width / 6 \
            and touch.x < 5 * self.width / 6 and self.player3.can_move:
            self.player3.center_x = touch.x
        if touch.y > 2* self.height / 3 and touch.x > self.width / 6 \
            and touch.x < 5 * self.width / 6 and self.player4.can_move:
            self.player4.center_x = touch.x


class PongApp(App):
    def build(self):
        game = PongGame()
        game.initialize()
        #game.serve_ball()
        Clock.schedule_interval(game.update, 1.0 / 60.0)
        return game

if __name__ == '__main__':
    PongApp().run()
于 2013-08-01T05:29:09.430 に答える