質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

5187閲覧

pythonのpygameでのゲーム作成について プログラムが応答しなくなります

kou_

総合スコア8

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2018/05/04 18:53

編集2018/05/05 13:07

orb.png
orb.png
player1.png
player1.png
player2.png
player2.png
grass.png および water.png の入手先

前提・実現したいこと

現在、pythonでpygameモジュールを用いてミニゲームを作成しているのですが、
ある状況下でプログラムが応答しなくなってしまいます。
この原因の究明が出来なかったので、分かる方に原因と解決策をご教示いただきたいです。

発生している問題・エラーメッセージ

以下のソースコードを実行し、スペースキー押下でゲーム開始→プレイヤーを衝突させてゲームが終了→タイトル画面に戻る→手順の初めに戻る、という手順を2ゲーム目まで行い、3ゲーム目開始時のスペースキー押下でプログラムが応答しなくなってしまいます。

該当のソースコード

python

1import pygame 2from pygame.locals import * 3import random 4import copy 5import sys 6import os 7 8SCREEN_WIDTH_SIZE = 608 9SCREEN_HEIGHT_SIZE = 480 10 11MSIZE = 32 # 1マスの大きさ 12 13LEFT, DOWN, RIGHT, UP = 3, 2, 1, 0 14 15TITLE, GAME, RESULT = 4, 5, 6 16 17class Game_Title: # タイトル画面の処理 18 def __init__(self): 19 self.titlefont = pygame.font.SysFont(None, 50) 20 self.startfont = pygame.font.SysFont(None, 30) 21 self.title_x, self.title_y = 202, 160 22 self.start_x, self.start_y = 204, 400 23 self.start_flame = 0 24 self.start_flag = False 25 self.finish = False 26 27 def update(self): 28 if self.start_flag: 29 self.start_flame += 1 30 if self.start_flame == 9000: # スペースキー押下後、ある程度テキスト点滅したらタイトル画面は終了 31 self.finish = True 32 33 def draw(self, screen): 34 title = self.titlefont.render("Orb Fighters", True, (255, 255, 255)) 35 start = self.startfont.render("Press Space to start", True, (255, 255, 255)) 36 screen.blit(title, (self.title_x, self.title_y)) 37 if self.start_flag: 38 if self.start_flame % 2000 < 1000: # スペースキーが押されたら押されたことをテキストの点滅で知らせる 39 screen.blit(start, (self.start_x, self.start_y)) 40 else: 41 screen.blit(start, (self.start_x, self.start_y)) 42 43 44class Player(pygame.sprite.Sprite): # プレイヤークラス 45 animcycle = 20 # アニメーション速度 46 frame = 0 # アニメーションのフレーム 47 target_x, target_y = -1, -1 # 移動時の移動先マスのx, y座標 48 move_flag = False # グリッド間の移動判定用フラグ 49 has_orbs = 0 # オーブ所持数 50 result = "" # 勝者か敗者か 51 52 def __init__(self, filename, pos_x, pos_y, direction, player): # プレイヤーオブジェクトの初期化処理 53 pygame.sprite.Sprite.__init__(self, self.containers) 54 self.direction = direction 55 self.pos_x, self.pos_y = pos_x, pos_y 56 self.target_x, self.target_y = pos_x * MSIZE, pos_y * MSIZE 57 self.images = split_chara_image(load_image(filename)) 58 self.image = self.images[self.direction][1] 59 self.rect = self.image.get_rect(topleft=(pos_x*MSIZE, pos_y*MSIZE)) 60 self.other_player = player 61 62 def update(self, map): 63 # キャラクターアニメーションおよびオーブ獲得数の更新 64 self.frame += 1 65 self.image = self.images[self.direction][int(self.frame / self.animcycle) % 3] # 20フレーム毎に足踏み 66 if self.move_flag: 67 if self.rect.x < self.target_x: 68 self.rect.x += 1 69 if self.rect.y > self.target_y: 70 self.rect.y -= 1 71 if self.rect.x > self.target_x: 72 self.rect.x -= 1 73 if self.rect.y < self.target_y: 74 self.rect.y += 1 75 if self.rect.x == self.target_x and self.rect.y == self.target_y: 76 self.move_flag = False 77 self.pos_x, self.pos_y = int(self.rect.x / MSIZE), int(self.rect.y / MSIZE) 78 self.get_orb(map) 79 80 def draw(self, screen): # キャラの描写 81 screen.blit(self.image, self.rect) 82 83 def move(self, dir, map): # キャラのグリッド移動 84 85 if self.rect.x == self.target_x and self.rect.y == self.target_y: 86 if dir == LEFT: 87 self.direction = LEFT 88 if map.map[self.pos_y][self.pos_x - 1] == 0: 89 self.move_flag = True 90 self.target_x -= MSIZE 91 if dir == DOWN: 92 self.direction = DOWN 93 if map.map[self.pos_y + 1][self.pos_x] == 0: 94 self.move_flag = True 95 self.target_y += MSIZE 96 if dir == RIGHT: 97 self.direction = RIGHT 98 if map.map[self.pos_y][self.pos_x + 1] == 0: 99 self.move_flag = True 100 self.target_x += MSIZE 101 if dir == UP: 102 self.direction = UP 103 if map.map[self.pos_y - 1][self.pos_x] == 0: 104 self.move_flag = True 105 self.target_y -= MSIZE 106 if self.collision_player(): 107 self.game_set() 108 109 def get_orb(self, map): # 移動してきたマスにオーブがあれば獲得 110 if not self.move_flag: 111 if map.orb_map[self.pos_y][self.pos_x] == 0: 112 map.orb_map[self.pos_y][self.pos_x] = 1 113 self.has_orbs += 1 114 115 def collision_player(self): # プレイヤー同士の衝突判定 116 if self.other_player is None: 117 pass 118 else: 119 if self.direction == LEFT: 120 if self.pos_y == self.other_player.pos_y and self.pos_x - 1 == self.other_player.pos_x: 121 return True 122 else: 123 return False 124 if self.direction == DOWN: 125 if self.pos_y + 1 == self.other_player.pos_y and self.pos_x == self.other_player.pos_x: 126 return True 127 else: 128 return False 129 if self.direction == RIGHT: 130 if self.pos_y == self.other_player.pos_y and self.pos_x + 1 == self.other_player.pos_x: 131 return True 132 else: 133 return False 134 if self.direction == UP: 135 if self.pos_y - 1 == self.other_player.pos_y and self.pos_x == self.other_player.pos_x: 136 return True 137 else: 138 return False 139 140 def game_set(self): # ゲームの勝敗がついたとき 141 if self.has_orbs > self.other_player.has_orbs: 142 self.result += "WINNER" 143 self.other_player.result += "LOSER" 144 elif self.has_orbs < self.other_player.has_orbs: 145 self.result += "LOSER" 146 self.other_player.result += "WINNER" 147 else: 148 self.result += "DRAW" 149 self.other_player.result += "DRAW" 150 151 152class Text_Orbs: # プレイヤーのオーブ所持数のテキスト 153 def __init__(self, player, map): 154 self.sysfont = pygame.font.SysFont(None, 25) 155 self.player = player 156 if player.pos_x == 1 and player.pos_y == 1: 157 self.x, self.y = (player.pos_x - 1) * MSIZE, (player.pos_y - 1) * MSIZE 158 elif player.pos_x == map.col - 2 and player.pos_y == map.row - 2: 159 self.x, self.y = (map.col - 5) * MSIZE, (map.row - 1) * MSIZE 160 161 def draw(self, screen): 162 text = self.sysfont.render("You got " + str(self.player.has_orbs) + " orbs.", True, (255,140,0)) 163 screen.blit(text, (self.x, self.y)) 164 165 166 167 168# 以下掲載しきれないので追記します

