Reputation: 359
I'm starting with kivy playing around in the tutorials I'm at the end of the Pong tutorial and want to add the 'Winner' label based on the score.
In order to do so, I styled a winner label:
<Winner>:
Label:
font_size: 200
#center_x: self.parent.width * .5
#center_y: self.parent.top - .5
text: "wINNER!"
I would like to place this label in the middle, based on the dimensions of the Pong game but it ends up somewhere in the lower left.
I also tried adding the widget directly in python (see update method), but then i still don't know how to do the placement dynamically, like how the other labels with the scores are placed in the PongGame in the kivy file.
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
class PongPaddle(Widget):
score = NumericProperty(0)
def bounce_ball(self, ball):
if self.collide_widget(ball):
vx, vy = ball.velocity
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
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 Winner(Widget):
pass
class PongGame(Widget):
ball = ObjectProperty(None)
player1 = ObjectProperty(None)
player2 = ObjectProperty(None)
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)
# bounce ball off bottom or top
if (self.ball.y < self.y) or (self.ball.top > self.top):
self.ball.velocity_y *= -1
# went of to a side to score point?
if self.ball.x < self.x:
self.player2.score += 1
self.serve_ball(vel=(4, 0))
if self.ball.x > self.width:
self.player1.score += 1
self.serve_ball(vel=(-4, 0))
if self.player1.score>0:
Clock.unschedule(self.update)
self.add_widget(Winner())
# self.add_widget(text='bla',center_y=self.parent.top-50)
self.add_widget(Label(text='bla',center_y=self.parent.top-50))
if self.player2.score>0:
Clock.unschedule(self.update)
self.add_widget(Winner())
self.add_widget(Label(text='bla',center_y=self.parent.top-50))
def on_touch_move(self, touch):
if touch.x < self.width / 3:
self.player1.center_y = touch.y
if touch.x > self.width - self.width / 3:
self.player2.center_y = touch.y
class PongApp(App):
def build(self):
game = PongGame()
game.serve_ball()
Clock.schedule_interval(game.update, 1.0 / 60.0)
return game
if __name__ == '__main__':
PongApp().run()
kivy
#:kivy 1.0.9
<PongBall>:
size: 50, 50
canvas:
Ellipse:
pos: self.pos
size: self.size
<Winner>:
Label:
font_size: 200
center_x: self.parent.width * .5
center_y: self.parent.top - .5
text: "wINNER!"
<PongPaddle>:
size: 20, 200
canvas:
Rectangle:
pos: self.pos
size: self.size
<PongGame>:
ball: pong_ball
player1: player_left
player2: player_right
canvas:
Rectangle:
pos: self.center_x - 5, 0
size: 10, self.height
Label:
font_size: 70
center_x: root.width / 4
top: root.top - 50
text: str(root.player1.score)
Label:
font_size: 70
center_x: root.width * 3 / 4
top: root.top - 50
text: str(root.player2.score)
Label:
font_size: 70
center_x: root.width * .5
top: root.top - 50
text: "Winner!"
PongBall:
id: pong_ball
center: self.parent.center
PongPaddle:
id: player_left
x: root.x
y: root.center_y
PongPaddle:
id: player_right
x: root.width-self.width
center_y: root.center_y
How to refer to the properties of the parent widget? Thanks!
Upvotes: 1
Views: 538
Reputation: 16011
The following enhancements are required in the kv file and Python script to solve the problem.
app.root
to refer to the root widget.There are three keywords specific to the Kv language:
- app: always refers to the instance of your application.
- root: refers to the base widget/template in the current rule
- self: always refer to the current widget
Kivy Language » Value Expressions, on_property Expressions, ids, and Reserved Keywords
self
The keyword self references the “current widget instance”:
Button: text: 'My state is %s' % self.state
root
This keyword is available only in rule definitions and represents the root widget of the rule (the first instance of the rule):
<MyWidget>: custom: 'Hello world' Button: text: root.custom
app
This keyword always refers to your app instance. It’s equivalent to a call to kivy.app.App.get_running_app() in Python.
Label: text: app.name
<Winner>:
font_size: 200
center: app.root.center
text: "WINNER!"
Winner()
from Widget
to Label
because we don't really need two widgets and it will reduce resource usage e.g. memory, size of app, etc.Winner
object.class Winner(Label):
pass
class PongGame(Widget):
...
def update(self, dt):
self.ball.move()
...
if self.player1.score > 0:
self.add_widget(Winner())
if self.player2.score > 0:
self.add_widget(Winner())
def on_touch_move(self, touch):
...
Upvotes: 1