I'm new to Kivy, I was doing pong tutorial and everything was going great, I adapted it to 4 players, each paddle has its own color and if the ball hits a paddle it gets the color of it, this way if the ball gets off the screen the last-hitter gets a score point.
I'm running in Ubuntu 14,04, with a virtualenv.
For easier download and checking, all code can be found here: Pong_kivy
What's the problem?
After a game is over once it restarts the ball seems like it's increasing speed everytime, until it crashes, which is not caused by velocity vector, I checked it, hence I think that I'm handling wrong the Clock.Schedule function. I can't seem to find whats wrong with so any help is appreciated.
pong.py file
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import NumericProperty, ReferenceListProperty,\
ObjectProperty
from kivy.vector import Vector
from kivy.clock import Clock
from kivy.graphics import *
from kivy.uix.button import Button, Label
from random import randint
class PongPaddle(Widget):
score = NumericProperty(0)
orientation = ObjectProperty([0, 0])
color = ObjectProperty([0,0,0,1])
def bounce_ball(self, ball):
if self.collide_widget(ball):
vx, vy = ball.velocity
ball.color = self.color
ball.last_hit = int(self.custom_id)
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)
last_hit = 0
color = ObjectProperty([0,0,0,1])
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)
l = Label()
btn1 = Button(text='Restart')
win_game = 1
def start(self):
Clock.schedule_interval(self.update, 1.0 / 60.0)
def stop(self):
# Stop updating
Clock.unschedule(self.update)
def init(self):
## Setup players
self.player1.orientation = [25, 200]
self.player1.color = [1,0,0,1]
self.player1.score = 0
# Player 2
self.player2.orientation = [25, 200]
self.player2.color = [0,1,0,1]
self.player2.score = 0
# Player 3
self.player3.orientation = [200, 25]
self.player3.color = [0,0,1,1]
self.player3.score = 0
# Player 4
self.player4.orientation = [200, 25]
self.player4.color = [1,1,0,1]
self.player4.score = 0
def serve_ball(self):
# Ball velocity - Add 2 to avoid 0
vel = (randint(-8,6)+2, randint(-8,6)+2)
# Setup ball
self.ball.center = self.center
self.ball.velocity = vel
self.ball.last_hit = 0
self.ball.color = [1,1,1,1]
def update(self, dt):
self.ball.move()
#Bounce out the of paddles - Why do all check? Only can bounce on one any given time
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 - This is for 2 players game
# if (self.ball.y < self.y) or (self.ball.top > self.top):
# self.ball.velocity_y *= -1
# Went of any side? - Last hitter gets a goal
if self.ball.x < self.x or self.ball.x > self.width or self.ball.y < self.y or self.ball.y > self.height:
if self.ball.last_hit == 1:
self.player1.score += 1
elif self.ball.last_hit == 2:
self.player2.score += 1
elif self.ball.last_hit == 3:
self.player3.score += 1
elif self.ball.last_hit == 4:
self.player4.score += 1
self.serve_ball()
if self.player1.score >= self.win_game:
self.player_win(1)
elif self.player2.score >= self.win_game:
self.player_win(2)
elif self.player3.score >= self.win_game:
self.player_win(3)
elif self.player4.score >= self.win_game:
self.player_win(4)
def player_win(self, player_int):
# Remove Ball and players
self.clear_widgets()
# Configure Label and Btn
self.l.text ='Player ' + str(player_int) + ' Wins!!'
self.l.top = self.top-50
self.l.font_size = 50
self.l.center_x = self.width/2
self.btn1.bind(on_press=self.restart)
self.btn1.center_x = self.width/2
self.btn1.top = self.top/2
self.add_widget(self.l)
self.add_widget(self.btn1)
self.stop()
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:
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:
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:
self.player4.center_x = touch.x
if touch.y > 2* self.height / 3 and touch.x > self.width / 6 \
and touch.x < 5 * self.width / 6:
self.player3.center_x = touch.x
# Method update layout
def update_rect(instance, value):
instance.rect.pos = instance.pos
instance.rect.size = instance.size
def restart(self, instance):
# Remove btn and labels
self.clear_widgets()
# Add what I want
self.add_widget(self.ball)
self.add_widget(self.player1)
self.add_widget(self.player2)
self.add_widget(self.player3)
self.add_widget(self.player4)
self.init()
self.serve_ball()
self.start()
class PongApp(App):
def build(self):
game = PongGame()
game.init()
game.serve_ball()
game.start()
return game
if __name__ == '__main__':
PongApp().run()
pong.kv file
#:kivy 1.0.9
<PongBall>:
size: 50, 50
canvas:
Color:
rgba: self.color[0], self.color[1], self.color[2], self.color[3]
Ellipse:
pos: self.pos
size: self.size
<PongPaddle>:
size: root.orientation[0], root.orientation[1]
canvas:
Color:
rgba: self.color[0], self.color[1], self.color[2], self.color[3]
Rectangle:
pos:self.pos
size:self.size
<PongGame>:
ball: pong_ball
player1: player_left
player2: player_right
player3: player_top
player4: player_bottom
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: 'black.jpg'
Label:
font_size: 15
center_x: root.width / 8
top: self.height*0.95
text: "P1: " + str(root.player1.score)
Label:
font_size: 15
center_x: root.width / 8
top: self.height*0.80
text: "P2: " + str(root.player2.score)
Label:
font_size: 15
center_x: root.width / 5
top: self.height*0.95
text: "P3: " + str(root.player3.score)
Label:
font_size: 15
center_x: root.width / 5
top: self.height*0.80
text: "P4: " + str(root.player4.score)
PongBall:
id: pong_ball
center: self.parent.center
PongPaddle:
id: player_left
custom_id: "1"
x: root.x
center_y: root.center_y
PongPaddle:
id: player_right
custom_id: "2"
x: root.width-self.width
center_y: root.center_y
PongPaddle:
id: player_top
custom_id: "3"
y: root.height - self.height
center_x: root.center_x
PongPaddle:
id: player_bottom
custom_id: "4"
y: root.y
center_x: root.center_x