試したこと

生成していたオブジェクトをdel文で削除し、ガベージコレクトで解放したメモリの回収を行ってみましたが、相変わらず問題は改善しませんでした。

補足情報(FW/ツールのバージョンなど)

python 3.2
pygame 1.9.2pre

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

umyu

2018/05/04 20:16

grass.png orb.png water.png player1.png player2.pngのファイルがないため、実行しても実行エラーになります。
kou_

2018/05/05 04:10

加工等で作成した画像の添付と、原物の画像が提示された入手先のリンクの追加を行わせていただきました。引き続き、よろしければお願い致します。
guest

回答2

0

ベストアンサー

400行に渡る力作ソースですね。。
問題の再現手順はゲームスタート→ゲームプレイ→オーブを全部取得で次のゲームを2回という手順でいいですか?

結果→手元の環境では再現しませんでした。
python 3.6.5
pygame 1, 9, 3
OS:Windows 10

コードを見て気になった点を指摘します。
a,Playerクラスのgame_set関数の処理はプレイヤーが衝突時に無限に文字列を加算(result)するので、メモリが枯渇する可能性があるのでまずいのではないでしょうか?

Python

1 def game_set(self): # ゲームの勝敗がついたとき 2 if self.has_orbs > self.other_player.has_orbs: 3 self.result += "WINNER" 4 self.other_player.result += "LOSER" 5 elif self.has_orbs < self.other_player.has_orbs: 6 self.result += "LOSER" 7 self.other_player.result += "WINNER" 8 else: 9 self.result += "DRAW" 10 self.other_player.result += "DRAW"

