Sections Demo 2#

Screen shot of using sections
sections_demo_2.py#
  1"""
  2Section Example 2:
  3
  4In this Section example we develop a very basic Pong game playable by two
  5persons in the same computer (hot seat!).
  6
  7Each Player is abstracted as a Section that consists of a space in the screen
  8where the player paddle can move.
  9
 10Note:
 11    - Sections can live along with Views. Sections do not need to occupy 100%
 12      of the screen.
 13    - View methods can interact with Sections by storing a reference to each
 14      one.
 15    - How keyboard events can be redirected to each section depending on the
 16      pressed key automatically.
 17
 18If Python and Arcade are installed, this example can be run from the command line with:
 19python -m arcade.examples.sections_demo_2
 20"""
 21import random
 22
 23from arcade import Window, Section, View, SpriteList, SpriteSolidColor, \
 24    SpriteCircle, draw_text, draw_line
 25from arcade.color import BLACK, BLUE, RED, BEAU_BLUE, GRAY
 26from arcade.key import W, S, UP, DOWN
 27
 28PLAYER_SECTION_WIDTH = 100
 29PLAYER_PADDLE_SPEED = 10
 30
 31
 32class Player(Section):
 33    """
 34    A Section representing the space in the screen where the player
 35    paddle can move
 36    """
 37
 38    def __init__(self, left: int, bottom: int, width: int, height: int,
 39                 key_up: int, key_down: int, **kwargs):
 40        super().__init__(left, bottom, width, height, accept_keyboard_keys={key_up, key_down}, **kwargs)
 41
 42        # keys assigned to move the paddle
 43        self.key_up: int = key_up
 44        self.key_down: int = key_down
 45
 46        # the player paddle
 47        self.paddle: SpriteSolidColor = SpriteSolidColor(30, 100, color=BLACK)
 48
 49        # player score
 50        self.score: int = 0
 51
 52    def setup(self):
 53        # reset the player paddle position to the middle of the screen
 54        self.paddle.position = self.left + 50, self.height / 2
 55
 56    def on_update(self, delta_time: float):
 57        # update the paddle position
 58        self.paddle.update()
 59
 60    def on_draw(self):
 61        # draw sections info and score
 62        if self.name == 'Left':
 63            keys = 'W and S'
 64            start_x = self.left + 5
 65        else:
 66            keys = 'UP and DOWN'
 67            start_x = self.left - 290
 68        draw_text(f'Player {self.name} (move paddle with: {keys})',
 69                  start_x, self.top - 20, BLUE, 9)
 70        draw_text(f'Score: {self.score}', self.left + 20,
 71                  self.bottom + 20, BLUE)
 72
 73        # draw the paddle
 74        self.paddle.draw()
 75
 76    def on_key_press(self, symbol: int, modifiers: int):
 77        # set the paddle direction and movement speed
 78        if symbol == self.key_up:
 79            self.paddle.change_y = PLAYER_PADDLE_SPEED
 80        else:
 81            self.paddle.change_y = -PLAYER_PADDLE_SPEED
 82
 83    def on_key_release(self, _symbol: int, _modifiers: int):
 84        # stop moving the paddle
 85        self.paddle.stop()
 86
 87
 88class Pong(View):
 89
 90    def __init__(self):
 91        super().__init__()
 92
 93        # a sprite list that will hold each player paddle to
 94        # check for collisions
 95        self.paddles: SpriteList = SpriteList()
 96
 97        # we store each Section
 98        self.left_player: Player = Player(
 99            0, 0, PLAYER_SECTION_WIDTH, self.window.height, key_up=W,
100            key_down=S, name='Left')
101        self.right_player: Player = Player(
102            self.window.width - PLAYER_SECTION_WIDTH, 0, PLAYER_SECTION_WIDTH,
103            self.window.height, key_up=UP, key_down=DOWN, name='Right')
104
105        # add the sections to the SectionManager so Sections start to work
106        self.add_section(self.left_player)
107        self.add_section(self.right_player)
108
109        # add each paddle to the sprite list
110        self.paddles.append(self.left_player.paddle)
111        self.paddles.append(self.right_player.paddle)
112
113        # create the ball
114        self.ball: SpriteCircle = SpriteCircle(20, RED)
115
116    def setup(self):
117        # set up a new game
118
119        # set ball position in the middle
120        self.ball.position = self.window.width / 2, self.window.height / 2
121
122        # randomize ball direction and speed
123        self.ball.change_x = random.choice([-3, -2, 3, 2])
124        self.ball.change_y = random.choice([-3, -2, 3, 2])
125
126        # setup player paddles
127        self.left_player.setup()
128        self.right_player.setup()
129
130    def on_update(self, delta_time: float):
131        self.ball.update()  # update the ball
132
133        # bounce the ball either at the top or at the bottom
134        if self.ball.bottom <= 0:
135            self.ball.change_y *= -1
136        elif self.ball.top >= self.window.height:
137            self.ball.change_y *= -1
138
139        # check if the ball has collided with a paddle
140        collided_paddle = self.ball.collides_with_list(self.paddles)
141        if collided_paddle:
142            # adjust ball coordinates to simplify the game
143            if collided_paddle[0] is self.left_player.paddle:
144                self.ball.left = self.left_player.paddle.right
145            else:
146                self.ball.right = self.right_player.paddle.left
147
148            # bounce the ball from the paddle
149            self.ball.change_x *= -1
150
151        # check if the ball has exited the screen in either side and
152        # end the game
153        if self.ball.right <= 0:
154            self.end_game(self.right_player)
155        elif self.ball.left >= self.window.width:
156            self.end_game(self.left_player)
157
158    def end_game(self, winner: Player):
159        """ Called when one player wins """
160        winner.score += 1  # increment the winner score
161        self.setup()  # prepare a new game
162
163    def on_draw(self):
164        self.clear(BEAU_BLUE)  # clear the screen
165
166        self.ball.draw()  # draw the ball
167
168        half_window_x = self.window.width / 2  # middle x
169
170        # draw a line diving the screen in half
171        draw_line(half_window_x, 0, half_window_x, self.window.height, GRAY, 2)
172
173
174def main():
175    # create the window
176    window = Window(title='Two player simple Pong with Sections!')
177
178    # create the custom View
179    game = Pong()
180
181    # set up the game (start a game)
182    game.setup()
183
184    # show the view
185    window.show_view(game)
186
187    # run arcade loop
188    window.run()
189
190
191if __name__ == '__main__':
192    main()