python - Kivy - adding and removing labels -
i'm new kivy, , can't find real answers adding , removing labels. worked way through pong tutorial (as might have guessed), , adapted 4 players. now, i'm trying add label display text winner!, , click on text restart game.
up there, it's working. problem is, can't label disappear again after new game starts. also, don't understand formatting - can't seem make label bigger or move lower in panel.
i'm going post code, since you'd play game anyway (once it's fixed), , i'm positive there's better, less janky way add , remove text.
from kivy.app import app kivy.uix.widget import widget kivy.uix.label import label kivy.properties import numericproperty, referencelistproperty,\ objectproperty kivy.vector import vector kivy.clock import clock 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) , not self.player3.can_move) \ or ((self.ball.top > self.top) , not self.player4.can_move): self.ball.velocity_y *= -1 if ((self.ball.x < self.x) , not self.player1.can_move) \ or ((self.ball.right > self.width) , not self.player2.can_move): self.ball.velocity_x *= -1 #went off side score point? if self.ball.x < self.x , 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 , 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 , 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 , 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 , touch.y > self.height / 6 \ , touch.y < 5 * self.height / 6 , self.player1.can_move: self.player1.center_y = touch.y if touch.x > self.width - self.width / 3 , touch.y > self.height / 6 \ , touch.y < 5 * self.height / 6 , self.player2.can_move: self.player2.center_y = touch.y if touch.y < self.height / 3 , touch.x > self.width / 6 \ , touch.x < 5 * self.width / 6 , self.player3.can_move: self.player3.center_x = touch.x if touch.y > 2* self.height / 3 , touch.x > self.width / 6 \ , touch.x < 5 * self.width / 6 , 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() and .kv file:
#: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
the label being removed, problem adding infinite number of them :) because update method scheduled called each 1/60 seconds here:
clock.schedule_interval(game.update, 1.0 / 60.0) you need un-schedule before adding widget if not computer going freeze:
clock.unschedule(self.update) the code below works. suggest not use global variable (it bad practice). modified too. don't need class attribute case since parameter instance contains same of self.win_label. also, change way centering (self.win_label.center = self.center). finally, easier use [button][1] instead of label because can bind other methods on_press or on_release. actually, don't need ref this. can bind on_touch_down.
from kivy.app import app kivy.uix.widget import widget kivy.uix.label import label kivy.properties import numericproperty, referencelistproperty,\ objectproperty kivy.vector import vector kivy.clock import clock 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) , not self.player3.can_move) \ or ((self.ball.top > self.top) , not self.player4.can_move): self.ball.velocity_y *= -1 if ((self.ball.x < self.x) , not self.player1.can_move) \ or ((self.ball.right > self.width) , not self.player2.can_move): self.ball.velocity_x *= -1 #went off side score point? if self.ball.x < self.x , 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 , 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 , 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 , 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) # should work: self.initialize() clock.schedule_interval(self.update, 1.0 / 60.0) def on_touch_move(self, touch): if touch.x < self.width / 3 , touch.y > self.height / 6 \ , touch.y < 5 * self.height / 6 , self.player1.can_move: self.player1.center_y = touch.y if touch.x > self.width - self.width / 3 , touch.y > self.height / 6 \ , touch.y < 5 * self.height / 6 , self.player2.can_move: self.player2.center_y = touch.y if touch.y < self.height / 3 , touch.x > self.width / 6 \ , touch.x < 5 * self.width / 6 , self.player3.can_move: self.player3.center_x = touch.x if touch.y > 2* self.height / 3 , touch.x > self.width / 6 \ , touch.x < 5 * self.width / 6 , 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()
Comments
Post a Comment