๐Ÿ“‘ํ”„๋กœ์ ํŠธ-PingBall ๊ฒŒ์ž„ ์ œ์ž‘


๊ณ ๋“ฑํ•™๊ต๋•Œ ํ•‘๋ณผ ๊ฒŒ์ž„ ์ œ์ž‘ํ–ˆ๋˜ ๊ฑธ ์ •๋ฆฌํ•ด์„œ ์˜ฌ๋ ค๋ณด๊ณ ์ž ํ•œ๋‹ค.
๋‹น์‹œ Pygame์„ ์ฒ˜์Œ ์จ๋ดค์œผ๋ฉฐ ์–ด๋–ค ์›๋ฆฌ๋กœ ๊ฒŒ์ž„์ด ๋Œ์•„๊ฐ€๋Š”์ง€ ์•Œ์•„๋ณด๊ณ ์ž ํŒ€์› ์…‹์ด์„œ ๋ชจ์—ฌ์„œ ๊ฐ™์ด ์ฝ”๋”ฉํ–ˆ๋˜ ๊ธฐ์–ต์ด ์žˆ๋‹ค. ์ง€๊ธˆ๋„ ์†”์งํžˆ ์›๋ฆฌ๋‚˜ ๊ตฌ์กฐ๋ฅผ ์™„๋ฒฝํžˆ ์ดํ•ดํ•˜๋ฉฐ ์ฝ”๋“œ๋ฅผ ์™„๋ฒฝํ•˜๊ฒŒ ๊ตฌํ˜„ํ•ด๋ณด๋ผ ํ•˜๋ฉด ํ•  ์ž์‹ ์€ ์—†์œผ๋‚˜, ๊ฒŒ์ž„์ด ์–ด๋–ค ์”ฉ์œผ๋กœ ์ œ์ž‘๋˜๋Š”์ง€ ๊ทธ ๊ตฌ์กฐ๋ฅผ ์ดํ•ดํ•˜๋Š” ๋ฐ์— ์žˆ์–ด ํฐ ๋„์›€์ด ๋ฌ๋˜ ๊ฒƒ ๊ฐ™๋‹ค.
์žฌ์ฐจ ๋งํ•˜์ง€๋งŒ Pygame์„ ์‚ฌ์šฉํ•ด์„œ ํ–ˆ์œผ๋‹ˆ ๋”ฐ๋ผํ•ด๋ณผ ์‚ฌ๋žŒ๋“ค์€ ์ธ์Šคํ†จํ•˜๋ฉด ๋  ๊ฒƒ ๊ฐ™๋‹ค.


Pygame ์ธ์Šคํ†จ

๋‚˜๋Š” ์—ฌ๋Ÿฌ highlight์™€ ๊ธ€์ž ์ƒ‰๊น”์ด ์ด์œ VS code๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๊ฑธ ์ข‹์•„ํ•œ๋‹ค.
์†”์งํžˆ ์•„๋‚˜์ฝ˜๋‹ค๋‚˜ ์ŠคํŒŒ์ด๋”๋ฅผ ์“ฐ๋ฉด ๋ฝ€๋Œ€๊ฐ€ ์•ˆ๋‚œ๋‹ค๊ณ  ํ•ด์•ผํ• ๊นŒ...๋ฌผ๋ก  sciphy๊ฐ™์€ ํŠน์ • ํˆด์„ ์“ธ ๋•Œ ๋Š” spider๊ฐ€ ๋” ์ง๊ด€์ ์ด๊ณ  ๋ณด๊ธฐ ํŽธํ•œ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์œผ๋‹ˆ ๊ฐ์ž ๋งž๋Š” ํ”Œ๋žซํผ์„ ์“ฐ๋ฉด ๋˜๊ฒ ๋‹ค.


์š”๋ ‡๊ฒŒ pip install pygame ์„ ์ž…๋ ฅํ•ด์ฃผ๋ฉด pygame์ด ๊น”๋ฆฐ๋‹ค.
์ฝ”๋”ฉํ•  ์ค€๋น„๊ฐ€ ๋œ ๊ฒƒ์ด๋‹ค.


