January 28, 2014♦
☀
E
F
F
L
U
E
N
C
E
☀
from ball_cup.pgfw.GameChild import GameChild
class Levels(GameChild, list):
def __init__(self, parent):
GameChild.__init__(self, parent)
self.load()
def load(self):
for line in file(self.get_resource("levels", "path")):
fields = line.split()
args = map(int, fields[:-1]) + [float(fields[-1])]
self.append(Level(*args))
class Level:
def __init__(self, *args):
self.ball_width, self.cup_width, self.cup_speed = args
def __repr__(self):
return "{0} {1} {2}".format(self.ball_width, self.cup_width,
self.cup_speed)
from random import randint, choice
from math import sqrt, ceil
from pygame import Surface
from pygame.draw import circle
from ball_cup.pgfw.Sprite import Sprite
class Cup(Sprite):
up, down = -1, 1
def __init__(self, parent):
Sprite.__init__(self, parent)
self.display_surface = self.get_display_surface()
self.load_configuration()
self.reset()
def load_configuration(self):
config = self.get_configuration("cup")
self.color = config["color"]
self.margin_vertical = config["margin-vertical"]
self.margin_right = config["margin-right"]
def reset(self):
level = self.parent.get_current_level()
self.halted = False
self.reset_frame(level.cup_width)
self.speed = level.cup_speed
self.set_padding()
self.set_bounds()
self.place_in_bounds()
self.indent()
self.reset_direction()
def reset_frame(self, width):
self.clear_frames()
frame = Surface((width, width))
frame.fill(self.color)
self.add_frame(frame)
def set_padding(self):
self.padding = int(ceil(self.get_radius() - self.get_half()))
def get_radius(self):
return sqrt(2 * self.get_half() ** 2)
def get_half(self):
return self.rect.w / 2.0
def set_bounds(self):
display_height = self.display_surface.get_height()
margin = self.margin_vertical
self.bounds = margin, display_height - margin
def place_in_bounds(self):
upper, lower = self.bounds
half = self.rect.h / 2
adjusted = upper + half, lower - half
self.rect.centery = randint(*adjusted)
def indent(self):
self.rect.right = self.display_surface.get_rect().right - \
self.margin_right
def reset_direction(self):
self.direction = choice([self.up, self.down])
def clear(self):
self.parent.clear(self.rect)
def halt(self):
self.halted = True
def update(self):
if not self.halted:
self.shift()
Sprite.update(self)
def shift(self):
self.move(dy=self.speed * self.direction)
overflow = self.collide_with_bounds()
if overflow is not None:
self.change_direction()
self.move(dy=overflow * 2 * self.direction)
def collide_with_bounds(self):
rect = self.rect
upper, lower = self.bounds
if rect.top <= upper:
return upper - rect.top
elif rect.bottom >= lower:
return rect.bottom - lower
def change_direction(self):
direction = self.direction
if direction == self.up:
direction = self.down
else:
direction = self.up
self.direction = direction
from pygame import Surface, Rect
from ball_cup.pgfw.Sprite import Sprite
from ball_cup.field.ball.Charge import Charge
class Ball(Sprite):
forward, backward = 1, -1
def __init__(self, parent):
Sprite.__init__(self, parent)
self.display_surface = self.get_display_surface()
self.charge = Charge(self)
self.load_configuration()
self.set_minimum_size()
self.reset()
def load_configuration(self):
config = self.get_configuration("ball")
self.color = config["color"]
self.margin = config["margin"]
self.base_deceleration = config["base-deceleration"]
self.base_velocity_range = config["base-velocity-range"]
def set_minimum_size(self):
levels = self.parent.levels
minimum = levels[0].ball_width
for level in levels[1:]:
if level.ball_width < minimum:
minimum = level.ball_width
self.minimum_size = minimum
def reset(self):
self.traveling = False
self.sent = False
self.direction = self.forward
level = self.parent.get_current_level()
self.reset_frame(level.ball_width)
self.place()
self.set_motion_parameters()
self.charge.reset()
def set_motion_parameters(self):
base = self.base_velocity_range
ratio = self.rect.w / float(self.minimum_size)
self.velocity_range = ratio * base[0], ratio * base[1]
self.deceleration = ratio * self.base_deceleration
def reset_frame(self, width):
self.clear_frames()
frame = Surface((width, width))
frame.fill(self.color)
self.add_frame(frame)
def place(self):
rect = self.rect
relative = self.display_surface.get_rect()
rect.centery = relative.centery
rect.left = relative.left + self.margin
def send(self):
self.set_velocity()
self.traveling = True
def set_velocity(self):
strength = self.charge.strength
lower, upper = self.velocity_range
self.velocity = strength * (upper - lower) + lower
def clear(self):
self.parent.clear(self.rect)
def update(self):
if not self.traveling and not self.sent:
self.charge.update()
elif self.traveling:
self.shift()
self.get_current_frame().fill(self.color)
self.collide_with_cup()
Sprite.update(self)
def shift(self):
self.move(self.velocity * self.direction)
if self.rect.right >= self.display_surface.get_rect().right:
self.direction = self.backward
self.move(self.display_surface.get_rect().right - self.rect.right)
if self.rect.right < 0:
self.velocity = 0
self.decelerate()
if self.velocity <= 1:
self.traveling = False
self.parent.cup.halt()
self.sent = True
self.parent.evaluate()
def decelerate(self):
self.velocity = max(0, self.velocity - self.deceleration)
def collide_with_cup(self):
rect = self.rect
relative = self.parent.cup.rect
if rect.colliderect(relative):
clip = rect.clip(relative)
section = Rect((clip.x - rect.x, clip.y - rect.y), clip.size)
self.get_current_frame().fill((255, 255, 255), section)