"""
Allegro Python port game example
Original Author: Jeroen De Busser
"""
from allegro import *
from random import randint, random
import os
examples_data = os.path.abspath(os.path.join(os.path.dirname(__file__),
"..", "examples/data"))
class Pallet:
def __init__(self, x, y, w, h, speed, color):
self.__initials = (x, y, w, h, speed, color, 0)
self.reset()
def reset(self):
'''Resets this pallet to its starting values '''
self.x, self.y, self.w, self.h, self.speed, self.color, self.moving =\
self.__initials
def update(self):
self.y += self.moving * self.speed
if self.y < 0:
self.y = 0
elif self.y > al_get_display_height(al_get_current_display()) - self.h:
self.y = al_get_display_height(al_get_current_display()) - self.h
def draw(self):
al_draw_filled_rounded_rectangle(self.x, self.y, self.x + self.w,
self.y + self.h, 6, 6, self.color)
al_draw_filled_rounded_rectangle(self.x + 2, self.y + 2,
self.x + self.w / 2, self.y + self.h - 5, 4, 4,
al_map_rgba_f(0.2, 0.2, 0.2, 0.2))
class Player(Pallet):
def __init__(self, x, y, h, w, speed, keyup, keydown, color):
self.__initials = (x, y, h, w, speed, keyup, keydown, color)
Pallet.__init__(self, x, y, h, w, speed, color)
self.keyup, self.keydown = keyup, keydown
def handle_event(self, ev):
if ev.type == ALLEGRO_EVENT_KEY_DOWN:
if ev.keyboard.keycode == self.keyup:
self.moving = -1
elif ev.keyboard.keycode == self.keydown:
self.moving = 1
elif ev.type == ALLEGRO_EVENT_KEY_UP:
if (ev.keyboard.keycode == self.keyup and self.moving == -1) or\
(ev.keyboard.keycode == self.keydown and self.moving == 1):
self.moving = 0
class AI(Pallet):
def __init__(self, x, y, w, h, speed, color, difficulty, ball):
Pallet.__init__(self, x, y, w, h, speed, color)
self.difficulty = difficulty
self.ball = ball
def handle_event(self, ev):
if ev.type == ALLEGRO_EVENT_TIMER:
if self.difficulty == 1:
target_y = self.ball.y + self.ball.size / 2
else:
dh = al_get_display_height(al_get_current_display())
if self.ball.xdir == -1 or abs(self.x - self.ball.x) >\
al_get_display_width(al_get_current_display()) * (
self.difficulty - 1) / self.difficulty:
target_y = dh / 2
else:
target_y = self.ball.y + (self.x - self.ball.x) *\
self.ball.ydir
if target_y < 0:
target_y = abs(target_y)
elif target_y > dh:
target_y = dh - target_y % dh
if target_y > self.y + self.h * 3 / 4:
self.moving = 1
elif target_y < self.y + self.h * 1 / 4:
self.moving = -1
else:
self.moving = 0
class Ball:
def __init__(self, x, y, speed, size, pallets, color):
self.x, self.y, self.speed, self.size, self.pallets, self.color =\
x, y, speed, size, pallets, color
self.xdir = randint(0, 1)
self.xdir = self.xdir - (self.xdir == 0)
self.ydir = randint(0, 1)
self.ydir = self.ydir - (self.ydir == 0)
def update(self):
new_x = self.x + self.xdir * self.speed
new_y = self.y + self.ydir * self.speed
p = self.pallets[(self.xdir == 1)]
if ((new_x <= p.x + p.w and self.xdir == -1) or (new_x + self.size >=
p.x and self.xdir == 1)) and new_y + self.size >= p.y and\
new_y <= p.y + p.h:
self.xdir = -self.xdir
self.speed += 0.1
self.on_pallet_touch(p)
self.new_x = self.x
dw = al_get_display_width(al_get_current_display())
dh = al_get_display_height(al_get_current_display())
if self.x < 0 or self.x > dw:
self.on_screen_exit()
if new_y < 0 or new_y + self.size > dh:
self.ydir = -self.ydir
new_y = self.y
self.x = new_x
self.y = new_y
def on_pallet_touch(self, pallet):
"""This function should be called on hitting a pallet"""
pass
def on_screen_exit(self):
'''This function is called when this ball exits the screen'''
pass
def draw(self):
al_draw_filled_circle(self.x + self.size / 2, self.y + self.size / 2,
self.size / 2, self.color)
al_draw_filled_circle(self.x + self.size / 4, self.y + self.size / 4,
self.size / 6, al_map_rgb_f(0.8, 0.9, 0.8))
class Upgrade(Ball):
def __init__(self, x, y, speed, pallets, color, effect_function):
Ball.__init__(self, x, y, speed, 10, pallets, color)
self.function = effect_function
self.touched = False
def on_pallet_touch(self, pallet):
self.touched = True
self.function(pallet)
def on_screen_exit(self):
self.touched = True
def main():
difficulty = int(input("What difficulty do you want to play on? " +
"Input: 0 for two-player mode, 1-4 for AI difficulty setting.\n"))
al_install_system(ALLEGRO_VERSION_INT, None)
w, h = 800, 600
al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST)
al_set_new_display_option(ALLEGRO_SAMPLES, 4, ALLEGRO_SUGGEST)
display = al_create_display(w, h)
al_init_primitives_addon()
al_install_keyboard()
al_init_image_addon()
al_init_font_addon()
font = al_load_font(os.path.join(examples_data, "fixed_font.tga"), 0, 0)
finished = False
need_redraw = True
FPS = 60
pallet_w, pallet_h, pallet_speed = 20, 80, 5
ball_size, ball_speed = 30, 4.6
players = []
players.append(Player(0, h / 2 - pallet_h / 2,
pallet_w, pallet_h, pallet_speed,
ALLEGRO_KEY_W, ALLEGRO_KEY_S, al_map_rgb_f(1.0, 0.0, 0.0)))
ball = Ball(w / 2, h / 2, ball_speed, ball_size, players,
al_map_rgb_f(0, 1.0, 0))
if not difficulty:
players.append(Player(w - pallet_w, h / 2 - pallet_h / 2,
pallet_w, pallet_h,
pallet_speed, ALLEGRO_KEY_UP, ALLEGRO_KEY_DOWN,
al_map_rgb_f(0.0, 0.0, 1.0)))
else:
players.append(AI(w - pallet_w, h / 2 - pallet_h / 2, pallet_w,
pallet_h, pallet_speed, al_map_rgb_f(0.0, 0.0, 1.0),
difficulty, ball))
def upgrade_grow_height(pallet):
pallet.h *= 1.25
def upgrade_shrink_height(pallet):
pallet.h *= 0.8
def upgrade_increase_speed(pallet):
pallet.speed *= 1.5
def upgrade_decrease_speed(pallet):
pallet.speed /= 1.5
upgrade_types = [
(al_map_rgb_f(0.0, 1.0, 0.0), upgrade_grow_height),
(al_map_rgb_f(1.0, 0.0, 0.0), upgrade_shrink_height),
(al_map_rgb_f(1.0, 1.0, 1.0), upgrade_increase_speed),
(al_map_rgb_f(0.3, 0.3, 0.3), upgrade_decrease_speed)]
upgrade_probability = 0.005
timer = al_create_timer(1.0 / FPS)
queue = al_create_event_queue()
al_register_event_source(queue, al_get_timer_event_source(timer))
al_register_event_source(queue, al_get_keyboard_event_source())
al_register_event_source(queue, al_get_display_event_source(display))
al_start_timer(timer)
upgrades = []
score = [0, 0]
while True:
if need_redraw and al_is_event_queue_empty(queue):
al_clear_to_color(al_map_rgb_f(0, 0, 0))
for player in players:
player.draw()
ball.draw()
for upgrade in upgrades:
upgrade.draw()
if not finished:
al_draw_text(font, al_map_rgb_f(1, 1, 1), w / 2, 10,
ALLEGRO_ALIGN_CENTRE, "Player 1: use W and S to move, " +
"Player 2: use the up and down arrow keys.")
else:
al_draw_text(font, al_map_rgb_f(1, 1, 1), w / 2, 10,
ALLEGRO_ALIGN_CENTRE, "Press R to reset, ESC to exit.")
al_draw_text(font, al_map_rgb_f(1, 1, 1), w / 2, h - 20,
ALLEGRO_ALIGN_CENTRE, "{0} - {1}".format(*score))
al_flip_display()
need_redraw = False
ev = ALLEGRO_EVENT()
al_wait_for_event(queue, byref(ev))
if ev.type == ALLEGRO_EVENT_TIMER:
for player in players:
player.update()
ball.update()
if ball.x + ball.size < 0 or ball.x > w:
finished = True
score[ball.x < 0] += 1
al_stop_timer(timer)
for upgrade in upgrades:
upgrade.update()
if upgrade.touched:
upgrades.remove(upgrade)
if random() < upgrade_probability:
i = randint(0, len(upgrade_types) - 1)
upgrades.append(Upgrade(w / 2, h / 2, ball_speed,
players, upgrade_types[i][0], upgrade_types[i][1]))
need_redraw = True
elif (ev.type == ALLEGRO_EVENT_KEY_DOWN and
ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) or\
ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE:
break
elif ev.type == ALLEGRO_EVENT_KEY_DOWN and\
ev.keyboard.keycode == ALLEGRO_KEY_R:
ball.x = w / 2
ball.y = h / 2
ball.speed = ball_speed
upgrades = []
for player in players:
player.reset()
al_start_timer(timer)
finished = False
for player in players:
player.handle_event(ev)
al_uninstall_system()
if __name__ == '__main__':
al_main(main)