ํ•„๋“œ ์„ค์ •

์–ด๋Š ์–ธ์–ด์—์„œ๋‚˜ ํ•„๋“œ๋Š” ์ค‘์š”ํ•œ ๊ฒƒ ๊ฐ™๋‹ค.
์ดˆ๊ธฐ๊ฐ’, ๋ณ€์ˆ˜๋“ค์„ ์ง€์ •ํ•ด์ฃผ๋Š” ์ค‘์š”ํ•œ ๋ถ€๋ถ„์ด๋‹ˆ ์ดˆ๊ธฐ ํ•„๋“œ๋ฅผ ์ž˜ ์žก๊ณ  ๊ฐ€๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค.
๋จผ์ € ํŒŒ์ด๊ฒŒ์ž„๊ณผ ์‹œ์Šคํ…œ์„ importํ•ด์ฃผ๋Š” ์ž‘์—…์„ ๊ฑฐ์ณค๋‹ค.

import pygame as pg
import sys

๋‹ค์Œ์œผ๋กœ ํ•„๋“œ๋ฅผ ์ž‘์„ฑํ•ด์ค€๋‹ค.

Size = [640, 480]
Width = Size[0]
Height = Size[1]    

black = (0, 0, 0)
white = (255, 255, 255)
blue = (0, 0, 255)
yellow = (200, 200, 0)

State_Wait = 0
State_play = 1
State_Won = 2
State_Over = 3

Brick_Width = 60
Brick_Height = 15

Paddle_Width = 60
Paddle_Height = 15

Ball_Size = 16
Ball_Radius = int(Ball_Size/2)

Max_Paddle_X = Width - Paddle_Width
Max_Ball_X = Width - Ball_Size
Max_Ball_Y = Height - Ball_Size

Paddle_Y = Height - Paddle_Height - 10

์ฐจ๋ก€์ฐจ๋ก€ ์‚ดํŽด๋ณด๋ฉด

1 . Size๋กœ ํ•ด์ƒ๋„ ํฌ๊ธฐ ์„ค์ •
2 . Width/Height๋กœ ๊ฐ€๋กœ, ์„ธ๋กœ ํฌ๊ธฐ ์„ค์ •
3 . black, white, blue, yellow ๋“ฑ ๊ฒŒ์ž„ ๋‚ด์—์„œ ์‚ฌ์šฉํ•  ์ƒ‰๊น” ์„ค์ •
4 . ๊ฒŒ์ž„ ์ •์ง€/ํ”Œ๋ ˆ์ด/์ด๊น€/ํŒจ๋ฐฐ ์ƒํƒœ ์ˆซ์ž ์„ค์ •
5 . PingBall ๋ฒฝ๋Œ ํฌ๊ธฐ ์„ค์ •
6 . PingBall ํŒจ๋“ค(ํ”Œ๋ ˆ์ด์–ด) ํฌ๊ธฐ ์„ค์ •
7 . ๋ณผ ์‚ฌ์ด์ฆˆ ๋ฐ ํŒจ๋“ค๊ณผ ๋ณผ์ด ์ตœ๋Œ€๋กœ ์›€์ง์ผ ์ˆ˜ ์žˆ๋Š” ๊ฑฐ๋ฆฌ ์„ค์ •

์ •๋„ ๋˜์‹œ๊ฒ ๋‹ค.
๋ง๋ถ™์—ฌ์„œ ์•„๊นŒ ๋‚ด๊ฐ€ VS Code๊ฐ€ ์ด๋ป์„œ ์• ์šฉํ•œ๋‹ค๊ณ  ํ–ˆ๋Š”๋ฐ ๊ทธ ์˜ˆ์ค‘ ํ•˜๋‚˜๊ฐ€ ์ €๋ ‡๊ฒŒ ์ƒ‰๊น”์„ ์ž…๋ ฅํ•˜๋ฉด