Playerクラスに情報を持たせずに、Judgeクラスを作成してそちらで勝敗を管理する方がよいと思います。

b,2重ループの処理はitertools.productが使えます。
c,コード内に移動方向に対応する加減算処理が多いので、移動方向(ベクトル)を表すdirectionsを作成してみてはー。

Python

1 directions = {LEFT: (0, -1), DOWN: (1, 0), RIGHT: (0, +1), UP: (-1, 0)} 2 print(directions) 3

コード修正する作業はバグを入れやすいので、テストロジックやPyCharmを使用しているなら、
メニューのバージョン管理→Local History機能を使って修正点を確認しなが作業するのをオススメします。


以下は憶測です。
反応がなくなるという特微から無限ループになっているのではと予想しました。
作成されたゲームで、無限ループになりそうな箇所のはMapクラスのgenerate_map
while (wall_flag)の判定とwhile(plus_land_yet)の判定です。
1,whileが確実に抜ける事を確認してくださいな。
2,オーブを全部取得したら、次のMAP生成のためにgenerate_mapが呼ばれますが、プレイヤーがいる位置を生成時に考慮していないように見受けられます。

画像で見ていただいた方が分かりやすいと思うので、これだとPlayer2が動けないMAPを生成してます。
イメージ説明

title関数 -> main関数 -> (2回目のプレイ)title関数 -> main関数この時
map.generate_map() # ランダムマップ生成
map.generate_orb_map() # 生成したマップをもとにオーブを配置
が呼ばれるのでは?


map.generate_map() の次行にprint('generate_map')を追加して確認してみましたが、
表示されないことからmap.generate_map()の処理で無限ループになってますね。
キーボードが反応しない原因はこれですね。
まず2重ループはやめて、itertools#productを使ったループにしてください。

Python

1from itertools import product 2for i, j in product(range(self.row), range(self.col)):

こうすることでループのネストが1段減ります。

次にcontinue文を使う事で、ネストを一段へらします。

Python

1 for i, j in product(range(self.row), range(self.col)): 2 print(i, j) # printでiとjの値を表示する。(デバック用) 3 wall_flag = True 4 if i == 0 or i == self.row - 1 or j == 0 or j == self.col - 1 or self.map[i][j] == 0: 5 continue 6 if i == 2 and j % 2 == 0 and self.map[i][j] == 1: 7 while (wall_flag): 8 direction = random.randint(0, 100) % 4

でこれで実行してみると
4 12の出力で止まるので、5行目13列で問題が発生して無限ループになったことが分かります。
止まる出力メッセージは質問者様の環境で違うはずです。
ポイントはprintの出力がMAPの最後の行と列まで出力されていないので、無限ループになっているという事が確定したことです。

< まとめ >
原因:無限ループによってキーボードの入力を受付なかった。
発生条件:map.generate_map関数のwall_flagがFalseにならない。


generate_map関数の
1,direction = random.randint(0, 100) % 4の方の
if direction == UP:wall_flag = Falseの設定がないです。
2,direction = random.randint(0, 100) % 3で生成される値は0~2ですが、
LEFT, DOWN, RIGHT, UP = 3, 2, 1, 0で定義されているので。
IF文で判定しているのはRIGHT:1,DOWN:2,LEFT:3です。
生成している乱数源が正しくないかと。

