100行のPythonのシンプルなゲームコード、Pythonのゲームプログラムのソースコード

皆さんこんにちは, この記事では 100 行の Python のシンプルなゲーム コードに焦点を当てます. Python ゲーム コードで何が使用できるかは, 多くの人が理解したいことです. Python ゲーム プログラムのソース コードを理解したい場合は, を理解する必要がありますまずは以下のことを。

今回は、Python を使用してボールをキャッチしてレンガを打つ小さなゲームを実装します。pygame モジュールをインポートする必要があります。体験の概要は次の 2 つです。

1. 複数の親クラスからの継承 2. 衝突検出の数学モデル

知識ポイントについては後ほど説明しますが、最初にゲームの効果と実装を見てみましょう。

1. ゲーム効果

201905181402364.gif

2. ゲームコード

#インポートモジュール

pygameをインポートする

pygame.locals からインポート *

システム、ランダム、時間、数学をインポートします

クラスGameWindow(オブジェクト):

''ゲーム ウィンドウ クラスの作成''

def __init__(self,*args,**kw):

self.window_length = 600

self.window_wide = 500

#ゲームウィンドウを描画し、ウィンドウサイズを設定する

self.game_window = pygame.display.set_mode((self.window_length,self.window_wide))

#ゲームウィンドウのタイトルを設定する

pygame.display.set_caption("キャッチボールゲーム")

#ゲームウィンドウの背景色のパラメータを定義する

self.window_color = (135,206,250)

デフォルトの背景(自分自身):

#ゲームウィンドウの背景色を描画します

self.game_window.fill(self.window_color)

クラスボール(オブジェクト):

「ボールを作成する」

def __init__(self,*args,**kw):

#ボールの半径、色、移動速度のパラメータを設定します

self.ball_color = (255,215,0)

self.move_x = 1

self.move_y = 1

self.radius = 10

デフボールレディ(自分):

#ボールの初期位置を設定し、

self.ball_x = self.mouse_x

self.ball_y = self.window_wide-self.rect_wide-self.radius

#ボールを描いてリバウンドトリガー条件を設定する

pygame.draw.circle(self.game_window,self.ball_color,(self.ball_x,self.ball_y),self.radius)

デフォルトボールムーブ(自分):

#ボールを描いてリバウンドトリガー条件を設定する

pygame.draw.circle(self.game_window,self.ball_color,(self.ball_x,self.ball_y),self.radius)

self.ball_x += self.move_x

self.ball_y -= self.move_y

#衝突検知機能の呼び出し

self.ball_window()

self.ball_rect()

#ボールを5回捕球するごとに球速が2倍になる

self. distance < self.radius の場合:

自己周波数 += 1

self.frequency == 5の場合:

自己周波数 = 0

self.move_x += self.move_x

self.move_y += self.move_y

自己.ポイント += 自己.ポイント

#ゲーム失敗条件を設定する

self.ball_y > 520の場合:

self.gameover = self.over_font.render("ゲームオーバー",False,(0,0,0))

self.game_window.blit(self.gameover,(100,130))

self.over_sign = 1

クラス Rect(オブジェクト):

「ラケットクラスの作成」

def __init__(self,*args,**kw):

#ラケットの色のパラメータを設定する

self.rect_color = (255,0,0)

self.rect_length = 100

self.rect_wide = 10

defectmove(self):

#マウス位置パラメータを取得する

self.mouse_x,self.mouse_y = pygame.mouse.get_pos()

#ラケットを引いて水平方向の境界を制限する

self.mouse_x >= self.window_length-self.rect_length//2 の場合:

self.mouse_x = self.window_length-self.rect_length//2

self.mouse_x <= self.rect_length//2 の場合:

self.mouse_x = self.rect_length//2