์ด๋Ÿฐ์”ฉ์œผ๋กœ ๊ตฌ๋ณ„ํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์ƒ‰๊น”์— highlightํ•ด์„œ ๋‚˜์˜ค๋Š” ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค. ์™„์ „ ๋ฝ€๋Œ€๋‚˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ?
์ฝ”๋“œ ์ž์ฒด๋Š” ํฌ๊ฒŒ ๋‘ ๋ถ€๋ฅ˜๋กœ ๋‚˜๋ˆด๋‹ค. Class๋ฅผ ํ•˜๋‚˜ ์ง€์ •ํ•ด์„œ Pingball์˜ ๋ฉ”์ธ ๊ธฐ๋Šฅ์„ ํ•˜๋Š” ํ•‘๋ณผํด๋ž˜์Šค, ๊ทธ๋ฆฌ๊ณ  ๋ฉ”์ธํ•จ์ˆ˜ ์ž์ฒด ์‹คํ–‰์‹œํ‚ค๋Š” init. Init ์‹คํ–‰์€ ๊ฐ„๋‹จํ•˜๋‹ˆ๊นŒ ์—ฌ๊ธฐ ์ ๊ฒ ๋‹ค.

if __name__ == "__main__":
    PingBall().run()

ํ•˜๋‚˜ ์ฃผ์˜ํ•ด์•ผ ํ•  ์ ์€ ์œ„์˜ ์‹คํ–‰ ์ฝ”๋“œ๋Š” pingballํด๋ž˜์Šค ๋ฐ–์— ๋“ค์—ฌ์“ฐ๊ธฐ ํ•ด์•ผํ•œ๋‹ค. ๋งŒ์•ฝ ์•ˆ์œผ๋กœ ๋“ค์—ฌ์“ฐ๊ธฐํ•˜๋ฉด ๋ถ„๋ช…ํžˆ ์˜ค๋ฅ˜๊ฐ€ ๋‚œ๋‹ค.
์ด์ œ ํ•„๋“œ์™€ ์‹คํ–‰ ๋“ฑ์˜ ์ค€๋น„๊ฐ€ ๋‹ค ๋ฌ์œผ๋‹ˆ ๋ฉ”์ธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด์ž.


ํ•ต์‹ฌ ์ฝ”๋“œ ์ž‘์„ฑ

ํ•ต์‹ฌ ์ฝ”๋“œ๋Š” ์ด 10๊ฐœ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค. ํ•˜๋‚˜ํ•˜๋‚˜ ๊ทธ ๊ธฐ๋Šฅ์„ ๊ฐ„๋‹จํžˆ ์ •๋ฆฌํ•ด๋ณด์ž๋ฉด

1 . __init__ : ํŒŒ์ด๊ฒŒ์ž„ ์ดˆ๊ธฐํ™”์‹œํ‚จ ์œˆ๋„์šฐ์ฐฝ ๋งŒ๋“ค๊ณ  Fps/Font๋“ฑ ๊ธฐ๋ณธ์„ค์ •
2 . init_game : ๊ธฐ๋ณธ ๋ชฉ์ˆจ/์Šค์ฝ”์–ด/์ƒํƒœ ์„ค์ • ๋ฐ ๊ณต๊ณผ ํŒจ๋“ค์˜ ์œ„์น˜์„ค์ •
3 . create_bricks : for๋ฌธ์„ ํ™œ์šฉํ•˜์—ฌ ์‹ค์งˆ์ ์ธ ๋ฒฝ๋Œ์„ ๋งŒ๋“ฆ
4 . draw_bricks : ๋ฒฝ๋Œ์˜ ์ƒ‰๊น” ์ง€์ • ๋ฐ ๋ฒฝ๋Œ ๊ทธ๋ฆฌ๊ธฐ
5 . check_input : ํ‚ค๋ณด๋“œ๊ฐ€ ๋ˆŒ๋ ธ์„ ๋•Œ ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ์ง€ ํŠธ๋ฆฌ๊ฑฐ ์„ค์ •
6 . move_ball : ๊ณต์ด ์–ด๋””์— ๋‹ฟ์œผ๋ฉด ๋ฉˆ์ถ”๊ณ  ํŠ•๊ธฐ๋Š”์ง€ ๋“ฑ ์„ค์ •
7 . handle_collisions : ์Šน๋ฆฌ ์กฐ๊ฑด ๋‹ฌ์„ฑ์‹œ ๋๋‚ด๋Š” ์ฝ”๋“œ
8 . show_stats : ์ ์ˆ˜์™€ ๋ชฉ์ˆจ ํ‘œ์‹œ
9 . show_message : ๋ฉ”์„ธ์ง€ ํ‘œ์‹œ
10 . run : ๋ฉ”์ธํ•จ์ˆ˜๋ผ๊ณ  ๋ณด๋ฉด ๋  ๊ฒƒ ๊ฐ™๋‹ค.