そもそも論としてこのwhile wall_flagは不要なのでは?
迷路生成(棒倒し法)でググって出てきたページを見る限りでもiとjだけで実装できると思いますが。


原因:maporb_maporb_map_checkrowcolの変数がクラス変数で宣言されていたため。
MAP情報が2回目以降初期化されていなかった。以下のコードで前回のMAPデータが表示されるのが分かると思います。

Python

1 def generate_map(self): 2 from pprint import PrettyPrinter 3 pp = PrettyPrinter() 4 pp.pprint(Map.map) 5

そのため2回目以降のgenerate_map関数が条件によって無限ループになった。
◇条件
行が4以上で2の倍数かつ2の倍数列で周りの4マスが全部オーブを取得した(Map情報を1にした)。
この時、wall_flagFalseにならず無限ループとなる。
◇対策方法
インスタンス変数にしてくださいな。あと以下の行も忘れずに
self.row = len(self.map)
self.col = len(self.map[0])
最後に変数名mapとクラス名Mapは標準の命名とかぶるため、list/mapなどは避けて
BoardやFieldかMapDataなどの名前に変更することをオススメいたします。


解決してよかったです。
最初は誰でもそーいうものなのです。
あんまりデバックしていないですが、コードを置いておきます
ご参考まで。

Python

1from itertools import product 2DIRECTIONS = {LEFT: (0, -1), DOWN: (1, 0), RIGHT: (0, +1), UP: (-1, 0)} 3# ↑Game_Titleの前に宣言 4 def generate_map(self): # マップ生成 5 from pprint import PrettyPrinter 6 pp = PrettyPrinter() 7 pp.pprint(Map.map) 8 # まず棒倒し法で迷路生成 9 START_ROW = 2 10 for i, j in product(range(START_ROW, self.row - 2, 2), range(2, self.col - 2, 2)): 11 data = [LEFT, DOWN, RIGHT] 12 # 最初の行は上にも倒せる。 13 if i == START_ROW: 14 data.append(UP) 15 random.shuffle(data) 16 while len(data) > 0: 17 direction = data.pop(0) 18 px, py = [x + y for (x, y) in zip([i, j], DIRECTIONS[direction])] 19 if self.map[px][py] == 0: 20 self.map[px][py] = 1 21 break 22

投稿2018/05/05 09:36

編集2018/05/05 17:55
umyu

総合スコア5846

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kou_

2018/05/05 10:31

ご回答ありがとうございます。 問題の再現手順についてですが、読み返してみると書き方が悪かったように思えました、申し訳ありません。 起こった問題についてですが、スペースキー押下でゲーム開始→プレイヤーを衝突させてゲームが終了→タイトル画面に戻る→手順の初めに戻る、という手順を2ゲーム目まで行い、3ゲーム目開始時のスペースキー押下でプログラムが応答しなくなってしまいます。 何度もプログラムを実行してみたのですが、応答しなくなるのが決まって2ゲームが終了した後に、3ゲーム目の始めでスペースキーを押下した瞬間、ということは確認できました。 問題に関しまして、引き続きアドバイスいただけると助かります。よろしくお願いいたします。 また、コードに関してあまりスッキリしていないと感じておりましたので、a, b, c のアドバイスをもとにコードの改良も行ってみようと考えております。アドバイスありがとうございます。 最後に憶測の2に関して、関数の命名の仕方がややこしくて申し訳ないのですが、オーブを全て取得時に呼び出される関数が generate_orb_map で、こちらはマップ情報をもとにオーブを再配置する関数となっており、マップ自体を作り替えることはないので恐らくこちらで問題は起こらないかと考えております。
umyu

2018/05/05 12:07

>kou_さんへ 質問文の再現手順をコメントしていただいた内容に修正していただいても宜しいでしょうか。 コメントの手順で問題が再現したので、デバックしてみますねー。
kou_

2018/05/05 13:12

>umyu様 ご指摘ありがとうございます。質問の再現手順の部分、修正させていただきました。 マップ生成の件ですが、現在のプログラムでのマップ生成だと、稀にプレイヤー2の動けないマップを生成してしまう可能性のあるプログラムとなってしまっていることが確認出来ていましたので、ゲームの骨格が出来上がり次第、修正を考える予定でした。こちらに関してもご指摘いただき感謝申し上げます。
kou_

