[6c45ee]: ball.py Maximize Restore History

Download this file

ball.py    158 lines (131 with data), 7.8 kB

  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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# -*- coding: utf-8 -*-
'''
Created on 14 July 2012
@author: Marco Baxemyr
'''
import math
from pygame import sprite
from pygame import Rect
from vector import Vector
from helper_functions import *
class Ball(sprite.Sprite):
thud_sound = None
def __init__(self, image_surface, position, direction, attached=False):
sprite.Sprite.__init__(self)
if Ball.thud_sound is None:
Ball.thud_sound = load_sound("explosion_dull.wav")
Ball.thud_sound.set_volume(0.5)
self.image = image_surface
self.radius = (self.image.get_width() / 2) - 1
self.speed = 720.
self.rect = Rect(0, 0, self.image.get_width(), self.image.get_height())
self.move(Vector(position[0], position[1]))
self.direction = direction.get_normalized()
self.has_passed_paddle=False
self.damage = 1
self.score = 0
self.combo = 0
self.combo_length = 0
self.attached_to_paddle = attached
def update(self, time_passed, paddle, normal_blocks, invulnerable_blocks):
"""
Moves the ball forward and handles collisions with walls and the passed objects.
time_passed: the time passed in seconds since last call
paddle: the paddle sprite
blocks: the group of the block sprites
"""
if self.attached_to_paddle:
self.keep_on_paddle(paddle)
return
displacement = Vector(self.direction.get_x() * self.speed * time_passed,
self.direction.get_y() * self.speed * time_passed)
new_pos = self.pos+displacement
old_pos = self.pos
bounds_collision_new_pos = self.keep_within_bounds(new_pos, old_pos, time_passed)
if bounds_collision_new_pos:
self.move(bounds_collision_new_pos)
return
paddle_collision_new_pos = self.check_and_handle_paddle_collision(paddle, new_pos, old_pos, time_passed)
if paddle_collision_new_pos:
self.move(paddle_collision_new_pos)
return
block_collision_new_pos = self.check_and_handle_block_collision(new_pos, old_pos, time_passed, normal_blocks, invulnerable_blocks)
if block_collision_new_pos:
self.move(block_collision_new_pos)
return
self.move(new_pos)
def combo_done(self):
self.score += self.combo
self.combo = 0
self.combo_length = 0
def move(self, position):
self.pos = position
self.rect.center = (position.get_x(), position.get_y())
def keep_on_paddle(self, paddle):
topleft = paddle.rect.topleft
pos = Vector(topleft[0] + (paddle.rect.width / 3), topleft[1] - self.radius)
self.move(pos)
def keep_within_bounds(self, new_pos, old_pos, time_passed):
if new_pos.get_x() - self.radius < 230:
self.direction = Vector(abs(self.direction.get_x()), self.direction.get_y())
displacement = Vector(self.direction.get_x() * self.speed * time_passed,
self.direction.get_y() * self.speed * time_passed)
new_pos = old_pos+displacement
elif new_pos.get_x() + self.radius > 722:
self.direction = Vector(-abs(self.direction.get_x()), self.direction.get_y())
displacement = Vector(self.direction.get_x() * self.speed * time_passed,
self.direction.get_y() * self.speed * time_passed)
new_pos = old_pos+displacement
elif new_pos.get_y() - self.radius < 0:
self.direction = Vector(self.direction.get_x(), abs(self.direction.get_y()))
displacement = Vector(self.direction.get_x() * self.speed * time_passed,
self.direction.get_y() * self.speed * time_passed)
new_pos = old_pos+displacement
elif new_pos.get_y() - self.radius > 720:
self.combo_done()
self.kill()
def check_and_handle_paddle_collision(self, paddle, new_pos, old_pos, time_passed):
if new_pos.get_y() + self.radius >= 651 and (new_pos.get_x() + self.radius > paddle.rect.left and new_pos.get_x() - self.radius < paddle.rect.right) and not self.has_passed_paddle:
offset_from_middle = (new_pos.get_x() - paddle.rect.centerx) / (paddle.rect.width / 2)
#self.direction = Vector(self.direction.get_x()+offset_from_middle, -abs(self.direction.get_y())).get_normalized()
self.direction = (Vector(offset_from_middle, -abs(self.direction.get_y())).get_normalized() * 0.66 + self.direction * 0.33).get_normalized()
displacement = Vector(self.direction.get_x() * self.speed * time_passed,
self.direction.get_y() * self.speed * time_passed)
new_pos = old_pos+displacement
self.combo_done()
elif new_pos.get_y() >= paddle.rect.bottom - (paddle.rect.height / 2.5):
self.has_passed_paddle = True
def check_and_handle_block_collision(self, new_pos, old_pos, time_passed, normal_blocks, invulnerable_blocks):
self.move(new_pos) #move the sprite forward to be able to check collision with other sprites
blocks = normal_blocks.copy()
blocks.add(invulnerable_blocks.sprites())
collided_blocks = sprite.spritecollide(self, blocks, False, sprite.collide_rect)
if collided_blocks:
top_or_bottom_hit, left_or_right_hit = False, False
for block in collided_blocks:
if (old_pos.get_y() < block.rect.centery) and (old_pos.get_x() < (block.rect.right + self.radius)) and (old_pos.get_x() > (block.rect.left - self.radius)):
top_or_bottom_hit = True
if (old_pos.get_y() > block.rect.centery) and (old_pos.get_x() < (block.rect.right + self.radius)) and (old_pos.get_x() > (block.rect.left - self.radius)):
top_or_bottom_hit = True
if (old_pos.get_x() < block.rect.centerx) and (old_pos.get_y() < (block.rect.bottom + self.radius)) and (old_pos.get_y() > (block.rect.top - self.radius)):
left_or_right_hit = True
if (old_pos.get_x() > block.rect.centerx) and (old_pos.get_y() < (block.rect.bottom + self.radius)) and (old_pos.get_y() > (block.rect.top - self.radius)):
left_or_right_hit = True
if not (top_or_bottom_hit or left_or_right_hit):
print "No collision with circle detected"
else:
self.combo_length += 1
score = block.damage(self.damage)
self.combo += int(score * (self.combo_length * 0.3)) / int(1 + self.combo_length * 0.1)
Ball.thud_sound.play()
break
if top_or_bottom_hit:
self.direction = Vector(self.direction.get_x(), -self.direction.get_y())
if left_or_right_hit:
self.direction = Vector(-self.direction.get_x(), self.direction.get_y())
displacement = Vector(self.direction.get_x() * self.speed * time_passed,
self.direction.get_y() * self.speed * time_passed)
return old_pos+displacement
blocks.empty() #remove all blocks from the temporary group, otherwise the sprites will soon find themselves in thousands of groups
def release_from_paddle(self):
self.attached_to_paddle = False