ボールが落ちてくるやつ


[ソフトバンクの料金詳細](https://www.softbank.jp/sbnews/entry/20230315_03)のボールが落ちてくるやつオシャレじゃん！ていうやつです。

## 　成果物

![Videotogif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3724119/1c1c91e8-2cb2-8db4-8bbf-314a0bc4c1f9.gif)



必要なもの
```
pip install pygame
pip install pymunk

```

pygameはデフォルトだと日本語のテキストを出力できないので別途作業が必要です。
コードを動かすディレクトリに使いたいフォントを入れてください。
今回は[ipaexg](https://moji.or.jp/ipafont/ipafontdownload/) を使いました。
サンプルの10行目あたりの
font = pygame.font.Font('ipaexg.ttf', 50)で設定しています。

大枠は一昔前に流行ったスイカゲームを参考にしています。

```sample.py

import pygame
import pymunk
from pygame.locals import *

pygame.init()

disp_size = (600, 800)
display = pygame.display.set_mode(disp_size)
clock = pygame.time.Clock()
space = pymunk.Space()
space.gravity = 0, -170
font = pygame.font.Font('ipaexg.ttf', 50)
"""
50, 650
550, 300
"""
surfaceOne = pygame.Surface((500, 350)) #横幅、縦幅
surfaceOneArea = [50, 150] # 左端[x,y]
FPS = 100

BLACK = (10, 20, 10)
WHE = (245,245,245)
WHEAT = (250, 250, 250)
WHITE = (255,255,255)

testColor = (0,150,0)

surfaceOne.fill((WHEAT))

color_01 = (1,110,254)
#color_02 = (255,187,44)
color_02 = (250,10,0)
color_03 = (148,219,1)
color_04 = (255,97,163)
color_05 = (143,143,143)
color_06 = (144, 175, 197)

radius_01 = 50
radius_02 = 35
radius_03 = 80
radius_04 = 35
radius_05 = 20
radius_06 = 75

def convert_cordinates(point):
    return point[0], disp_size[1]-point[1]

class Ball(object):
    def __init__(self, x, y, color, radius, mass, collision_type,text):
        self.color = color
        self.body = pymunk.Body(body_type=pymunk.Body.DYNAMIC)
        self.body.position = x, y
        self.body.mass = mass
        self.shape = pymunk.Circle(self.body, radius)
        self.shape.collision_type = collision_type
        self.shape.density = 1
        self.shape.elasticity = 0.5
        self.shape.friction = 0.5
        self.text = text
        space.add(self.body, self.shape)
    def draw(self):
        pygame.draw.circle(
            display,
            self.color,
            convert_cordinates(self.body.position),
            self.shape.radius
        )
        text = font.render(self.text, True, BLACK)
        text_rect = text.get_rect(center=convert_cordinates(self.body.position))
        display.blit(text, text_rect)


class Ball01(Ball):
    def __init__(self, x, y):
        super().__init__(x, y, color_01, radius_01, 10, 1,"テキスト")
        pass

class Ball02(Ball):
    def __init__(self, x, y):
        super().__init__(x, y, color_02, radius_02, 15, 2,"テキスト")
        pass

class Ball03(Ball):
    def __init__(self, x, y):
        super().__init__(x, y, color_03, radius_03, 20, 3,"テキスト")
        pass

class Ball04(Ball):
    def __init__(self, x, y):
        super().__init__(x, y, color_04, radius_04, 25, 4,"テキスト")
        pass

class Ball05(Ball):
    def __init__(self, x, y):
        super().__init__(x, y, color_05, radius_05, 30, 5 ,"テキスト")
        pass

class Ball06(Ball):
    def __init__(self, x, y):
        super().__init__(x, y, color_06, radius_06, 35, 6, "テキスト")
        pass

class Field():
    def __init__(self, tlx, tly, brx, bry):
        self.tlx = tlx
        self.tly = tly
        self.brx = brx
        self.bry = bry
        self.edge = int(brx - tlx)
        self.step = 7
        self.width = 3
        
        # Start and Stop
        self.rl_start, self.rl_stop = (brx, tly), (brx, bry)
        self.bl_start, self.bl_stop = (tlx, bry), (brx, bry)
        self.ll_start, self.ll_stop = (tlx, tly), (tlx, bry)
        # Create Line
        self.create_line(self.rl_start, self.rl_stop)  # Right
        self.create_line(self.bl_start, self.bl_stop)  # Bottom
        self.create_line(self.ll_start, self.ll_stop)  # Left
    def draw(self):
        # Top Line
        pygame.draw.line(
            display,
            WHE,
            convert_cordinates((self.tlx, self.tly)),
            convert_cordinates((self.tlx, self.tly)),
            self.width
        )
        # Right Line
        pygame.draw.line(
            display,
            WHE,
            convert_cordinates(self.rl_start),
            convert_cordinates(self.rl_stop),
            self.width
        )
        # Bottom Line
        pygame.draw.line(
            display,
            WHE,
            convert_cordinates(self.bl_start),
            convert_cordinates(self.bl_stop),
            self.width
        )
        # Left Line
        pygame.draw.line(
            display,
            WHE,
            convert_cordinates(self.ll_start),
            convert_cordinates(self.ll_stop),
            self.width
        )
    def create_line(self, start, stop):
        body = pymunk.Body(body_type=pymunk.Body.STATIC)
        shape = pymunk.Segment(body, start, stop, self.width)
        shape.elasticity = 0.75
        shape.friction = 0.9
        space.add(shape, body)

def game():
    # Ball
    balls = []
    r = 0
    # フィールド
    tlx, tly = 50, 650
    brx, bry = 550, 300
    field = Field(tlx, tly, brx, bry)
    # Game Start
    while(True):
        
        for event in pygame.event.get():
            if(event.type == pygame.QUIT):
                return
            if(event.type == pygame.MOUSEBUTTONDOWN):

                x, y = convert_cordinates(event.pos)
                r += 1 #rが7以上でバグになります 
                if(r == 1):
                    ball = Ball01(x, y)
                elif(r == 2):
                    ball = Ball02(x, y)
                elif(r == 3):
                    ball = Ball03(x, y)
                elif(r == 4):
                    ball = Ball04(x, y)
                elif(r == 5):
                    ball = Ball05(x, y)
                elif(r == 6):
                    ball = Ball06(x, y)
                balls.append(ball)
        # Fiil background
        
        display.fill(WHITE)
        display.blit(surfaceOne, surfaceOneArea)
        # Draw Ball
        for ball in balls:
            ball.draw()
            

        field.draw()

        # Display Update
        pygame.display.update()
        clock.tick(FPS)
        space.step(1/FPS)

game()
pygame.quit()

```

# 参考
圧倒的感謝！

https://niwakomablog.com/python-free-fall-game-part1/


https://qiita.com/Red-Jersey/items/cf28a8821a8fab17b7cb