2018/05/05 17:25

>umyu様 まとめ の1に関して、棒倒し法の1段目以外の核となる部分のUP以外に棒を倒す、という部分を先に書いて、コピーアンドペーストで1段目の処理も作ってしまったため、その際にwall_flagの更新を書くことを忘れてしまっていました。 次に2に関して、初めに方向を示す定数を定義する際に、 LEFT, DOWN, RIGHT, UP = 0, 1, 2, 3 と定義していたところを、後に現在の形に書き換えてしまっていたために生成した乱数値が条件文の条件から外れてしまう、ということが起きてしまっておりました。 また、wall_flagを使用していたことに関して、生成した乱数方向に既に棒を倒し壁が立っていた場合に、壁は立たないのでもう一度while文を回す必要がある…と考えて壁を立てている、という意味でのフラグwall_flagを作ったつもりでした。 しかし、ご指摘いただき気づきましたが、確かにフラグを使わずとも棒を倒した瞬間にbreak文にてループを抜け出せば良い話でした。 さらに、Mapクラスの変数としていたマップのデータ map 、その他のクラス変数の未初期化の件について、自分の今までの解釈では、main関数で map = Map() として呼び出した時点で変数も初期化されている、と勘違いしていたのが原因でした。 他のクラス同様にMapクラスにも__init__メソッドを実装し、毎回クラス変数を全て初期化出来るように書き換えたところ、何度か試した限りでは無限ループには陥らなくなりました。 最後に、ループの深さを減らす方法について、とても参考になる手法でしたので、今後のプログラミング練習にも活かしたいと思います。また、Mapなどの名称が標準にあるため、他の標準と被らないように命名する旨、参考にさせていただき、この後に修正させていただこうと考えております。 まだまだ拙いプログラミング力ですが、今回の件で得たものを今後に活かして、さらに力を磨いていけるよう頑張りたいと思います。 長々とお時間を取らせてしまい、申し訳ありませんでした。丁寧に対応いただきとても助かりました、心より感謝申し上げます。
kou_

2018/05/05 18:06

>umyu様 コードサンプルの掲載、ありがとうございます。 randomモジュールのshuffle関数など、初めて見る手法が様々見られるので、とても勉強になります。 こちらのコードを参考にリファレンスなども調べつつ、より綺麗なコーディングに仕上げていけるように頑張りたいと思います。
guest

0

ソースコードの追記

python

