Pygameでクラス化してアプリケーションを作る

#pythonとは
システムソフトウェア(組み込み系ソフトウェア)でなければ大体何でもできる汎用性の高い言語。[GUI](https://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%A9%E3%83%95%E3%82%A3%E3%82%AB%E3%83%AB%E3%83%A6%E3%83%BC%E3%82%B6%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9)のアプリケーションや[AI](https://ja.wikipedia.org/wiki/%E4%BA%BA%E5%B7%A5%E7%9F%A5%E8%83%BD)などがとても得意だといわれている。

#クラス化とは
classという雛形を作りインスタンスというリアルな物を作る方法。C++,C#,Java,Pythonなどたくさんの言語で実装されており、見やすくアプリケーションなどを作ることができる。詳しくは[オブジェクト指向](https://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91)を読んでください。

#pygameとは
ビデオゲームを製作するために設計されたクロスプラットフォームのPythonモジュール集であり、Pythonでコンピュータグラフィクスと音声を扱うためのライブラリを含んでいる。pygameは、SDL ライブラリの上に構築されており、C言語のような低水準の機構を使わずにリアルタイムのコンピュータゲームを開発できるようにするための配慮がなされている。これは、計算量の多い関数（主にグラフィクス処理）のほとんどはゲームロジック自体から切り離せるという想定にもとづいており、それがPythonのような高水準言語をゲーム開発に使用することを可能にしている。詳しくは[PYGAME](https://ja.wikipedia.org/wiki/Pygame)を読んでください。
#サンプルスクリプト

```skeleton.pyw
import pygame,main,apng,OpenGL as lse,OpenGL.GL as lily 
from pygame.locals import * 

class CVak:
    #アンダーバー*2でプライベート 
    #__RenderName = None
    #__Scene = None
    #__FULLNESS = (22222,)定数宣言(大文字タプル)アクセスはthis.__FULLNESS[0]

    #コンストラクタ(クラス初期化)
    def __init__(this):#thisの部分はselfやthisといわれるものが一般的
        #Render対象作成
        #exp/this(self).__RenderName = main.CvRender("Data\\name.png",posx,posy)
        #this.__Scene = CvScene()
        pass#何もしないCの様な無名関数は不要<-インタプリタが読み飛ばしてくれる。

    #初期化処理(毎回)
    def init(this):
        return

    #キーの入力時の更新処理
    def UpdDwKey(this,key):
        #if key == K_Up:
        return

    #キーの出力時の更新処理
    def UpdUpKey(this,key):
        return

    #マウス座標取得
    def MousePos(this,x,y):
        return

    #更新処理
    def Update(this):
        return

    #描画処理
    def Draw(this):
        #exp/this.__RenderName.Draw()
        return

    #音楽再生処理pygame.mixer系
    def Music(this):
        return

    #ゲームループ
    def GameLoop(this):
        if(False):#発動しない
            this.init()
        this.Update()
        #スクリーンに色出力
        main.Main.Drawwnd(main.Clist.Red.get())
        this.Draw()
        this.Music()
        pass

    #終了処理
    def finGame(this):
        return
```

```main.pyw
import pygame ,sys,OpenGL as GL
from OpenGL.GL import *
from OpenGL.GLU import *
import skeleton as sk

class Main:
    #静的変数
    #__SCRFLG = ((pygame.OPENGL|pygame.DOUBLEBUF),)3Dが必要な時
    __SCRFLG = (0,)#2D
    __ScreenHeight:int = 810
    __ScreenWidth:int = 931
    __GameFPS:int = 60
    __GameName:str = "Vgame"
    pygame.init()
    __wnd = pygame.display.set_mode((__ScreenWidth,__ScreenHeight),__SCRFLG[0]) 
    pygame.display.set_caption(__GameName)
    pygame.time.Clock()
    __wnd.fill((0,0,255))
    __game = None
        
    def quit():
        Main.__game.finGame()
        pygame.quit()
        sys.exit(None)

    def Eventloop(event):
        if(event.type == pygame.QUIT):
            Main.quit()
        if(event.type == pygame.KEYDOWN):
            if(event.key == pygame.K_ESCAPE):
                Main.quit()
            else:
                Main.__game.UpdDwKey(event.key)
                return
        if(event.type == pygame.KEYUP):
            Main.__game.UpdUpKey(event.key)
        if(event.type == pygame.MOUSEMOTION):
            (x, y) = event.pos
            Main.__game.MousePos(x,y)
        else:
            return

    def GameMain():
        Main.__game = sk.CVak()
        while(True):
            for event in pygame.event.get():
                Main.Eventloop(event)
            Main.__game.GameLoop()
            pygame.display.update()
        return

    def Drawwnd(color):
        Main.__wnd.fill(color)

    def getWndGet():
        return Main.__wnd
        
#main関数
def main():
    Main.GameMain()

class CvRender:
    x:int
    y:int
    path:str
    surf:int

    def __init__(this,path,x,y):
        this.path = path
        this.x = x
        this.y = y
        this.surf = pygame.image.load(this.path).convert_alpha()
    
    def getSizeGet(this):
        return (-this.surf.get_width(),-this.surf.get_height())

    def Draw(this):
        Main.getWndGet().blit(this.surf,(this.x,this.y))
    
    def DrawMiddle(this):
        Main.getWndGet().blit(this.surf,(this.x-this.surf.get_width()/2
                                         ,this.y-this.surf.get_height()/2))

    def CutDraw(this,startx,starty,cutx,cuty):
        Main.getWndGet().blit(this.surf,(this.x,this.y),(startx,starty,cutx,cuty))
    
    def Rev(this,bx,by):
        this.surf = pygame.transform.flip(this.surf,bx,by)

    def Scale(this,sx,sy):
        this.surf = pygame.transform.scale(this.surf,(sx,sy))

    def Rot(this,angle):
        this.surf = pygame.transform.rotate(this.surf.convert(),angle)

class HitsFlg():

    #widthをposzに入れる
    def tri(pos1,pos2,h2):
        if(pos1.posx + pos1.posz <= pos2.posx 
           or pos1.posx >= pos2.posx + pos2.posz):
            return False
        elif(pos2.posy + h2 >= pos1.posy 
             or pos1.posy <= pos2.posy + h2):
            return False
        else:
            return True

    def yen(pos0,pos1):
        posx = pos1.x - pos0.x
        posy = pos1.y - pos0.y
        rad = pos1.z + pos0.z
        if(pow(posx,2) + pow(posy,2) 
           <= pow(rad,2)):
            return True
        else:
            return False
        pass

class CvPos():
    x:int
    y:int
    z:int
    def __init__(this,posx,posy,Btwn):
        this.x = posx
        this.y = posy
        this.z = Btwn

class Cv3DPos():
    pos:CvPos
    size:CvPos

    def __init__(this,posx:int,posy:int,posz:int,sizex = 0,sizey = 0):
        this.pos = (posx,posy,posz)
        this.size = (sizex,sizey,0)
        return 

    def location_in_view(this,adj_x, adj_y):
        """ 3D座標から2D上の座標算出 """
        x2 = int((this.pos.x + adj_x * this.pos.y) / (this.pos.z/10 + 1)) + 200 - int(this.size.x * 0.5 / (this.pos.z/10 + 1))
        y2 = int((this.pos.y + adj_y * this.pos.z) / (this.pos.z/10 + 1)) + 150 - int(this.size.y * 0.5 / (this.pos.z/10 + 1)) 
        return (x2, y2)

    def size_in_view(this):
        """ 3D座標から2D上のサイズ算出 """
        s_x2 = int(this.size.x / (this.pos.z/10 + 1))
        s_y2 = int(this.size.y / (this.pos.z/10 + 1))
        return (s_x2, s_y2)

#色定義
class CvCollor():
    __red:int
    __green:int
    __blue:int
    def __init__(this,r,g,b):
        this.__red = r
        this.__green = g
        this.__blue = b
    def get(this):
        return(this.__red,this.__green,this.__blue) 

#色リスト(自分で好きな色拡張してね)
class Clist():
    #色 = CvCollor(紅, 緑, 青)
    White = CvCollor(255, 255, 255)
    Black = CvCollor(0, 0, 0)
    Green = CvCollor(0, 255, 0)
    Blue = CvCollor(0, 0, 255)
    Red = CvCollor(255, 0, 0) 
    Yellow = CvCollor(255, 255, 0)
    Purple = CvCollor(255, 0, 255)
    Skyblue = CvCollor(0, 255, 255)
    Orange = CvCollor(255, 180, 105)
    Blown = CvCollor(165, 42, 42)
    Pink = CvCollor(255, 0, 165)
    Silver = CvCollor(192, 192, 192)
    Lime = CvCollor(50, 205, 50)
    Virid = CvCollor(0, 137, 107)
    Coblue = CvCollor(0, 71, 171)
    Dblown = CvCollor(81, 31, 9)
    Greeny = CvCollor(17, 69, 20)

class Cvmoveflg():
    up:bool
    down:bool
    left:bool
    right:bool
    def __init__(this,upflg,dwflg,ltflg,rtflg):
        this.up = upflg
        this.down = dwflg
        this.left = ltflg
        this.right = rtflg

class CvFont():
    font:int
    collor:CvCollor
    def __init__(this,name,size,collor):
        this.font = pygame.font.Font(name,size)
        this.collor = collor

    def UpdColor(this,collor):
        this.collor = collor

    def show(this,string,sd,x,y):
        Main.getWndGet().blit(this.font.render(string,sd,this.collor.get()),(x,y))

    def bcshow(this,string,sd,bc,x,y):
        Main.getWndGet().blit(this.font.render(string,sd,this.collor.get(),bc.get()),(x,y))

    def Font(this,collor):
        this.collor = collor
        
if __name__ == "__main__":
    main()


```
#これを丸々コピペすると
x=931,y=810のタイトル"vgame"の赤い画面が出てくると思う。これから作成していくと楽に音楽付きのアプリケーションやゲームなんかも作れますよ。プログラム初心者はコピペすることをお勧めします。今からプログラムを始めてください。アプリケーションを作るスクリプトが出来上がれば次を読んでください。

#アプリケーション化の手っ取り早い方法
cmd.exeを開き

```
[cmd.exeパス]>> cd [pipのパス]
[pipのパス]>> pip install pyinstaller
```

と打つ
pyinstallerなどが有名まず最初にpyinstaller.exeを目的のアプリケーションのパスにコピー
cmd.exeを開き

```
[cmd.exeパス]>> cd [目的のアプリケーションのパス(以下G)]
```
と打ち,

```
[G]>> pyinstaller [main.pywから名前を変えたもの].pyw [skeleton.pywから名前を変えたもの].pyw --onefile --noconsole (--exclude pandas --exclude numpy)
```

と打つ
そうすると[main.pywから名前を変えたもの].specができていると思うので、aのexcludesの項目に"pygame"を追加

```py
a.datas += Tree("[Pythonのパス]/Lib/site-packages/pygame/", prefix= "pygame")
a.datas += Tree("[Pythonのパス]/lib/xml/", prefix= "xml")
```

`__pycache__`やbuildやdistのフォルダを消した後cmd.exeに戻り

```
[G]>> pyinstaller [main.pywから名前を変えたもの].spec [skeleton.pywから名前を変えたもの].spec
```

と打つと外部データを読み込んでいなければdist下のexeは起動が成功する。読み込んでいた場合、distの上に持っていくと成功する。

#最後に
PyOpenGLを使ってみたい。それでもたくさん記事を書いてみたい。