์ฒ˜์Œ์— ๋Œ€์ฒด ์ด๊ฑธ ์–ด๋–ป๊ฒŒ ์งœ์•ผ ํ•  ์ง€ ๋ง‰๋ง‰ํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์œ ํŠœ๋ธŒ๋กœ ๊ฐ•์˜๋„ ์ฐพ์•„๋ณด๊ณ , ๊ตฌ๊ธ€๋ง์„ ์—ด์‹ฌํžˆ ํ•˜๋‹ˆ๊นŒ ์ด์ •๋„๋กœ ์ฝ”๋”ฉ์„ ํ•˜๋ฉด ์˜ค๋ฅ˜์—†์ด ์ž˜ ์ž‘๋™ํ•จ์„ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์œ„์˜ ์ฝ”๋“œ๋ฅผ ํ•˜๋‚˜ํ•˜๋‚˜ ์ž‘์„ฑํ•˜๊ณ  ์„ค๋ช…ํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ๋‹ค.

Init

    def __init__(self):
        pg.init()

        self.screen = pg.display.set_mode(Size)
        pg.display.set_caption("PingBall_Game")
        self.fps = pg.time.Clock()
        self.font = pg.font.Font(None, 30)

        self.init_game()

Init์€ ์œˆ๋„์šฐ ์ฐฝ์„ ์ดˆ๊ธฐํ™”์‹œ์ผœ์ฃผ๊ณ  Fps๋‚˜ ๊ธฐ๋ณธ ํฐํŠธ๊ฐ™์€๊ฑธ ์„ค์ •ํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.
ํ•œ๊ฐ€์ง€ ์ฃผ์˜ํ•  ์ ์ด ์žˆ๋‹ค๋ฉด ๋‚ด๊ฐ€ init๊ณผ init_game์„ ๋”ฐ๋กœ ์ง  ์ด์œ ๋Š” init๋งŒ ๊ฐ€์ง€๊ณ ๋Š” ์œˆ๋„์šฐ์ฐฝ ์ž์ฒด๊ฐ€ ๊ณ„์† ์œ ์ง€๋˜์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ž˜์„œ ๋”ฐ๋กœ ์ฝ”๋“œ๋ฅผ ์งœ์ฃผ๊ฑฐ๋‚˜ ๋ฉ”์ธ ๋ฉ”์†Œ๋“œ๊ฐ™์€ ๊ณณ์— ๊ฒŒ์ž„๋ฃจํ”„๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค. ๊ฒŒ์ž„๋ฃจํ”„์— ๋Œ€ํ•œ ๋ถ€๊ฐ€์ ์ธ ๋‚ด์šฉ์„ ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด ์ด ๊ณณ ์ฐธ์กฐ.

Init_game

    def init_game(self):
        self.lives = 3
        self.score = 0
        self.state = State_Wait

        self.paddle = pg.Rect(300, Paddle_Y, Paddle_Width, Paddle_Height)
        self.ball = pg.Rect(300, Paddle_Y - Ball_Size, Ball_Size, Ball_Size)

        self.create_bricks()

