事前準備
今回は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()
うまくいったらうれしいです。
コメント