1class Map: # マップクラス 2 3 # mapは 0が陸地, 1が水 orb_map,orb_map_checkは 0がオーブが残っており, 1がオーブがなくなっている(もしくは元からない) 4 map = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 5 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 6 [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], 7 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 8 [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], 9 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 10 [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], 11 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 12 [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], 13 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 14 [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], 15 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 16 [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], 17 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 18 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] 19 orb_map = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 20 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 21 [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], 22 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 23 [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], 24 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 25 [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], 26 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 27 [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], 28 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 29 [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], 30 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 31 [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], 32 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 33 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] 34 orb_map_check = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 35 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 36 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 37 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 38 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 39 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 40 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 41 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 42 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 43 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 44 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 45 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 46 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 47 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 48 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] 49 row, col = len(map), len(map[0]) # マップの行数,列数を取得 50 imgs = [None] * 256 # マップチップ 51 orb_img = None 52 direction = -1 53 54 # マップの描画 55 def draw(self, screen): 56 for i in range(self.row): 57 for j in range(self.col): 58 screen.blit(self.imgs[self.map[i][j]], (j * MSIZE, i * MSIZE)) 59 if self.orb_map[i][j] == 0: 60 screen.blit(self.orb_img, (j * MSIZE, i * MSIZE)) 61 62 def generate_map(self): # マップ生成 63 for i in range(self.row): # まず棒倒し法で迷路生成 64 for j in range(self.col): 65 wall_flag = True 66 if i == 0 or i == self.row - 1 or j == 0 or j == self.col - 1 or self.map[i][j] == 0: 67 pass 68 elif i == 2 and j % 2 == 0 and self.map[i][j] == 1: 69 while (wall_flag): 70 direction = random.randint(0, 100) % 4 71 if direction == RIGHT: 72 if self.map[i][j + 1] == 0: 73 self.map[i][j + 1] = 1 74 wall_flag = False 75 if direction == DOWN: 76 if self.map[i + 1][j] == 0: 77 self.map[i + 1][j] = 1 78 wall_flag = False 79 if direction == LEFT: 80 if self.map[i][j - 1] == 0: 81 self.map[i][j - 1] = 1 82 wall_flag = False 83 if direction == UP: 84 if self.map[i - 1][j] == 0: 85 self.map[i - 1][j] = 1 86 elif i % 2 == 0 and j % 2 == 0 and self.map[i][j] == 1: 87 while(wall_flag): 88 direction = random.randint(0, 100) % 3 89 if direction == RIGHT: 90 if self.map[i][j + 1] == 0: 91 self.map[i][j + 1] = 1 92 wall_flag = False 93 if direction == DOWN: 94 if self.map[i + 1][j] == 0: 95 self.map[i + 1][j] = 1 96 wall_flag = False 97 if direction == LEFT: 98 if self.map[i][j - 1] == 0: 99 self.map[i][j - 1] = 1 100 wall_flag = False 101 for i in range(self.row): # 生成した迷路の陸地をランダムでつなげて回路づくり 102 for j in range(self.col): 103 if i == 0 or i == self.row - 1 or j == 0 or j == self.col - 1: 104 pass 105 else: 106 if self.map[i][j] == 1: 107 create_land = random.randint(0, 100) % 4 108 if create_land == 0: 109 self.map[i][j] = 0 110 if self.map[i][j] == 0: 111 plus_land_yet = True 112 count = 0 113 water = [False, False, False, False] 114 if self.map[i - 1][j] == 1: 115 count += 1 116 water[UP] = True 117 if self.map[i][j - 1] == 1: 118 count += 1 119 water[LEFT] = True 120 if self.map[i + 1][j] == 1: 121 count += 1 122 water[DOWN] = True 123 if self.map[i][j + 1] == 1: 124 count += 1 125 water[RIGHT] = True 126 # 生成した陸地がどの陸地とも陸続きでないとき、どこかと陸続きにする 127 if count >= 3: # == 4 だと直線の浮島ができる >= 3 だと枠ギリギリまで陸が出来てしまう 128 while(plus_land_yet): 129 plus_land = random.randint(0, 100) % 4 130 if plus_land == UP and water[UP] and i - 1 != 0: 131 self.map[i - 1][j] = 0 132 plus_land_yet = False 133 elif plus_land == LEFT and water[LEFT] and j - 1 != 0: 134 self.map[i][j - 1] = 0 135 plus_land_yet = False 136 elif plus_land == DOWN and water[DOWN] and i + 1 != self.row - 2: 137 self.map[i + 1][j] = 0 138 plus_land_yet = False 139 elif plus_land == RIGHT and water[RIGHT] and j + 1 != self.col -2: 140 self.map[i][j + 1] = 0 141 plus_land_yet = False 142 # count(陸地が隣接する水辺の数) >= 3 で枠ギリギリに陸が出来ないように修正 143 if i == 1: 144 self.map[i - 1][j] = 1 145 if i == self.row - 2: 146 self.map[i + 1][j] = 1 147 if j == 1: 148 self.map[i][j - 1] = 1 149 if j == self.col - 2: 150 self.map[i][j + 1] = 1 151 152 def generate_orb_map(self): # どこにオーブがあるかのマップデータ 153 self.orb_map = copy.deepcopy(self.map) 154 self.orb_map[1][1] = 1 155 self.orb_map[self.row - 2][self.col - 2] = 1 156 157 def check_orb_is_empty(self): # マップ上にオーブがなくなったかの判定 158 if self.orb_map == self.orb_map_check: 159 return True 160 else: 161 return False 162

投稿2018/05/04 18:55

kou_

総合スコア8

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kou_

2018/05/04 18:58

