Sections Demo 2#

sections_demo_2.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 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | """
Section Example 2:
In this Section example we develop a very basic Pong game playable by two
persons in the same computer (hot seat!).
Each Player is abstracted as a Section that consists of a space in the screen
where the player paddle can move.
Note:
- Sections can live along with Views. Sections do not need to occupy 100%
of the screen.
- View methods can interact with Sections by storing a reference to each
one.
- How keyboard events can be redirected to each section depending on the
pressed key automatically.
"""
import random
from arcade import Window, Section, View, SpriteList, SpriteSolidColor, \
SpriteCircle, draw_text, draw_line
from arcade.color import BLACK, BLUE, RED, BEAU_BLUE, GRAY
from arcade.key import W, S, UP, DOWN
PLAYER_SECTION_WIDTH = 100
PLAYER_PADDLE_SPEED = 10
class Player(Section):
"""
A Section representing the space in the screen where the player
paddle can move
"""
def __init__(self, left: int, bottom: int, width: int, height: int,
key_up: int, key_down: int, **kwargs):
super().__init__(left, bottom, width, height,
accept_keyboard_events={key_up, key_down}, **kwargs)
# keys assigned to move the paddle
self.key_up: int = key_up
self.key_down: int = key_down
# the player paddle
self.paddle: SpriteSolidColor = SpriteSolidColor(30, 100, BLACK)
# player score
self.score: int = 0
def setup(self):
# reset the player paddle position to the middle of the screen
self.paddle.position = self.left + 50, self.height / 2
def on_update(self, delta_time: float):
# update the paddle position
self.paddle.update()
def on_draw(self):
# draw sections info and score
if self.name == 'Left':
keys = 'W and S'
start_x = self.left + 5
else:
keys = 'UP and DOWN'
start_x = self.left - 290
draw_text(f'Player {self.name} (move paddle with: {keys})',
start_x, self.top - 20, BLUE, 9)
draw_text(f'Score: {self.score}', self.left + 20,
self.bottom + 20, BLUE)
# draw the paddle
self.paddle.draw()
def on_key_press(self, symbol: int, modifiers: int):
# set the paddle direction and movement speed
if symbol == self.key_up:
self.paddle.change_y = PLAYER_PADDLE_SPEED
else:
self.paddle.change_y = -PLAYER_PADDLE_SPEED
def on_key_release(self, _symbol: int, _modifiers: int):
# stop moving the paddle
self.paddle.stop()
class Pong(View):
def __init__(self):
super().__init__()
# a sprite list that will hold each player paddle to
# check for collisions
self.paddles: SpriteList = SpriteList()
# we store each Section
self.left_player: Player = Player(
0, 0, PLAYER_SECTION_WIDTH, self.window.height, key_up=W,
key_down=S, name='Left')
self.right_player: Player = Player(
self.window.width - PLAYER_SECTION_WIDTH, 0, PLAYER_SECTION_WIDTH,
self.window.height, key_up=UP, key_down=DOWN, name='Right')
# add the sections to the SectionManager so Sections start to work
self.add_section(self.left_player)
self.add_section(self.right_player)
# add each paddle to the sprite list
self.paddles.append(self.left_player.paddle)
self.paddles.append(self.right_player.paddle)
# create the ball
self.ball: SpriteCircle = SpriteCircle(20, RED)
def setup(self):
# set up a new game
# set ball position in the middle
self.ball.position = self.window.width / 2, self.window.height / 2
# randomize ball direction and speed
self.ball.change_x = random.choice([-3, -2, 3, 2])
self.ball.change_y = random.choice([-3, -2, 3, 2])
# setup player paddles
self.left_player.setup()
self.right_player.setup()
def on_update(self, delta_time: float):
self.ball.update() # update the ball
# bounce the ball either at the top or at the bottom
if self.ball.bottom <= 0:
self.ball.change_y *= -1
elif self.ball.top >= self.window.height:
self.ball.change_y *= -1
# check if the ball has collided with a paddle
collided_paddle = self.ball.collides_with_list(self.paddles)
if collided_paddle:
# adjust ball coordinates to simplify the game
if collided_paddle[0] is self.left_player.paddle:
self.ball.left = self.left_player.paddle.right
else:
self.ball.right = self.right_player.paddle.left
# bounce the ball from the paddle
self.ball.change_x *= -1
# check if the ball has exited the screen in either side and
# end the game
if self.ball.right <= 0:
self.end_game(self.right_player)
elif self.ball.left >= self.window.width:
self.end_game(self.left_player)
def end_game(self, winner: Player):
""" Called when one player wins """
winner.score += 1 # increment the winner score
self.setup() # prepare a new game
def on_draw(self):
self.clear(BEAU_BLUE) # clear the screen
self.ball.draw() # draw the ball
half_window_x = self.window.width / 2 # middle x
# draw a line diving the screen in half
draw_line(half_window_x, 0, half_window_x, self.window.height, GRAY, 2)
def main():
# create the window
window = Window(title='Two player simple Pong with Sections!')
# create the custom View
game = Pong()
# set up the game (start a game)
game.setup()
# show the view
window.show_view(game)
# run arcade loop
window.run()
if __name__ == '__main__':
main()
|