事前準備
今回はwindows環境でwindows版pythonをインストールしています。
pythonにはAnaconda版もあります。使用目的によって使い分けます。
そしてpythonでゲームをするにはpygameをインストールします。
コマンドプロントを開いて、
python3 -m pip install pygame
でインストールできます。
素材の準備
今回ブロック崩しを制作するにあたり、こちらの記事を参考にさせていただきました。
ブロックやボールなどの素材は、windows標準のペイントやペイント3Dを使用して作っています。
ダウンロード
ゲームの反響音などは、プログラミングで有名なScratchを使用しました。
こちらの記事を参考にしてください。
ダウンロード
ゲームのバックミュージックも無料で自作しました。
BandLabというアプリを使用しています。
ダウンロード
まずは結果をご覧ください
プログラムや素材の保存場所
プログラムを実行するには、プログラム内で素材の場所などにパスを通す必要があります。
プログラムと素材を同じフォルダーに入れます。
今回はデスクトップにblocksというフォルダーを作りました。

こんな感じです。

このフォルダー内で右クリックし、「ターミナルで開く」を選択。
python block.py
を実行します。
プログラムの名前は何でもいいのですが、pythonは最後に、.pyをつけてください。
実際のプログラム
156行目以下の(r”C:\Users\\Desktop\blocks\hit1.○○○○”)ですが、
先ほど素材やプログラムを格納したフォルダを右クリックして、
パスのコピーをすると簡単です。
それを()内に貼り付けるのですが、先頭にrをつけて””でパスを囲むのを忘れずに。
そして実際には(r”C:\Users\あなたのユーザー名\Desktop\blocks\hit1.wav”)
のようになります。
あとはコピペでも動くと思うのですが・・・
block.py
#coding: utf-8
import pygame
from pygame.locals import *
import math
import sys
import pygame.mixer
# 画面サイズ
GAMEN = Rect(0, 0, 760, 800)# スコアを上部に入れるため、縦を長くした
pygame.display.set_caption("俺のブロック崩し")# pygame左上のタイトル
# パドルのクラス
class Paddle(pygame.sprite.Sprite):
# コンストラクタ(初期化メソッド)
def __init__(self, filename):
pygame.sprite.Sprite.__init__(self, self.containers)
self.image = pygame.image.load(filename).convert()
# 画像サイズをrectで取得する rect.bottom位置の設定
self.rect = self.image.get_rect()
self.rect.bottom = GAMEN.bottom -20 # パドルyの座標
def update(self):
# マウス操作で移動するように設定
self.rect.centerx = pygame.mouse.get_pos()[0]# マウスのx座標をパドルのx座標に
self.rect.clamp_ip(GAMEN) # ゲーム内のみで移動
# ボールのクラス
class Ball(pygame.sprite.Sprite):
# コンストラクタ(初期化メソッド)
def __init__(self, filename, paddle, blocks, score, speed, angle_left, angle_right):
pygame.sprite.Sprite.__init__(self, self.containers)
self.image = pygame.image.load(filename).convert()
self.rect = self.image.get_rect()
self.dx = self.dy = 0 # ボールの速度
self.paddle = paddle # パドルへの参照
self.blocks = blocks # ブロックグループへの参照
self.update = self.start # ゲーム開始状態に更新
self.score = score
self.hit = 0 # 連続でブロックを壊した回数
self.speed = speed # ボールの初期速度
self.angle_left = angle_left # パドルの反射方向(左端135度)
self.angle_right = angle_right # パドルの反射方向(右端45度)
# ゲーム開始状態(マウスを左クリックで、ボールを射出)
def start(self):
# ボールの初期位置(パドルの上)
self.rect.centerx = self.paddle.rect.centerx
self.rect.bottom = self.paddle.rect.top
# 左クリックでボール射出
if pygame.mouse.get_pressed()[0] == 1:
self.dx = 0
self.dy = -self.speed
self.update = self.move
# ボールの挙動
def move(self):
self.rect.centerx += self.dx
self.rect.centery += self.dy
# 壁との反射
if self.rect.left < GAMEN.left: # 左側
self.rect.left = GAMEN.left
self.dx = -self.dx # 速度を反転
self.kabe_sound.play() # 壁の反射音
if self.rect.right > GAMEN.right: # 右側
self.rect.right = GAMEN.right
self.dx = -self.dx # 速度を反転
self.kabe_sound.play() # 壁の反射音
if self.rect.top < GAMEN.top: # 上側
self.rect.top = GAMEN.top
self.dy = -self.dy # 速度を反転
self.kabe_sound.play() # 壁の反射音
# パドルとの反射(左端:135度方向, 右端:45度方向, それ以外:線形補間)
# 2つのspriteが接触しているかどうかの判定
if self.rect.colliderect(self.paddle.rect) and self.dy > 0:
self.hit = 0 # 連続ヒットを0に戻す。
(x1, y1) = (self.paddle.rect.left - self.rect.width, self.angle_left)
(x2, y2) = (self.paddle.rect.right, self.angle_right)
x = self.rect.left # ボールが当たった位置
y = (float(y2-y1)/(x2-x1)) * (x - x1) + y1 # 線形補間
angle = math.radians(y) # 反射角度
self.dx = self.speed * math.cos(angle)
self.dy = -self.speed * math.sin(angle)
self.paddle_sound.play() # 反射音
# ボールを落とした場合
if self.rect.top > GAMEN.bottom:
self.update = self.start # ボールを初期状態に
self.shippai_sound.play()
self.hit = 0
self.score.add_score(-100) # スコア原点(-100)
# ボールと衝突したブロックリストを取得
# (Groupが格納しているSpriteの中から、
# 指定したSpriteと接触しているものを探索)
blocks_collided = pygame.sprite.spritecollide(self, self.blocks, True)
if blocks_collided: # 衝突ブロックがある場合
oldrect = self.rect
for block in blocks_collided:
# ボールが左から衝突
if oldrect.left < block.rect.left < oldrect.right < block.rect.right:
self.rect.right = block.rect.left
self.dx = -self.dx
# ボールが右から衝突
if block.rect.left < oldrect.left < block.rect.right < oldrect.right:
self.rect.left = block.rect.right
self.dx = -self.dx
# ボールが上から衝突
if oldrect.top < block.rect.top < oldrect.bottom < block.rect.bottom:
self.rect.bottom = block.rect.top
self.dy = -self.dy
# ボールが下から衝突
if block.rect.top < oldrect.top < block.rect.bottom < oldrect.bottom:
self.rect.top = block.rect.bottom
self.dy = -self.dy
self.block_sound.play()
self.hit += 1 # 衝突回数
self.score.add_score(self.hit * 10) # 衝突回数に応じてスコア加点
# ブロックのクラス
class Block(pygame.sprite.Sprite):
def __init__(self, filename, x,y):
pygame.sprite.Sprite.__init__(self, self.containers)
self.image = pygame.image.load(filename).convert()
self.rect = self.image.get_rect()
self.rect.left = GAMEN.top + x * self.rect.width
# スコア表示のためブロックを20下げる
self.rect.top = GAMEN.top + 20 + y * self.rect.height
# スコアのクラス
class Score():
def __init__(self, x, y):
# スコアのフォントサイズは40
self.sysfont = pygame.font.SysFont(None, 40)# スコアのフォントサイズは40
self.score = 0
(self.x, self.y) = (x, y)
def draw(self, screen):
# 黄色の文字
img = self.sysfont.render("SCORE:"+str(self.score), True, (255,255,0))
screen.blit(img, (self.x, self.y))
def add_score(self, x):
self.score += x
def main():
pygame.init()
screen = pygame.display.set_mode(GAMEN.size)
# Mixerを初期化(サンプリング周波数を設定)
pygame.mixer.init(frequency = 44100)
# バックグラウンドミュージックのボリューム設定
pygame.mixer.music.set_volume(0.6)
# パドルにボールが衝突した時の効果音取得
Ball.paddle_sound = pygame.mixer.Sound(r"C:\Users\\Desktop\blocks\hit1.wav")
# ブロックにボールが衝突した時の効果音取得
Ball.block_sound = pygame.mixer.Sound(r"C:\Users\\Desktop\blocks\hit2.wav")
# ボールを落とした時の効果音取得
Ball.shippai_sound = pygame.mixer.Sound(r"C:\Users\\Desktop\blocks\shippai.wav")
# 壁に当たった時の効果音取得
Ball.kabe_sound = pygame.mixer.Sound(r"C:\Users\\Desktop\blocks\kabe.wav")
# 画像用のスプライトグループ
group = pygame.sprite.RenderUpdates()
# 衝突判定用のスプライトグループ
blocks = pygame.sprite.Group()
# スプライトグループに追加
Paddle.containers = group
Ball.containers = group
Block.containers = group, blocks
# パドルの作成
paddle = Paddle(r"C:\Users\\Desktop\blocks\paddle.png")
# ブロックの作成(14*10)
for x in range(1, 15):
for y in range(1, 11):
Block(r"C:\Users\\Desktop\blocks\block.png", x, y)
# スコア画面(10, 10)表示
score = Score(10, 10)
# ボールを作成
Ball(r"C:\Users\\Desktop\blocks\ball.png", paddle, blocks, score, 5, 135, 45)
clock = pygame.time.Clock()
while (1):
clock.tick(60) # フレームレート(60fps)
screen.fill((0,20,0))
# すべてのスプライトグループを更新
group.update()
# すべてのスプライトグループを描画
group.draw(screen)
# スコアを描画
score.draw(screen)
# 描画処理を実行
pygame.display.update()
# キーイベント(終了)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN and event.key == K_ESCAPE:
pygame.quit()
sys.exit()
# マウスボタンクリックでバックグラウンドミュージック開始
if event.type == pygame.MOUSEBUTTONDOWN:
pygame.mixer.music.load(r"C:\Users\\Desktop\blocks\gameongaku.wav")
pygame.mixer.music.play(-1)
if len(blocks) == 0:
pygame.mixer.music.stop()
continue
if __name__ == "__main__":
main()
うまくいったらうれしいです。
コメント