์ฒซ ๋ชฉ์ˆจ์€ 3๊ฐœ, ์Šค์ฝ”์–ด๋Š” ๋‹น์—ฐํžˆ 0์œผ๋กœ ํ•ด๋‘์—ˆ๊ณ  ์ƒํƒœ๋Š” ๊ธฐ๋‹ค๋ฆผ์œผ๋กœ ํ–ˆ๋‹ค. pg.Rect๋ฅผ ์‚ฌ์šฉํ•ด ํŒจ๋“ค๊ณผ ๊ณต์˜ ์œ„์น˜๋ฅผ ์„ฑ์ •ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

create_bricks

    def create_bricks(self):
        Y = 35
        self.bricks = []
        for i in range(7):
            X = 35
            for j in range(8):
                self.bricks.append(pg.Rect(X, Y, Brick_Width, Brick_Height))
                X += Brick_Width + 10
            Y += Brick_Height + 5

Gui๋กœ ๋ช‡๋ฒˆ ๊ตฌํ˜„์„ ํ•ด๋ณด๋‹ค๋ณด๋‹ˆ๊นŒ ๋‚œ์ด๋„์—๋Š” brick 56๊ฐœ๊ฐ€ ์ ๋‹นํ•˜๋‹ค๋Š” ๊ฒฐ๋ก ์— ๋„๋‹ฌํ–ˆ๋‹ค.
X์™€ Y๋Š” Brick ๊ฐ„์˜ ๊ฐ„๊ฒฉ์„ ์„ค์ •ํ•ด์ฃผ๊ธฐ ์œ„ํ•ด ์ ์–ด๋‘” ๊ฑฐ๋‹ค. Y์˜ ์ดˆ๊ธฐ๊ฐ’์€ 35, X์˜ ์ดˆ๊ธฐ๊ฐ’ ๋˜ํ•œ 35๋กœ ์ง€์ •ํ•œ ํ›„ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ตํ•ด ๊ฐ๊ฐ 10,5 ์”ฉ ์ฆ๊ฐ์—ฐ์‚ฐ์„ ํ•˜์—ฌ ๋ฒฝ๋Œ๊ฐ„์˜ ๊ฐ„๊ฒฉ์„ ์ง€์ •ํ•ด์ฃผ์—ˆ๋‹ค.

draw_bricks

def draw_bricks(self):
        for brick in self.bricks:
            pg.draw.rect(self.screen, yellow, brick)

๋ฒฝ๋Œ์„ ๋…ธ๋ž€์ƒ‰์œผ๋กœ ๊ทธ๋ ค์ค€๋‹ค.

check_input


    def check_input(self):
        keys = pg.key.get_pressed()

        if keys[pg.K_LEFT]:
            self.paddle.left -= 5
            if self.paddle.left < 0:
                self.paddle.left = 0
        if keys[pg.K_RIGHT]:
            self.paddle.left += 5
            if self.paddle.left > Max_Paddle_X:
                self.paddle.left = Max_Paddle_X
        if keys[pg.K_SPACE] and self.state == State_Wait:
            self.ball_move = [5, -5]
            self.state = State_play
        if keys[pg.K_r] and (self.state == State_Over or self.state == State_Won):
            self.init_game()

๋ง๊ทธ๋Œ€๋กœ ํ‚ค๋ณด๋“œ ์ธํŽ์„ ๋ฐ›์•„์ฃผ๋Š” ์ฝ”๋“œ๋‹ค. ํ‚ค๋ณด๋“œ ์ธํŽ ๋ ˆํ”„ํŠธ๋กœ ๊ฐ€๊ฒŒ ๋ผ ์žˆ์œผ๋ฉด ํŒจ๋“ค์„ ์™ผ์ชฝ์œผ๋กœ 5๋งŒํผ ์˜ฎ๊ธด๋‹ค๋˜๊ฐ€ ํ•˜๋Š” ์ฝ”๋“œ ๋ง์ด๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ๊ฐ€๊ฒŒ ๋˜๋ฉด +5 ๋ฅผ ์ฆ๊ฐ์—ฐ์‚ฐ ํ•ด์ฃผ๋ฉด ๋œ๋‹ค. ํ•œ ๊ฐ€์ง€ ์ฃผ์˜ํ•  ์ ์€ ์ฐฝ์„ ๋„˜์–ด๊ฐ€๋ฉด ์•ˆ ๋˜๊ธฐ ๋•Œ๋ฌธ์— Max๊ฐ’๊ณผ 0๊ฐ’ ๋“ฑ์„ ์ด์šฉํ•ด์„œ ์ฐฝ์˜ ํฌ๊ธฐ๋งŒํผ๋งŒ ์›€์ง์ด๊ฒŒ ์„ค์ •ํ•ด์•ผํ•œ๋‹ค.