pygame.draw.rect(self.game_window,self.rect_color,((self.mouse_x-self.rect_length//2),(self.window_wide-self.rect_wide),self.rect_length,self.rect_wide))

クラスレンガ(オブジェクト):

def __init__(self,*args,**kw):

#レンガの色のパラメータを設定する

self.brick_color = (139,126,102)

self.brick_list = [[1,1,1,1,1,1],[1,1,1,1,1,1],[1,1,1,1,1,1],[1, 1,1,1,1,1],[1,1,1,1,1,1]]

self.brick_length = 80

self.brick_wide = 20

def tilearrange(self):

range(5) の i の場合:

range(6) の j の場合:

self.brick_x = j*(self.brick_length+24)

self.brick_y = i*(self.brick_wide+20)+40

self.brick_list[i][j] == 1の場合:

#レンガを描く

pygame.draw.rect(self.game_window,self.brick_color,(self.brick_x,self.brick_y,self.brick_length,self.brick_wide))

#衝突検知機能の呼び出し

self.ball_brick()

self. distanceb < self.radius の場合:

self.brick_list[i][j] = 0

自己スコア += 自己ポイント

#ゲームの勝利条件を設定する

if self.brick_list == [[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0],[ 0,0,0,0,0,0],[0,0,0,0,0,0]]:

self.win = self.win_font.render("あなたの勝ち",False,(0,0,0))

self.game_window.blit(self.win,(100,130))

self.win_sign = 1

クラススコア(オブジェクト):

'''分数クラスの作成''

def __init__(self,*args,**kw):

#初期スコアを設定する

自己スコア = 0

#分数フォントを設定する

self.score_font = pygame.font.SysFont('arial',20)

#初回ボーナスポイントを設定する

セルフポイント = 1

#初期のキャッチ数を設定する

自己周波数 = 0

def countscore(self):

#プレイヤーのスコアをプロットする

my_score = self.score_font.render(str(self.score),False,(255,255,255))

self.game_window.blit(my_score,(555,15))

クラスGameOver(オブジェクト):

「ゲームオーバークラスを作成する」

def __init__(self,*args,**kw):

#ゲームオーバーフォントを設定する

self.over_font = pygame.font.SysFont('arial',80)

#GameOver ロゴを定義する

self.over_sign = 0

クラス Win(オブジェクト):

「ゲーム勝利クラスの作成」

def __init__(self,*args,**kw):

#Set You Win フォント

self.win_font = pygame.font.SysFont('arial',80)

#Win ロゴの定義

self.win_sign = 0

クラス衝突(オブジェクト):

「衝突検出クラス」

#ボールとウィンドウ境界間の衝突検出

def ball_window(self):

self.ball_x <= self.radius または self.ball_x >= (self.window_length-self.radius) の場合:

self.move_x = -self.move_x

self.ball_y <= self.radius の場合:

self.move_y = -self.move_y

#ボールとラケットの衝突検知

def ball_rect(自分):

#衝突識別子の定義

self.collision_sign_x = 0

self.collision_sign_y = 0

if self.ball_x < (self.mouse_x-self.rect_length//2):

self.closestpoint_x = self.mouse_x-self.rect_length//2

self.collision_sign_x = 1

elif self.ball_x > (self.mouse_x+self.rect_length//2):

self.closestpoint_x = self.mouse_x+self.rect_length//2

self.collision_sign_x = 2

それ以外:

self.closestpoint_x = self.ball_x

self.collision_sign_x = 3

if self.ball_y < (self.window_wide-self.rect_wide):

self.closestpoint_y = (self.window_wide-self.rect_wide)

self.collision_sign_y = 1

elif self.ball_y > self.window_wide:

self.closestpoint_y = self.window_wide

self.collision_sign_y = 2

それ以外:

self.closestpoint_y = self.ball_y

self.collision_sign_y = 3

#ラケットと円の中心に最も近い点と円の中心の間の距離を定義します

self. distance = math.sqrt(math.pow(self.closestpoint_x-self.ball_x,2)+math.pow(self.closestpoint_y-self.ball_y,2))

#ラケットの左、中上、右上の3つの状況でのボールの衝突検出

self. distance < self.radius かつ self.collision_sign_y == 1 かつ (self.collision_sign_x == 1 または self.collision_sign_x == 2) の場合:

self.collision_sign_x == 1 かつ self.move_x > 0 の場合:

self.move_x = - self.move_x

self.move_y = - self.move_y

self.collision_sign_x == 1 かつ self.move_x < 0 の場合:

self.move_y = - self.move_y

self.collision_sign_x == 2 かつ self.move_x < 0 の場合:

self.move_x = - self.move_x

self.move_y = - self.move_y

self.collision_sign_x == 2 かつ self.move_x > 0 の場合:

self.move_y = - self.move_y

self. distance < self.radius かつ self.collision_sign_y == 1 かつ self.collision_sign_x == 3 の場合:

self.move_y = - self.move_y

#ラケットの左右中央でのボールの衝突検出

self. distance < self.radius および self.collision_sign_y == 3 の場合:

self.move_x = - self.move_x

#ボールとレンガの衝突検出

def ball_brick(自分):

#衝突識別子の定義

self.collision_sign_bx = 0

self.collision_sign_by = 0

self.ball_x < self.brick_x の場合:

self.closestpoint_bx = self.brick_x

self.collision_sign_bx = 1

elif self.ball_x > self.brick_x+self.brick_length:

self.closestpoint_bx = self.brick_x+self.brick_length

self.collision_sign_bx = 2

それ以外:

self.closestpoint_bx = self.ball_x

self.collision_sign_bx = 3

self.ball_y < self.brick_y の場合:

self.closestpoint_by = self.brick_y

self.collision_sign_by = 1

elif self.ball_y > self.brick_y+self.brick_wide:

self.closestpoint_by = self.brick_y+self.brick_wide

self.collision_sign_by = 2

それ以外:

self.closestpoint_by = self.ball_y

self.collision_sign_by = 3

#レンガと円の中心に最も近い点と円の中心の間の距離を定義します

self. distanceb = math.sqrt(math.pow(self.closestpoint_bx-self.ball_x,2)+math.pow(self.closestpoint_by-self.ball_y,2))

#レンガ上の左、中上、右上の3つの状況でのボールの衝突検出

self. distanceb < self.radius かつ self.collision_sign_by == 1 かつ (self.collision_sign_bx == 1 または self.collision_sign_bx == 2) の場合:

self.collision_sign_bx == 1 かつ self.move_x > 0 の場合:

self.move_x = - self.move_x

self.move_y = - self.move_y

self.collision_sign_bx == 1 かつ self.move_x < 0 の場合:

self.move_y = - self.move_y

self.collision_sign_bx == 2 かつ self.move_x < 0 の場合:

self.move_x = - self.move_x

self.move_y = - self.move_y

self.collision_sign_bx == 2 かつ self.move_x > 0 の場合:

self.move_y = - self.move_y

self. distanceb < self.radius および self.collision_sign_by == 1 および self.collision_sign_bx == 3 の場合:

self.move_y = - self.move_y

# レンガの下の左、中央下、右下の 3 つの状況でのボールの衝突検出

self. distanceb < self.radius かつ self.collision_sign_by == 2 かつ (self.collision_sign_bx == 1 または self.collision_sign_bx == 2) の場合:

self.collision_sign_bx == 1 かつ self.move_x > 0 の場合:

self.move_x = - self.move_x

self.move_y = - self.move_y

self.collision_sign_bx == 1 かつ self.move_x < 0 の場合:

self.move_y = - self.move_y

self.collision_sign_bx == 2 かつ self.move_x < 0 の場合:

self.move_x = - self.move_x

self.move_y = - self.move_y

self.collision_sign_bx == 2 かつ self.move_x > 0 の場合:

self.move_y = - self.move_y

self. distanceb < self.radius および self.collision_sign_by == 2 および self.collision_sign_bx == 3 の場合:

self.move_y = - self.move_y

#レンガの左右中央にあるボールの衝突検出

self. distanceb < self.radius および self.collision_sign_by == 3 の場合:

self.move_x = - self.move_x

クラス Main(GameWindow,Rect,Ball,Brick,Collision,Score,Win,GameOver):

''メインプログラムクラスを作成します''

def __init__(self,*args,**kw):

super(Main,self).__init__(*args,**kw)

super(GameWindow,self).__init__(*args,**kw)

super(Rect,self).__init__(*args,**kw)

super(Ball,self).__init__(*args,**kw)

super(Brick,self).__init__(*args,**kw)

super(Collision,self).__init__(*args,**kw)

super(スコア,self).__init__(*args,**kw)

super(Win,self).__init__(*args,**kw)

#ゲーム開始識別子を定義する

スタートサイン = 0

True の場合:

self.backgroud()

self.rectmove()

self.countscore()

self.over_sign == 1 または self.win_sign == 1 の場合:

壊す

#ゲームウィンドウのステータスを取得する

pygame.event.get() のイベントの場合:

イベント.タイプ == pygame.QUITの場合:

sys.exit()

イベントタイプ == マウスボタンダウンの場合:

pressed_array = pygame.mouse.get_pressed()

pressed_array[0]の場合:

スタートサイン = 1

start_sign == 0の場合:

self.ballready()

それ以外:

self.ballmove()

self.brickarrange()

#ゲームウィンドウを更新する

pygame.display.update()

#ゲームウィンドウの更新頻度を制御する

時間.睡眠(0.010)

__name__ == '__main__'の場合:

pygame.init()

pygame.font.init()

キャッチボール = メイン()

3. 知っておきたいポイント 1. 複数の親クラスからの継承

Python の継承方法は深さ優先と幅優先に分かれており、Python2 には古典的なクラスの深さ優先検索の継承方法 (クラス A:) と新しい形式のクラスの幅優先検索の継承方法 (クラス A(オブジェクト):) があります。 Python3 には古典的なクラスがありますが、新形式のクラスの継承方法は python2 の新形式のクラスの継承方法と一致しており、どちらも幅優先の継承方法です。

古典的なクラスの深さ優先検索の継承メソッド:

201905181402365.png

写真が示すように

クラスB(A)

クラスC(A)

クラスD(B,C)

(1) クラスDにコンストラクタがある場合、すべての親クラスの継承を書き換える

(2) クラス D にコンストラクターがなく、クラス B にコンストラクターがある場合、クラス D はクラス B のコンストラクターを継承します。

(3) クラス D にコンストラクタがなく、クラス B にもコンストラクタがない場合、クラス D はクラス C のコンストラクタの代わりにクラス A のコンストラクタを継承します。

(4) クラス D にコンストラクタがなく、クラス B にコンストラクタがなく、クラス A にコンストラクタがない場合、クラス D はクラス C のコンストラクタを継承します。

新しいスタイルのクラスの幅優先検索の継承:

201905181402366.png

写真が示すように

クラスB(A)

クラスC(A)

クラスD(B,C)

(1) クラスDにコンストラクタがある場合、すべての親クラスの継承を書き換える

(2) クラス D にコンストラクターがなく、クラス B にコンストラクターがある場合、クラス D はクラス B のコンストラクターを継承します。

(3) クラス D にコンストラクタがなく、クラス B にもコンストラクタがない場合、クラス D はクラス A のコンストラクタの代わりにクラス C のコンストラクタを継承します。

(4) クラス D にコンストラクタがなく、クラス B にコンストラクタがなく、クラス C にコンストラクタがない場合、クラス D はクラス A のコンストラクタを継承します。

上記の分析を通じて、Python におけるクラスの継承順序については誰もが明確に理解できるはずですが、次に問題は、親クラスのコンストラクターを書き換えたくないが、サブクラスと親クラスの両方のコンストラクターが必要な場合はどうすればよいかということです。効果を発揮するには?この解決策には、直接の親クラス オブジェクトを参照する super キーワードを使用する必要があります。super を使用すると、サブクラスによってオーバーライドされる親クラスのメソッドまたはプロパティにアクセスできます。

クラスA(オブジェクト):

def __init__(self,*args,**kw)

クラスB(A):

def __init__(self,*args,**kw)

super(B,self).__init__(*args,**kw)

クラスC(A):

def __init__(self,*args,**kw)

super(C,self).__init__(*args,**kw)

クラス D(B,C):

def __init__(self,*args,**kw)

super(D,self).__init__(*args,**kw)

super(B,self).__init__(*args,**kw)

2. 衝突検知の数学モデル

実際、プログラミングの問題は最終的には数学の問題です。このゲームには、2D の円と四角形の衝突検出問題が含まれます。

衝突検出の原理: 円の中心に最も近い長方形上の点を見つけ、その点と円の中心の間の距離が円の半径より小さいかどうかを判断します。それより小さい場合は、それは衝突です。

では、円の中心に最も近い長方形上の点を見つけるにはどうすればよいでしょうか? 次に、x 軸方向と y 軸方向からそれぞれ探索します。説明の便宜上、まず次の変数について合意します。

(1) 円の中心に最も近い長方形上の点は変数です: 最も近い点 = [x, y]

(2) 長方形rect = [x, y, l, w] 左上隅と長さ、幅

(3) 円周 = [x, y, r] の中心と半径

201905181402367.png

まず X 軸:

円の中心が長方形の左側にある場合 (circle_x <rect_x の場合)、closestpoint_x = rect_x となります。

円の中心が長方形の右側にある場合 (elif Circle_x > Rect_x + Rect_l)、closestpoint_x = rect_x + rect_l となります。

円の中心が長方形の真上と真下にある場合 (else)、最も近い点_x = 円_x になります。

同様に、y 軸についても次のようになります。

円の中心が長方形の上にある場合 (circle_y <rect_y の場合)、closestpoint_y = rect_y となります。

円の中心が長方形の下にある場合 (elif Circle_y > rect_y + rect_w)、closestpoint_y = rect_y + rect_w となります。

円の中心が長方形の左側と右側にある場合 (else)、最も近いpoint_y = Circle_y となります。

したがって、上記の方法により、円の中心に最も近い長方形上の点を見つけ、「2点間の距離公式」を使用して「最も近い点」と「中心」の間の距離を求めることができます。円の半径」を計算し、最後に円の半径に加算することで、衝突が発生したかどうかを判断できます。

距離=math.sqrt(math.pow(最も近い点_x-circle_x,2)+math.pow(最も近い点_y-円_y,2))

距離 <circle.r の場合:

True を返します �C 衝突が発生しました

それ以外 :

False を返します �C 衝突は発生しませんでした

以上は、編集者が紹介した Python レンガ崩しゲームの詳細な説明と統合です。ご参考になれば幸いです。ご不明な点がございましたら、メッセージを残していただければ、編集者がすぐに返信させていただきます。スクリプト ハウス Web サイトをサポートしてくださった皆様にも感謝いたします。

おすすめ

転載: blog.csdn.net/i_like_cpp/article/details/132128845