# 上記に続きさらに追記です def load_image(filename, colorkey=None): # 画像データの読み込み filepath = os.path.join(os.getcwd(), filename) image = pygame.image.load(filepath) # この出来上がった方のimageはSurfaceオブジェクト image = image.convert() if colorkey is not None: if colorkey is -1: colorkey = image.get_at((0,0)) image.set_colorkey(colorkey, RLEACCEL) return image def split_chara_image(image): # プレイヤーキャラの画像を切り抜きリストに image_list = [] chara_size = 32 for i in range(0, 128, chara_size): tmp_list = [] for j in range(0, 96, chara_size): surface = pygame.Surface((chara_size, chara_size)) surface.blit(image, (0, 0), (j, i, chara_size, chara_size)) surface.set_colorkey(surface.get_at((0, 0)), RLEACCEL) surface.convert() tmp_list.append(surface) image_list.append(tmp_list) return image_list def title(screen): # タイトル画面の処理 game_title = Game_Title() # ゲームタイトルオブジェクトの生成 while True: screen.fill((0, 0, 0)) game_title.update() game_title.draw(screen) pygame.display.update() for event in pygame.event.get(): # イベント処理 if event.type == QUIT: # 閉じるボタンが押されると終了 pygame.quit() sys.exit() if event.type == KEYDOWN and event.key == K_ESCAPE: # エスケープキーでも終了 pygame.quit() sys.exit() if event.type == KEYDOWN and event.key == K_SPACE and not game_title.start_flag: # スペースキーでスタート game_title.start_flag = True break if game_title.finish: break def main(screen): # ゲーム中の処理 maptips = ["grass.png", "water.png"] Map.imgs[0] = load_image(maptips[0]) Map.imgs[1] = load_image(maptips[1]) Map.orb_img = load_image("orb.png", -1) map = Map() map.generate_map() # ランダムマップ生成 map.generate_orb_map() # 生成したマップをもとにオーブを配置 all = pygame.sprite.RenderUpdates() # スプライトをまとめて扱う Player.containers = all player1 = Player("player1.png", 1, 1, DOWN, None) player2 = Player("player2.png", 17, 13, UP, player1) player1.other_player = player2 player1_score = Text_Orbs(player1, map) player2_score = Text_Orbs(player2, map) clock = pygame.time.Clock() while True: clock.tick(60) all.update(map) map.draw(screen) all.draw(screen) player1_score.draw(screen) player2_score.draw(screen) if map.check_orb_is_empty(): map.generate_orb_map() pygame.display.update() pressed_key = pygame.key.get_pressed() # get_pressed()だと長押し判定が可能 if pressed_key[K_LEFT]: player1.move(LEFT, map) if pressed_key[K_DOWN]: player1.move(DOWN, map) if pressed_key[K_RIGHT]: player1.move(RIGHT, map) if pressed_key[K_UP]: player1.move(UP, map) if pressed_key[K_a]: player2.move(LEFT, map) if pressed_key[K_s]: player2.move(DOWN, map) if pressed_key[K_d]: player2.move(RIGHT, map) if pressed_key[K_w]: player2.move(UP, map) for event in pygame.event.get(): # イベント処理 if event.type == QUIT: # 閉じるボタンが押されると終了 pygame.quit() sys.exit() if event.type == KEYDOWN and event.key == K_ESCAPE: # エスケープキーでも終了 pygame.quit() sys.exit() if player1.result != "": # ゲームの勝敗がついていたらリザルト print("Player1 is " + player1.result + ", Player2 is " + player2.result) break if __name__ == "__main__": while True: pygame.init() # 初期化 screen = pygame.display.set_mode((SCREEN_WIDTH_SIZE, SCREEN_HEIGHT_SIZE)) # 描写スクリーンの準備 pygame.display.set_caption("Orb Fighters") # ウィンドウのタイトル title(screen) # タイトル画面 main(screen) # ゲームのメインループ
kou_

2018/05/04 19:00

コメントにての追記でインデントが崩れてしまってます。分かりづらくて申し訳ありません。
hayataka2049

2018/05/04 19:03

このサイトは質問の編集機能あるので、そっちでやってくださいな。この回答も読みづらいので、ぜんぶそっちにまとめてください
kou_

2018/05/05 02:42

申し訳ありません。 読みづらいのは重々承知しておりますが、質問やその他の回答、コメントの文字制限が10000字までとなっているようで、ソースコードがどうやってもひとまとめに掲載出来ませんでした。 何かしらの代替の方法がありますでしょうか… ソースコードのファイルを添付する、という方法も考えたのですが、ファイルを添付する欄等もなかったため、このような読みづらい掲載方法になってしまいました…
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問