move_ball

  def move_ball(self):
        self.ball.left += self.ball_move[0]
        self.ball.top += self.ball_move[1]

        if self.ball.left <= 0:
            self.ball.left = 0
            self.ball_move[0] = -self.ball_move[0]
        elif self.ball.left >= Max_Ball_X:
            self.ball.left = Max_Ball_X
            self.ball_move[0] = -self.ball_move[0]

        if self.ball.top < 0:
            self.ball.top = 0
            self.ball_move[1] = -self.ball_move[1]

์ด ์ฝ”๋“œ ๋˜ํ•œ top ๋“ฑ์„ ์„ค์ •ํ•ด์„œ ๊ณต์ด ํ™”๋ฉด ๋ฐ–์œผ๋กœ ์•ˆ๋‚˜๊ฐ€๊ฒŒ ์ฝ”๋”ฉํ–ˆ๋˜๊ฑฐ๋‹ค.

handle_collisions

    def handle_collisions(self):
        for brick in self.bricks:
            if self.ball.colliderect(brick):
                self.score += 1
                self.ball_move[1] = -self.ball_move[1]
                self.bricks.remove(brick)
                break
        if len(self.bricks) == 0:
            self.state = State_Won
                if self.ball.colliderect(self.paddle):
            self.ball.top = Paddle_Y - Ball_Size
            self.ball_move[1] = -self.ball_move[1]
        elif self.ball.top > self.paddle.top:
            self.lives -= 1
            if self.lives > 0:
                self.state = State_Wait
            else:
                self.state = State_Over

๋ฒฝ๋Œ์— ์ถฉ๋Œํ•˜๋ฉด ๋ฒฝ๋Œ์ด ํ•˜๋‚˜ ์‚ฌ๋ผ์ง€๊ณ  ์ ์ˆ˜๊ฐ€ ์˜ฌ๋ผ๊ฐ€๊ฒŒ ํ•˜๋Š” ์ถฉ๋Œ ์ด๋ฒคํŠธ์™€ ๋ฒฝ๋Œ์„ ์ „๋ถ€ ์ œ๊ฑฐํ–ˆ์„ ์‹œ์— ์ƒํƒœ๋ฅผ won์œผ๋กœ ํ‘œํ˜„ํ•˜๊ฒŒ ํ•˜๋Š” ์ฝ”๋“œ๋‹ค.

show_stats/show_message

def show_stats(self):
        if self.font:
            font_surface = self.font.render("Score : " + str(self.score)
                                            + " Lives : " + str(self.lives), True, white)
            self.screen.blit(font_surface, (205, 5))

    def show_message(self, message):
        if self.font:
            size = self.font.size(message)
            font_surface = self.font.render(message, False, white)
            x = (Size[0] - size[0]) // 2
            y = (Size[1] - size[1]) // 2
            self.screen.blit(font_surface, (x, y))

ํ˜„์žฌ ์Šคํƒฏ(์ ์ˆ˜์™€ ๋ชฉ์ˆจ)์„ ๋ณด์—ฌ์ฃผ๋Š” ์ฝ”๋“œํ•˜๊ณ  ๋ฉ”์„ธ์ง€๋กœ ์ถœ๋ ฅํ•ด์ฃผ๋Š” ์ฝ”๋“œ๋‹ค.

