お知らせ
変更箇所に誤りがありました
タイトル画面のコードを修正しました
フォントファイルのおすすめを変更しました(テキスト表示)
変更箇所の誤り
Ln365(365行目)変更個所に誤りがありました。
def draw(self, screen, offset):
"""マップを描画する"""
offsetx, offsety = offset
# マップの描画範囲を計算
startx = int(offsetx / GS)#ここ
endx = int(startx + SCR_RECT.width/GS + 1)#ここ
starty = int(offsety / GS) - 1#ここ
endy = int(starty + SCR_RECT.height/GS) + 1 #ここ
endy = int(starty + SCR_RECT.height/GS) + 1 のところが
endy = int(starty + SCR_RECT.height/GS + 1) + 1でした。
この変更を試した人がいたら申し訳ありませんでした。
目次
最初に気を付けること
どんな人が書いてる?
環境
pythonの基礎を学びたい人へ
参考にしたサイト
pyrpg27の変更個所
画面の表示
テキスト表示
効果音を鳴らす
BGMを鳴らす
選択肢を作る
線の描画
背景の描画
タイトル画面
画面切り替え
最初に気を付けること
pygameについてよくわかってない頃は、頻繁に無限ループに陥ります。青い輪が出たら速やかにセルの閉じるボタンを押しましょう。ゲーム画面を表示しているウィンドウの閉じるボタンは効きません。
キーの連打は絶対にやめましょう。処理が重なって余計に動かなくなります。
無限ループが始まったばかりなら、まだ希望が持てます。Alt + F4などを使って脱出するのです。
最初のうちは古いパソコンを使った方が良いかもしれません。新しいパソコンを壊したくなければ。
どんな人が書いてる?
ここをクリックしてください
1.おじさん
2.python初心者
環境
ここをクリックしてください
python3.11
IDLE
pythonの基礎を学びたい人へ
サイトを紹介しておきます。
参考にしたサイト
ここをクリックしてください
人工知能に関する断創録
PythonとPygameで作る レトロ風RPG 全コード
*注意:while の中にprint()があると、基本的に無限ループに陥るので気をつけましょう。(ただし、処理が遅い場合やif文、キー操作で一回だけ実行する場合は大丈夫です)
Pygameド素人がRPGを作る1
Pygameド素人がRPGを作る2
PygameでRPG制作 ーーそれっぽい画面を作ってみよう
PygameでRPG制作 ーーそれっぽい画面を作ってみよう② バトル画面のメニューを作ろう
PygameでRPG制作 ーーそれっぽい画面を作ってみよう③効果音を使ってみよう
PygameでRPG制作 ーーそれっぽい画面を作ってみよう④ 各アクションのでの動作とHP機能の実装
PygameでRPG制作 ーーそれっぽい画面を作ってみよう⑤ HP表示とスライムリッキーの反撃、終了処理
人工知能に関する断創録は特に役に立ちます。ぼくのコードは、ほとんどaidiaryさんのコードをコピペしたものです。
すぐ動かせるようにpyrpg27のエラーを修正したものを書いておきます。
注意:ぼくとaidiaryさんは何の関係もありません。勝手にコードをお借りしているだけです。修正したコードに不備があった場合、その責任はすべてぼくにあります。
pyrpg27 サイトへ移動
pyrpg27の変更個所
ここをクリックしてください
Ln23(23行目) 行数はdef()の行数です。変更個所ではありません。
(以下はすべて変更済みのコードです)
()をつけたり、isを==に変えたりしてます。
def load_image(dir, file, colorkey=None):
file = os.path.join(dir, file)
try:
image = pygame.image.load(file)
except (pygame.error, message):#ここ
print ("Cannot load image:"), file#ここ
raise (SystemExit, message)#ここ
image = image.convert()
if colorkey is not None:
if colorkey == -1:#ここ
colorkey = image.get_at((0,0))
image.set_colorkey(colorkey, RLEACCEL)
return image
Ln365(365行目)変更個所に誤りがありました。以下のコードは自分の誤りを訂正したコードです。
int()をつけてます。-1と+1をつけてます。
def draw(self, screen, offset):
"""マップを描画する"""
offsetx, offsety = offset
# マップの描画範囲を計算
startx = int(offsetx / GS)#ここ
endx = int(startx + SCR_RECT.width/GS + 1)#ここ
starty = int(offsety / GS) - 1#ここ
endy = int(starty + SCR_RECT.height/GS + 1) + 1 #ここ
Ln556(556行目)
/ を // にしています。
def update(self, map):
"""キャラクター状態を更新する。
mapは移動可能かの判定に必要。"""
# プレイヤーの移動処理
if self.moving == True:
# ピクセル移動中ならマスにきっちり収まるまで移動を続ける
self.rect.move_ip(self.vx, self.vy)
if self.rect.left % GS == 0 and self.rect.top % GS == 0: # マスにおさまったら移動完了
self.moving = False
self.x = self.rect.left // GS#ここ
self.y = self.rect.top // GS#ここ
/ を // にしています。
# キャラクターアニメーション(frameに応じて描画イメージを切り替える)
self.frame += 1
self.image = self.images[self.name][self.direction*4+self.frame//self.animcycle%4]#ここ
Ln603(行目)
/ を // にしています。
def update(self, map, battle):
"""プレイヤー状態を更新する。
mapは移動可能かの判定に必要。
battleはエンカウントに必要。"""
global game_state
# プレイヤーの移動処理
if self.moving == True:
# ピクセル移動中ならマスにきっちり収まるまで移動を続ける
self.rect.move_ip(self.vx, self.vy)
if self.rect.left % GS == 0 and self.rect.top % GS == 0: # マスにおさまったら移動完了
self.moving = False
self.x = self.rect.left // GS#ここ
self.y = self.rect.top // GS#ここ
/ を // にしています。
# キャラクターアニメーション(frameに応じて描画イメージを切り替える)
self.frame += 1
self.image = self.images[self.name][self.direction*4+self.frame//self.animcycle%4]#ここ
Ln764(行目)
()をつけてます。
def draw_character(self, screen, pos, ch):
"""1文字だけ描画する"""
x, y = pos
try:
rect = self.kana2rect[ch]
screen.blit(self.image, (x,y), (rect.x+self.color,rect.y,rect.width,rect.height))
except KeyError:
print ("描画できない文字があります:%s" % ch)#ここ
return
Ln843(843行目)
/ を // にしています。
def set(self, message):
"""メッセージをセットしてウィンドウを画面に表示する"""
self.cur_pos = 0
self.cur_page = 0
self.next_flag = False
self.hide_flag = False
# 全角スペースで初期化
self.text = [u' '] * (self.MAX_LINES*self.MAX_CHARS_PER_LINE)
# メッセージをセット
p = 0
for i in range(len(message)):
ch = message[i]
if ch == "/": # /は改行文字
self.text[p] = "/"
p += self.MAX_CHARS_PER_LINE
p = (p//self.MAX_CHARS_PER_LINE)*self.MAX_CHARS_PER_LINE#ここ
elif ch == "%": # \fは改ページ文字
self.text[p] = "%"
p += self.MAX_CHARS_PER_PAGE
p = (p//self.MAX_CHARS_PER_PAGE)*self.MAX_CHARS_PER_PAGE#ここ
else:
self.text[p] = ch
p += 1
self.text[p] = "$" # 終端文字
self.show()
Ln868(868行目)
/ を // にしています。
def update(self):
"""メッセージウィンドウを更新する
メッセージが流れるように表示する"""
if self.is_visible:
if self.next_flag == False:
self.cur_pos += 1 # 1文字流す
# テキスト全体から見た現在位置
p = self.cur_page * self.MAX_CHARS_PER_PAGE + self.cur_pos
if self.text[p] == "/": # 改行文字
self.cur_pos += self.MAX_CHARS_PER_LINE
self.cur_pos = (self.cur_pos//self.MAX_CHARS_PER_LINE) * self.MAX_CHARS_PER_LINE#ここ
elif self.text[p] == "%": # 改ページ文字
self.cur_pos += self.MAX_CHARS_PER_PAGE
self.cur_pos = (self.cur_pos//self.MAX_CHARS_PER_PAGE) * self.MAX_CHARS_PER_PAGE#ここ
elif self.text[p] == "$": # 終端文字
self.hide_flag = True
# 1ページの文字数に達したら▼を表示
if self.cur_pos % self.MAX_CHARS_PER_PAGE == 0:
self.next_flag = True
self.frame += 1
Ln888(888行目)
/ を // にしています。
def draw(self, screen):
"""メッセージを描画する
メッセージウィンドウが表示されていないときは何もしない"""
Window.draw(self, screen)
if self.is_visible == False: return
# 現在表示しているページのcur_posまでの文字を描画
for i in range(self.cur_pos):
ch = self.text[self.cur_page*self.MAX_CHARS_PER_PAGE+i]
if ch == "/" or ch == "%" or ch == "$": continue # 制御文字は表示しない
dx = self.text_rect[0] + MessageEngine.FONT_WIDTH * (i % self.MAX_CHARS_PER_LINE)
dy = self.text_rect[1] + (self.LINE_HEIGHT+MessageEngine.FONT_HEIGHT) * (i // self.MAX_CHARS_PER_LINE)
self.msg_engine.draw_character(screen, (dx,dy), ch)#ここ
# 最後のページでない場合は▼を表示
if (not self.hide_flag) and self.next_flag:
if self.frame / self.animcycle % 2 == 0:
dx = self.text_rect[0] + (self.MAX_CHARS_PER_LINE/2) * MessageEngine.FONT_WIDTH - MessageEngine.FONT_WIDTH/2
dy = self.text_rect[1] + (self.LINE_HEIGHT + MessageEngine.FONT_HEIGHT) * 3
screen.blit(self.cursor, (dx,dy))
Ln919(919行目)
/ を // にしています。
def draw(self, screen):
Window.draw(self, screen)
if self.is_visible == False: return
# はなす、つよさ、そうび、とびらを描画
for i in range(0, 4):
dx = self.text_rect[0] + MessageEngine.FONT_WIDTH
dy = self.text_rect[1] + (self.LINE_HEIGHT+MessageEngine.FONT_HEIGHT) * (i % 4)
self.msg_engine.draw_string(screen, (dx,dy), self.COMMAND[i])
# じゅもん、どうぐ、さくせん、しらべるを描画
for i in range(4, 8):
dx = self.text_rect[0] + MessageEngine.FONT_WIDTH * 6
dy = self.text_rect[1] + (self.LINE_HEIGHT+MessageEngine.FONT_HEIGHT) * (i % 4)
self.msg_engine.draw_string(screen, (dx,dy), self.COMMAND[i])
# 選択中のコマンドの左側に▶を描画
dx = self.text_rect[0] + MessageEngine.FONT_WIDTH * 5 * (self.command // 4)#ここ
dy = self.text_rect[1] + (self.LINE_HEIGHT+MessageEngine.FONT_HEIGHT) * (self.command % 4)
screen.blit(self.cursor, (dx,dy))
画面の表示
ここをクリックしてください
import pygame
import sys
pygame.init()
screen = pygame.display.set_mode((320, 320))
pygame.display.set_caption('screen only')
while (1):
screen.fill((0, 0, 0))
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
import pygame
ライブラリのインポート
事前にインストールしておきましょう。
コマンドで py -m pip install pygame
import sys
画面を閉じるのに必要です。
pygame.init()
初期化します。
screen = pygame.display.set_mode((320, 320))
数値は画面の大きさです。(よこ、たて)
pygame.display.set_caption('screen only')
ウィンドウの名前です。
while (1):
screen.fill((0, 0, 0))
画面の色を指定します。黒(0, 0, 0)白(255, 255, 255)灰色(128, 128, 128)
pygame.display.update()
画面の更新をします。
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
ウィンドウの閉じるボタンを押すと動かなくなります。まだ閉じません。
sys.exit()
ウィンドウを閉じます。
テキスト表示
ここをクリックしてください
コードを動かす前に、まずはフォントファイルの準備が必要です。
pygameでは日本語がサポートされてません。日本語でテキストを表示するには、.ttfファイルが必要です。.pngファイルだと自分でコードを書かないとダメです。
一般社団法人文字情報技術促進協議会(ここから、フォントファイルをダウンロード)
Windowsでパスをそのまま貼り付けるとエラーが出るので、""(ダブルクォーテーション)の前にrをつけましょう。(r"")
エラーの原因がエラー文が指し示すのとは別の行のこともあります。
import pygame
import sys
pygame.init()
screen = pygame.display.set_mode((160, 160))
pygame.display.set_caption('text only')
#ここにフォントのパスを貼り付ける
font = pygame.font.Font(パス, 30)
while (1):
screen.fill((0, 0, 0))
message_text = font.render("こんにちは", True, (255, 255, 255))
screen.blit(message_text, (5, 65))
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
font = pygame.font.Font(ここにパスを貼り付ける, 30)
フォントファイルをロードします。()の中にパスを貼り付けましょう。数値はフォントの大きさです。
message_text = font.render("こんにちは", True, (255, 255, 255))
Falseにすると、文字がギザギザします。数値は文字の色です。
screen.blit(message_text, (5, 65))
文字を画面に描画します。数値は座標です。(よこ、たて)
*座標は左上が(0,0)です。ヨコは右に行くほど増えます。タテは下に行くほど増えます。
効果音を鳴らす
ここをクリックしてください
コードを動かす前に効果音のファイルが必要です。
On-Jin ~音人~ ここから効果音ファイルをダウンロード
import pygame
import sys
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((160, 160))
pygame.display.set_caption('SE only')
#ここに効果音のパスを貼り付ける
sound = pygame.mixer.Sound(パス)
while (1):
screen.fill((0, 0, 0))
pygame.display.update()
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
sound.play()
from pygame.locals import *
from pygame.locals import * は特定の定数のみをインポートし、from pygame import * はPygame全体をインポートします。
これがあると KEYDOWNやQUITの前にpygame. を書かなくてよいです。すべてのpygame.がいらなくなるわけではないです。(pygame.quit()のpygameを消すとちょっと挙動が怪しいので消さないようにしましょう)
sound = pygame.mixer.Sound(ここにパスを貼り付ける)#ファイルのパス
効果音をロードします。
pygame.error: No such file or directory:
こういったエラーが出たら、パスの前にrをつけましょう。
r"パス"
elif event.type == KEYDOWN:
何かキーが押されたときに処理を実行します。
for event in pygame.event.get():の下に書きます。
sound.play()
効果音を鳴らします。(ここではsoundは変数名です。)
BGMを鳴らす
ここをクリックしてください
コードを動かす前に音楽ファイルが必要です。
かまタマゴ ここから音楽ファイルをダウンロード
import pygame
import sys
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((160,160))
pygame.display.set_caption("BGM_only")
#ここにBGMのパスを貼り付ける
pygame.mixer.music.load(パス)
pygame.mixer.music.play(-1)
while True:
pygame.display.update()
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.mixer.music.load(ここにパスを貼り付ける)
BGMをロードします。
pygame.error: No such file or directory:
こういったエラーが出たら、パスの前にrをつけましょう。
r"パス"
pygame.mixer.music.play(-1)
BGMをループします。1だと1回、鳴らします。何も書かない場合でも1回、鳴らします。
start = 1.0 でスタート地点を指定できます。ただし2回目は最初から再生されます。数値は秒単位です。pygame.mixer.music.play(1,1.0)と書くこともできます。
選択肢を作る
ダウンキーとアップキーでテキストの明るさが変わります。
ここをクリックしてください
import pygame
from pygame.locals import *
import sys
pygame.init()
screen = pygame.display.set_mode((160,160))
#ここにフォントのパスを貼り付ける
font = pygame.font.Font(パス, 30)
white = (255,255,255)
gray = (128,128,128)
color1 = white
color2 = gray
cmd = 0
while (1):
screen.fill((0, 0, 0))
text1 = font.render("newgame", True, color1)
text2 = font.render("continue", True, color2)
screen.blit(text1, (10 , 50))
screen.blit(text2, (10 , 80))
pygame.display.update()
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_DOWN:
if cmd == 0:
cmd = 1
color1 = gray
color2 = white
elif event.key == K_UP:
if cmd == 1:
cmd = 0
color1 = white
color2 = gray
明るさが変わると書きましたが、実際は色を変えてます。
線の描画
ここをクリックしてください
import pygame
import sys
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((320, 320))
pygame.display.set_caption('line')
while (1):
screen.fill((0, 0, 0))
pygame.draw.line(screen, (255,255,255), (110, 160), (210, 160), 2)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
pygame.draw.line(screen, (255,255,255), (110, 160), (210, 160), 2)
(255,255,255)色の指定です。
(110,160),(210,160) (始点の座標),(終点の座標)
2は線の太さです。
背景の描画
背景をダウンロードしましょう。
ぴぽや倉庫 ここからダウンロード
ここをクリックしてください
import pygame
import sys
pygame.init()
screen = pygame.display.set_mode((320,320))
pygame.display.set_caption("背景の描画")
#ここに背景のパスを貼り付ける
bg = pygame.image.load(パス)
while(1):
screen.blit(bg,(0,0))
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
bg = pygame.image.load(ここにパスを貼り付ける)
画像をロードします。
pygame.error: No such file or directory:
こういったエラーが出たら、パスの前にrをつけましょう。
r"パス"
screen.blit(bg,(0,0))
(0,0)座標です。(よこ、たて)
タイトル画面
ここをクリックしてください
あらかじめ、ペイント3Dでタイトルロゴを作ります。
(ペイント3Dは、2024年11月4日以降、Microsoft Storeでは入手できなくなり、今後の更新プログラムも受信できなくなります。)
まずはフォントをインストールします。
フォントファイルをダブルクリックします。
インストールをクリックします。
一瞬で終わります。
ペイント3Dを開きます。
キャンパスをクリックします。(アイコンの方)
透明なキャンパスをオンにします。
テキストをクリックします。(右側のTの字)
3Dテキストをクリックします。
フォントを選びます。
大きさを48にします。
色をクリックします。
キャンパス内をクリックしてタイトルを書きます。
タイトルを傾けます。
クリックして確定します。
(一度位置を確定しても文字をダブルクリックすればもう一度やり直せます。文字の変更の表示が出なくても辛抱強くダブルクリックしましょう。そのうち出ます)
キャンパスをクリックします。(アイコンの方)
キャンパスをできるだけ小さくします。
メニューをクリックして、名前を付けて保存を選びます。
画像をクリックします。
ファイルの種類をPNGのままにして保存をクリックします。
(PNGでないと背景が透明のまま保存できません)
import pygame
import sys
from pygame.locals import *
# Pygameの初期化
pygame.init()
# 画面サイズの設定
screen = pygame.display.set_mode((640, 480))
pygame.display.set_caption("title")
#ここにフォントのパスを貼り付ける
font = pygame.font.Font(パス, 20)
#背景画像
#ここに背景のパスを貼り付ける
image = pygame.image.load(パス)
#タイトル画像
#ここにタイトル画像のパスを貼り付ける
tile_image = pygame.image.load(パス)
#シルエット画像
#ここにシルエット画像のパスを貼り付ける
silhouette_image = pygame.image.load(パス)
cmd = 0
white = (255,255,255)
gray = (208,208,208)
red = (255,0,0)
yellow = (245,245,0)
color1 = (208,208,208)
color2 = (208,208,208)
color3 = (208,208,208)
# メインループ
running = True
while running:
#背景
screen.blit(image,(0, 0))
#タイトルロゴ
screen.blit(silhouette_image,(260,30))
screen.blit(tile_image,(20,70))
#サブタイトル
message_text = font.render("ヘイジパクエスト", True, red)
screen.blit(message_text, (240, 175))
pygame.draw.line(screen, red, (240, 200), (400, 200), 1)
message_text = font.render("失われた王国の秘宝", True, white)
screen.blit(message_text, (228, 205))
#選択
message_text = font.render("New Game", True, color1)
screen.blit(message_text, (270, 293))
message_text = font.render("Continue", True, color2)
screen.blit(message_text, (280, 323))
message_text = font.render("Finish", True, color3)
screen.blit(message_text, (290, 353))
#色の変更
if cmd == 0:
color1 = white
else:
color1 = gray
if cmd == 1:
color2 = white
else:
color2 = gray
if cmd == 2:
color3 = white
else:
color3 = gray
# 画面を更新
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_DOWN:
if cmd == 0:
cmd = 1
elif cmd == 1:
cmd = 2
elif cmd == 2:
cmd = 0
elif event.key == K_UP:
if cmd == 0:
cmd = 2
elif cmd == 1:
cmd = 0
elif cmd == 2:
cmd = 1
pygame.error: No such file or directory:
こういったエラーが出たら、パスの前にrをつけましょう。
r"パス"
エラー文ではシルエット画像が示されましたが、エラーの原因はタイトル画像でした。(ぼくの体験談)
エラーの原因がエラー文が指し示すのとは別の行のこともあります。
画面切り替え
ここをクリックしてください
スペースキーで画面が切り替わります。
import pygame
from pygame import *
import sys
first,second = 0,1
game_state = first
pygame.init()
screen=pygame.display.set_mode((160,160))
while(True):
screen.fill((0,0,0))
pygame.display.update()
if game_state==first:
pygame.init()
screen=pygame.display.set_mode((160,160))
pygame.display.set_caption('a')
running = True
while running:
screen.fill((0,0,0))
pygame.display.update()
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
elif event.type==KEYDOWN:
if event.key==K_SPACE:
if game_state==first:
running = False
game_state=second
elif game_state==second:
pygame.init()
screen=pygame.display.set_mode((160,160))
pygame.display.set_caption('b')
running = True
while running:
screen.fill((255,255,255))
pygame.display.update()
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
elif event.type==KEYDOWN:
if event.key==K_SPACE:
if game_state==second:
running = False
game_state=first
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
if文とキーハンドラーを使って切り替えます。
ポイントはgame_stateを変更する前にrunning = Falseにしていることです。これがないと画面が切り替わりません。ループを止めてから画面を切り替えます。