/
ball.py
135 lines (109 loc) · 5.51 KB
/
ball.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import pygame as pg
import time
from load import load_sound
class Ball(pg.sprite.Sprite):
"""Ball class"""
def __init__(self, *, start_pos, x_start_speed = 5, y_start_speed = 5):
"""
Ball constructor.
:param start_pos: starting position of the ball
:param x_start_speed: starting x speed
:param y_start_speed: starting y speed
"""
pg.sprite.Sprite.__init__(self, self.containers) #call Sprite initializer
screen = pg.display.get_surface()
self.area = screen.get_rect()
#region import sound
self.bounce_sound = load_sound('bounce.wav')
self.loser_sound = load_sound('loser.wav')
#endregion
self.image = pg.Surface([ self.area.width * 1/100 , self.area.width * 1/100]).convert()
self.image.fill((200, 200, 200))
self.start_pos = start_pos#change
self.rect = self.image.get_rect()
self.set_pos( self.start_pos )
self.speed_multiplier = 1
self.start_velocity = [ x_start_speed, y_start_speed ]
self.set_velocity( self.start_velocity )
self.collided = False
def set_pos(self, pos):
self.rect.center = pos
def set_velocity(self, vel):
self.velocity = [ vel[0] * self.speed_multiplier, vel[1] * self.speed_multiplier ]
def update(self):
"""move ball in indicated direction"""
self.rect.move_ip( self.velocity )
#bounce if ball hit bottom or top
if self.rect.top < self.area.top:
self.rect.top = self.area.top - self.rect.top
self.bounce_y()
self.bounce_sound.play()
elif self.rect.bottom > self.area.bottom:
self.rect.bottom = self.area.bottom - ( self.rect.bottom - self.area.bottom )
self.bounce_y()
self.bounce_sound.play()
def paddle_collide(self, paddles):
if not self.collided:
for paddle in pg.sprite.spritecollide( self, paddles, 0):#for all collided paddles
if self.velocity[0] > 0:
shift_x = self.rect.right - paddle.rect.left
else:
shift_x = self.rect.left - paddle.rect.right
if self.velocity[1] > 0:
shift_y = self.rect.bottom - paddle.rect.top
else:
shift_y = self.rect.top - paddle.rect.bottom
#calculations to determine the new speed
vel_sum = (abs(self.velocity[0]) + abs(self.velocity[1])) / self.speed_multiplier
abs_diff_between_center_y = abs( self.rect.centery - paddle.rect.centery )
collision_area = ( paddle.rect.height/2 + self.rect.height )
#bounce from the long edge
if shift_x * self.velocity[0] <= shift_y * self.velocity[1]:
shift_y = round( self.velocity[1]/self.velocity[0] * shift_x )
#bounce from the short edge
else:
shift_x = round( ( 1 if self.velocity[1] >= 0 else -1 ) * shift_y )
self.bounce_y()
self.bounce_sound.play()
#self.rect.move_ip( -shift_x, -shift_y )
self.bounce_x()
ball_speed_x = int ( round ( ( 1 if self.velocity[0] >= 0 else -1 ) * ( 1 - abs_diff_between_center_y/collision_area ) * vel_sum ) )
ball_speed_y = int ( round ( ( 1 if self.velocity[1] >= 0 else -1 ) * abs_diff_between_center_y/collision_area * vel_sum ) )
if abs( ball_speed_y ) < 2:
ball_speed_y = 2 * ( 1 if self.velocity[1] >= 0 else -1 )
ball_speed_x = ( vel_sum - 2 ) * ( 1 if self.velocity[0] >= 0 else -1 )
if abs( ball_speed_x ) < 2:
ball_speed_x = 1 * ( 1 if self.velocity[0] >= 0 else -1 )
ball_speed_y = ( vel_sum - 1 ) * ( 1 if self.velocity[1] >= 0 else -1 )
self.set_velocity( [ ball_speed_x, ball_speed_y ] )
self.collided = True
else:#if 'self.collided == True'
if len( pg.sprite.spritecollide( self, paddles, 0) ) == 0:
self.collided = False
for paddle in paddles:
if (paddle.rect.left < self.rect.right < paddle.rect.right) or (paddle.rect.left < self.rect.left < paddle.rect.right):
self.collided = True #Ball is not collided but still in paddle waist
if self.rect.right > self.area.right:
for paddle in paddles:
if paddle != paddles.sprites()[1]:
paddle.score.add_point()
self.reset()
elif self.rect.left < self.area.left- 10:
for paddle in paddles:
if paddle != paddles.sprites()[0]:
paddle.score.add_point()
self.reset()
def bounce_x(self):
"""Inverts the velocity vector in the X axis"""
self.velocity[0] *= -1
def bounce_y(self):
"""Inverts the velocity vector in the Y axis"""
self.velocity[1] *= -1
def reset(self):
"""Sets the ball to the start position and reverses the velocity vector in the X axis"""
self.loser_sound.play()
self.set_pos( self.start_pos )
self.bounce_x()
ball_speed_x = ( 1 if self.velocity[1] >= 0 else -1 ) * self.start_velocity[0]
ball_speed_y = ( 1 if self.velocity[1] >= 0 else -1 ) * self.start_velocity[1]
self.set_velocity( [ ball_speed_x, ball_speed_y ] )