run

    def run(self):
        while True:
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    pg.quit()
                    sys.exit()

            self.screen.fill(black)
            self.check_input()

            if self.state == State_play:
                self.move_ball()
                self.handle_collisions()
            elif self.state == State_Wait:
                self.ball.left = self.paddle.left + self.paddle.width / 2
                self.ball.top = self.paddle.top - self.ball.height
                self.show_message("Press space to lanch the ball")
            elif self.state == State_Over:
                self.show_message("Game over! press R to play again")
            elif self.state == State_Won:
                self.show_message("You Win! press R to play again")

            self.draw_bricks()
            pg.draw.rect(self.screen, blue, self.paddle)
            pg.draw.circle(self.screen, white, (self.ball.left + Ball_Radius,
                                    self.ball.top + Ball_Radius), Ball_Radius)
            self.show_stats()

            self.fps.tick(60)
            pg.display.update()

Fps, ๋””์Šคํ”Œ๋ ˆ์ด, ์ƒํƒœ(state)์— ๋”ฐ๋ฅธ ๋ฉ”์„ธ์ง€ ์ถœ๋ ฅ ๋“ฑ์„ ๋‹ด๋‹นํ•˜๋Š” run ๋ฉ”์†Œ๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ๋๋‚œ๋‹ค.
์•„๊นŒ ๋งํ–ˆ๋“ฏ์ด init์—์„œ ์œˆ๋„์šฐ ์ฐฝ์„ ํ•ญ์ƒ ์—ด์–ด์ฃผ์ง„ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋‚˜๊ฐ™์€ ๊ฒฝ์šฐ๋Š” while์— true๋ฅผ ์จ์„œ ๋ฌดํ•œ๋ฃจํ”„์‹œ์ผฐ๋‹ค. ์ด์ œ ๊ฒŒ์ž„ ์ œ์ž‘ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด


ํ…Œ์ŠคํŠธ ๋ฐ ์™„์„ฑ๋ณธ


์•„๊นŒ ์„ค์ •ํ–ˆ๋˜ ๋ชฉ์ˆจ/์Šค์ฝ”์–ด ๋“ค์€ ์ด์ƒ์—†๊ณ  ์ƒํƒœ๋ฉ”์„ธ์ง€, ๋ฒฝ๋Œ, ๊ณต, ํŒจ๋“ค๊นŒ์ง€ ์ด์ƒ์—†์ด ์ถœ๋ ฅ๋˜๋Š” ๋ชจ์Šต์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์ƒํƒœ๋ณ€ํ™”์—๋„ ํฐ ์ด์ƒ์ด ์—†์œผ๋ฉฐ ์Šค์ฝ”์–ด ๋˜ํ•œ ์ž˜ ์˜ฌ๋ผ๊ฐ€๋Š” ๋ชจ์Šต์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค


์–ธ์ œ๋‚˜ ๊ทธ๋žฌ๋“ฏ์ด ์•„๋ž˜์— ์ฝ”๋“œ ์ „๋ฌธ์„ ์ฒจ๋ถ€ํ•œ๋‹ค.

import pygame as pg
import sys

Size = [640, 480]
Width = Size[0]
Height = Size[1]

black = (0, 0, 0)
white = (255, 255, 255)
blue = (0, 0, 255)
yellow = (200, 200, 0)

State_Wait = 0
State_play = 1
State_Won = 2
State_Over = 3

Brick_Width = 60
Brick_Height = 15

Paddle_Width = 60
Paddle_Height = 15

Ball_Size = 16
Ball_Radius = int(Ball_Size/2)

Max_Paddle_X = Width - Paddle_Width
Max_Ball_X = Width - Ball_Size
Max_Ball_Y = Height - Ball_Size

Paddle_Y = Height - Paddle_Height - 10


