- pythonでゲームを作りたい人
- 迷路ゲームのプログラムが欲しい人
こんにちは.けんゆー(@kenyu0501_)です.
最近のpythonの人気は凄いですよね.この人気はおそらく,プログラムが簡単に記述できるだけではなく,ライブラリも豊富だからだと思います.
使用用途も様々で,人工知能に関するプログラムや数値計算,グラフ作成だけではなく,なんと簡単なゲームも作れちゃいます.
おいらも簡単な2次元ゲームですが,こういった迷路ゲームを作成しました.
興味のある方は是非読んでみてください.
迷路ゲームは日経ソフトウェア2019年3月号を参考にして作りました.
迷路ゲームの概要
ルールなどを含めたゲームの概要をざっくりと説明していきます.
【pythonで迷路ゲームの実装】
・迷路のブロックは乱数にて生成
・自分のライフ(Special ability)は壁抜けと敵キャラの遭遇で減る
・プレイヤの壁抜けは一回につき-1ライフ
・敵キャラは10体,動きは乱数,壁のすりぬけがたまに可能
・ライフ0でゲームオーバ
・ゴールするとリトライと辞めるを選択可 pic.twitter.com/JM0CHrSabP— けんゆー@博士課程 (@kenyu0501_) May 13, 2019
- Pythonのpygameといライブラリを用いて実装
- 敵キャラを回避しつつ,ゴールへ向かうという迷路ゲーム
- 自分のライフ(life)は初め5である.
- 壁抜けでライフが-1.敵キャラとの接触でライフ-0.1.
- 壁抜けをすると壁抜けができる.
- 敵キャラは10体.動きは乱数.壁のすり抜けがたまーにできる.
- 迷路のブロックは乱数により生成
- 十字キーで移動
- 「y」で壁抜け(ライフが余っている状態でしかできない)
このような感じのゲームです.
壁のブロックと敵キャラはプログラム上で増やすことができます.
また,壁を抜けた時や,敵と接触した時のライフの減り具合も同様にプログラム上で調整が可能です.
難しくなく,たまにゴールできないくらいの難易度で設定しました.
プログラムや画像データに関して
こちらから迷路ゲームのダウンロードが可能です.
pythonプログラムと画像データが入っています.
zipファイル→ meiro2
もし,試してみたい方がおりましたらどうぞ.
アプリにしてゲーム配布ができたら良いですが,,,,今の所できてません.
もしできるようになったらパッケージにします.
プログラムについて
zipファイルが落とせない人用にプログラムも記述しておきます.
コメントアウトで機能を書いているので,細かい説明は省きます.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 | # -*- coding: utf-8 -*- # maze test import time import numpy as np import pygame WIDTH = 640 HEIGHT = 480 # 480 WHITE = (255, 255, 255) GREEN = (0, 255, 0) BLUE = (0, 0, 255) BLACK = (0, 0, 0) LOAD = (255, 255, 255) NAVY = (0, 0, 128) #pygame初期化 pygame.init() #画面オブジェクトの作成 screen = pygame.display.set_mode((WIDTH, HEIGHT)) font1 = pygame.font.Font(None, 48) font2 = pygame.font.Font(None, 20) myclock = pygame.time.Clock() bgx = 0 #BG offset bgy = 0 #BG offset size = 32 #sprite size # sprite class class Spclass(pygame.sprite.Sprite): # スプライトの初期化関数 def __init__(self, x, y, filename): pygame.sprite.Sprite.__init__(self) # 画像の読み込み self.image = \ pygame.image.load(filename).convert() colorkey = self.image.get_at((0, 0)) # 透明色を設定する self.image.set_colorkey(colorkey) self.x = x self.y = y self.dir = 0 self.walking = 0 self.rect = self.image.get_rect() #プレイヤーのlife(Special Quality) life = 5.0 #壁抜け時の吹き出し用操作変数m hukidashi = 0 # プレイヤー class Player(Spclass): # スプライトの移動処理を行う関数 def update(self): global bgx, bgy, life, hukidashi, endflag x1 = [0, 1, 0, -1] y1 = [-1, 0, 1, 0] if self.walking == 0: newdir = -1 #キーボード入力の判定を行う press = pygame.key.get_pressed() press2 = pygame.key.get_pressed() if press[pygame.K_UP]: newdir = 0 if press[pygame.K_RIGHT]: newdir = 1 if press[pygame.K_DOWN]: newdir = 2 if press[pygame.K_LEFT]: newdir = 3 #hが押された時に発動するコマンド if press[pygame.K_h]: pygame.draw.rect(screen, (125, 125, 0), pygame.Rect(270, 195, 150, 45)) question_1 = \ font1.render("Do you use your special ability?", True, WHITE) screen.blit(question_1, (50, 150)) answer_1 = \ font1.render("y : YES", True, WHITE) screen.blit(answer_1, (280, 200)) answer_2 = \ font1.render("n : No ", True, WHITE) screen.blit(answer_2, (280, 250)) if newdir != -1: hukidashi = 0 newx = int(self.x / size) + x1[newdir] newy = int(self.y / size) + y1[newdir] if bgdata[newy][newx] == "0": self.dir = newdir self.walking = 1 else: if (bgdata[newy][newx] == "1") & (life > 0): if press2[pygame.K_y]: # pygame.draw.rect(screen, (125,125,0), pygame.Rect(270,195,150,45), 2) self.dir = newdir self.walking = 1 life -= 1.0 hukidashi = 1 # elif press2[pygame.K_n]: ## pygame.draw.rect(screen, (125,125,0), pygame.Rect(270,245,150,45), 2) else: self.x += x1[self.dir] * 4 self.y += y1[self.dir] * 4 if hukidashi != 0: commentimage = pygame.image.load("comment1.png").convert() rect_cmimage = commentimage.get_rect().move(self.x, self.y) # cmimage.fill(LOAD) screen.blit(commentimage, rect_cmimage) if (self.x % size) == 0 and (self.y % size) == 0: self.walking = 0 # 画面のスクロール処理 if self.x - bgx < 160: bgx -= 4 if self.x - bgx >= WIDTH - 160: bgx += 4 if self.y - bgy < 160: bgy -= 4 if self.y - bgy >= HEIGHT - 160: bgy += 4 self.rect.left = self.x - bgx self.rect.top = self.y - bgy # どのクラスとぶつかっているかの衝突判定 hitlist = pygame.sprite.spritecollide(self, allgroup, False) #hitlist.pop(0) if len(hitlist) >= 2: for hit in hitlist: if hit == player: continue elif hit == goal: imagetext1 = font1.render("GOAL!", True, GREEN) screen.blit(imagetext1, (260, 150)) btn1image = pygame.image.load("retry1.png").convert() rect_btn1image = btn1image.get_rect().move(180, 200) screen.blit(btn1image, rect_btn1image) imagetext2 = font1.render("or", True, GREEN) screen.blit(imagetext2, (300, 215)) btn2image = pygame.image.load("quit1.png").convert() rect_btn2image = btn2image.get_rect().move(350, 200) screen.blit(btn2image, rect_btn2image) life = 0.0 if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: mouse_x, mouse_y = event.pos if mouse_x >= 180 and mouse_x <= 285 and mouse_y >= 200 and mouse_y <= 250: # for i in range(5): btn1image_2 = pygame.image.load("retry2.png").convert() rect_btn1image_2 = btn1image_2.get_rect().move(180, 200) screen.blit(btn1image_2, rect_btn1image_2) time.sleep(0.02) self.y = size self.x = size life = 5 bgx = -128 bgy = -128 # break elif mouse_x >= 350 and mouse_x <= 455 and mouse_y >= 200 and mouse_y <= 250: btn2image = pygame.image.load("quit1.png").convert() rect_btn2image = btn2image.get_rect().move(350, 200) endflag = 1 print("end") # break elif hit == enemys[0] or hit == enemys[1] or hit == enemys[2] or hit == enemys[3] or hit == enemys[ 4] or hit == enemys[5] or hit == enemys[6] or hit == enemys[7] or hit == enemys[8] or hit == enemys[ 9]: life -= 0.01 question_1 = font2.render("Life : {0:.2f}".format(life), True, WHITE) screen.blit(question_1, (500, 20)) #敵キャラのクラス class Enemy(Spclass): # スプライトの移動処理を行う関数 def update(self): global bgx, bgy x2 = [0, 1, 0, -1] y2 = [-1, 0, 1, 0] if self.walking == 0: newdir = -1 p = np.random.randint(1, 101) if p % 4 == 0: newdir = 0 if p % 4 == 1: newdir = 1 if p % 4 == 2: newdir = 2 if p % 4 == 3: newdir = 3 if newdir != -1: newx = int(self.x / size) + x2[newdir] newy = int(self.y / size) + y2[newdir] if bgdata[newy][newx] == "0": self.dir = newdir self.walking = 1 #ブロックに当たった場合,壁抜けができるかどうかをか確率的にする elif (bgdata[newy][newx] == "1") & (np.random.randint(1, 101) % 5 == 0): self.dir = newdir self.walking = 1 else: self.walking = 0 else: self.x += x2[self.dir] * 4 self.y += y2[self.dir] * 4 if (self.x % size) == 0 and (self.y % size) == 0: self.walking = 0 self.rect.left = self.x - bgx self.rect.top = self.y - bgy #ゴール(終わり)のクラス class Goal(Spclass): def update(self): global bgx, bgy self.rect.left = self.x - bgx self.rect.top = self.y - bgy #迷路を作る関数 def func(l): # 配列かどうかの判定 if isinstance(l, (np.ndarray, list)): return [func(i) for i in l] else: #80以下ならブロックを置かない if l < 70: return 0 else: return 1 def functor(f, l): #配列かどうかの判定 if isinstance(l, (np.ndarray, list)): return [functor(f, i) for i in l] else: return f(l) def join_n(l): #配列の次元数を取得 if np.ndim(l) != 1: return [join_n(i) for i in l] else: return ''.join(l) #迷路のブロックは乱数(0-100)により生成する.8行38列. int_list = np.random.randint(0, 100, (8, 38)) int_list = func(int_list) # print(len(int_list)) int_list[0][0] = 0 int_list[7][37] = 0 # print(int_list) #周囲の壁は2にする array = np.array([[2, 2, 2, 2, 2, 2, 2, 2]]) int_list = np.hstack([array.T, int_list, array.T]) str_list = functor(str, int_list) bgdata_m = join_n(str_list) bgdata_add = np.array(["2222222222222222222222222222222222222222"]) bgdata = np.append(bgdata_add, bgdata_m) bgdata = np.append(bgdata, bgdata_add) blockimage = \ pygame.image.load("grass.png").convert() bgimage = pygame.Surface((size * 40, size * 10)) # ここの数字でブロックの迷路の長さを変更できる bgimage.fill(LOAD) # 迷路を描画する for y in range(10): for x in range(40): if (bgdata[y][x] == "0"): continue bgimage.blit(blockimage, (size * x, size * y)) # スプライト100個をグループに登録する allgroup = pygame.sprite.Group() goal = Goal(size * 38, size * 8, "ken_gf.png") allgroup.add(goal) player = Player(size * 1, size * 1, "ken.png") enemys = [i for i in range(10)] for i in range(10): enemys[i] = Enemy(size * ((i + 1) * 2), size * (i * 0.5), "ken_cg.png") allgroup.add(enemys[i]) allgroup.add(player) endflag = 0 #メインループ while endflag == 0: for event in pygame.event.get(): if event.type == pygame.QUIT: endflag = 1 # ウィンドウを閉じた時の処理 screen.fill(BLACK) # 迷路の表示 screen.blit(bgimage, (-bgx, -bgy)) # スプライトの移動処理 allgroup.update() # time.sleep(0.001) # スプライトの描画処理 allgroup.draw(screen) myclock.tick(45) # ループの周期を1/45秒に設定 pygame.display.flip() # 画面を更新する pygame.quit() |
画像素材たち
欲しかったら使ってください.
この記事を読んでくれた人にオススメの記事です.
この本はこんな人にオススメです Pythonでゲームを作ってみたい人 Pygameを理解したい人 Python…