class PingBall:
    def __init__(self):
        pg.init()

        self.screen = pg.display.set_mode(Size)
        pg.display.set_caption("PingBall_Game")
        self.fps = pg.time.Clock()
        self.font = pg.font.Font(None, 30)

        self.init_game()

    def init_game(self):
        self.lives = 3
        self.score = 0
        self.state = State_Wait

        self.paddle = pg.Rect(300, Paddle_Y, Paddle_Width, Paddle_Height)
        self.ball = pg.Rect(300, Paddle_Y - Ball_Size, Ball_Size, Ball_Size)

        self.create_bricks()

    def create_bricks(self):
        Y = 35
        self.bricks = []
        for i in range(7):
            X = 35
            for j in range(8):
                self.bricks.append(pg.Rect(X, Y, Brick_Width, Brick_Height))
                X += Brick_Width + 10
            Y += Brick_Height + 5
            
    def draw_bricks(self):
        for brick in self.bricks:
            pg.draw.rect(self.screen, yellow, brick)

    def check_input(self):
        keys = pg.key.get_pressed()

        if keys[pg.K_LEFT]:
            self.paddle.left -= 5
            if self.paddle.left < 0:
                self.paddle.left = 0
        if keys[pg.K_RIGHT]:
            self.paddle.left += 5
            if self.paddle.left > Max_Paddle_X:
                self.paddle.left = Max_Paddle_X
        if keys[pg.K_SPACE] and self.state == State_Wait:
            self.ball_move = [5, -5]
            self.state = State_play
        if keys[pg.K_r] and (self.state == State_Over or self.state == State_Won):
            self.init_game()

    def move_ball(self):
        self.ball.left += self.ball_move[0]
        self.ball.top += self.ball_move[1]

        if self.ball.left <= 0:
            self.ball.left = 0
            self.ball_move[0] = -self.ball_move[0]
        elif self.ball.left >= Max_Ball_X:
            self.ball.left = Max_Ball_X
            self.ball_move[0] = -self.ball_move[0]

        if self.ball.top < 0:
            self.ball.top = 0
            self.ball_move[1] = -self.ball_move[1]

    def handle_collisions(self):
        for brick in self.bricks:
            if self.ball.colliderect(brick):
                self.score += 1
                self.ball_move[1] = -self.ball_move[1]
                self.bricks.remove(brick)
                break
        if len(self.bricks) == 0:
            self.state = State_Won

        if self.ball.colliderect(self.paddle):
            self.ball.top = Paddle_Y - Ball_Size
            self.ball_move[1] = -self.ball_move[1]
        elif self.ball.top > self.paddle.top:
            self.lives -= 1
            if self.lives > 0:
                self.state = State_Wait
            else:
                self.state = State_Over

    def show_stats(self):
        if self.font:
            font_surface = self.font.render("Score : " + str(self.score)
                                            + " Lives : " + str(self.lives), True, white)
            self.screen.blit(font_surface, (205, 5))

    def show_message(self, message):
        if self.font:
            size = self.font.size(message)
            font_surface = self.font.render(message, False, white)
            x = (Size[0] - size[0]) // 2
            y = (Size[1] - size[1]) // 2
            self.screen.blit(font_surface, (x, y))

    def run(self):
        while True:
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    pg.quit()
                    sys.exit()

            self.screen.fill(black)
            self.check_input()

            if self.state == State_play:
                self.move_ball()
                self.handle_collisions()
            elif self.state == State_Wait:
                self.ball.left = self.paddle.left + self.paddle.width / 2
                self.ball.top = self.paddle.top - self.ball.height
                self.show_message("Press space to lanch the ball")
            elif self.state == State_Over:
                self.show_message("Game over! press R to play again")
            elif self.state == State_Won:
                self.show_message("You Win! press R to play again")

            self.draw_bricks()
            pg.draw.rect(self.screen, blue, self.paddle)
            pg.draw.circle(self.screen, white, (self.ball.left + Ball_Radius,
                                    self.ball.top + Ball_Radius), Ball_Radius)
            self.show_stats()

            self.fps.tick(60)
            pg.display.update()


if __name__ == "__main__":
    PingBall().run()

์ข‹์€ ์›นํŽ˜์ด์ง€ ์ฆ๊ฒจ์ฐพ๊ธฐ