0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

pygameでRPGをつくってみる4 テキスト

Last updated at Posted at 2024-10-06

記事全体の目次へ移動

GIF

ここをクリックしてください

無題の動画 ‐ Clipchampで作成 (4).gif

無題の動画 ‐ Clipchampで作成 (5).gif

無題の動画 ‐ Clipchampで作成 (6).gif

この記事の目的

 会話ができるようにしたいと思います。

図形

 この記事ではメッセージの背景を作るために使います。

ここをクリックしてください
図形
import pygame
import sys

pygame.init()
screen = pygame.display.set_mode((320, 320))
pygame.display.set_caption('screen only')
while (1):
    screen.fill((255, 255, 255))
    pygame.draw.rect(screen,(0,0,0),(140,140,40,40))
    pygame.display.update()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

pygame.draw.rect(screen,(0,0,0),(140,140,40,40))
(0,0,0)色の指定をします。
(140,140,40,40) 座標と大きさです。(横、縦、幅、高さ)

 この記事ではテキストウィンドゥの枠のためです。

ここをクリックしてください
import pygame
import sys

pygame.init()
screen = pygame.display.set_mode((320, 320))
pygame.display.set_caption('screen only')
while (1):
    screen.fill((255, 255, 255))
    pygame.draw.rect(screen,(0,0,0),(140,140,40,40),5)
    pygame.display.update()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

pygame.draw.rect(screen,(0,0,0),(140,140,40,40),5)
最後の5が枠の太さです。

テキスト改行

この記事では使いませんが、長いセリフでは改行が必要になります。

ここをクリックしてください

 ¥n 環境によっては、\nでテキストを改行できます。

import pygame
pygame.init()

# 画面の設定
screen = pygame.display.set_mode((320, 160))
pygame.display.set_caption("Pygame Text Wrapping Example")

# フォントの設定
#ここにフォントのパスを貼り付ける
font = pygame.font.Font(パス, 20)

# テキストを改行して描画する関数
def draw_text(surface, text, pos, color=(255, 255, 255)):
    lines = text.split('\n')
    x, y = pos
    for line in lines:
        text_surface = font.render(line, True, color)
        surface.blit(text_surface, (x, y))
        y += text_surface.get_height()

# メインループ
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    screen.fill((0, 0, 0))
    draw_text(screen, "ここは\nはじまりのむらです", (50, 50))
    pygame.display.flip()

pygame.quit()


会話する

会話のためのコードを書いていきます。

ここをクリックしてください

Zキーを押すと会話します。

import pygame
from pygame.locals import *
import sys

GS = 32
DOWN,LEFT,RIGHT,UP = 0,1,2,3

def split_image(image):
    """32x128のキャラクターイメージを32x32の4枚のイメージに分割
    分割したイメージを格納したリストを返す"""
    imageList = []
    for i in range(0, 128, GS):
        for j in range(0, 128, GS):
            surface = pygame.Surface((GS,GS))
            surface.blit(image, (0,0), (j, i,GS,GS))
            surface.set_colorkey(surface.get_at((0,0)), RLEACCEL)
            surface.convert()
            imageList.append(surface)
    return imageList


pygame.init()
screen = pygame.display.set_mode((160,200))
pygame.display.set_caption('会話する')
#ここにフォントのパスを貼り付ける
font = pygame.font.Font(パス, 20) 
#ここに一人目のパスを貼り付ける
playerImgList = split_image(pygame.image.load(パス))
#ここに二人目のパスを貼り付ける
playerImgList2 = split_image(pygame.image.load(パス))

text_window = False
chara_dict  = {(3,2):"girl"}

x2,y2 = 3,2
x,y = 0,0
cx,cy = 0,0
chara_pos = 0
a = 0
direction = DOWN
direction2 = DOWN
animcycle = 24  # アニメーション速度
frame = 0
clock = pygame.time.Clock()
 
while True:
    clock.tick(60)
    screen.fill((128,128,128))
    # 経過フレーム数に応じて表示する画像を変える
    frame += 1
    player = playerImgList[int(direction*4+frame/animcycle%4)]
    player2 = playerImgList2[int(direction2*4+frame/animcycle%4)]
    screen.blit(player, (x*GS, y*GS))
    screen.blit(player2, (x2*GS, y2*GS))
    if a == 0:
        message = "わたし?"
    if text_window == True and chara_pos in chara_dict:
        text = font.render(message, True, (255,255,255))
        pygame.draw.rect(screen, (0, 0, 0), Rect(10, 130, 140, 50))
        pygame.draw.rect(screen, (255, 255, 255), Rect(10, 130, 140, 50), 3)
        screen.blit(text, (15, 140))
    pygame.display.update()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type==KEYDOWN:
            if event.key==K_SPACE:
                pygame.quit()
                sys.exit()

            elif  event.key==K_DOWN:
                direction = DOWN
                y += 1      
            elif  event.key==K_UP:
                direction = UP
                y -= 1
            elif event.key==K_RIGHT:
                direction = RIGHT
                x += 1
            elif  event.key==K_LEFT:
                direction = LEFT
                x -= 1

            elif event.key == K_z:
                if  direction == DOWN:
                    cx = x
                    cy = y + 1
                elif  direction == UP:
                    cx = x
                    cy = y - 1
                elif  direction == RIGHT:
                    cx = x + 1
                    cy = y
                elif  direction == LEFT:
                    cx = x - 1
                    cy = y

                chara_pos = (cx,cy)
                if chara_pos in chara_dict:
                    text_window = True
                    if direction == DOWN:
                        direction2 = UP
                    if direction == UP:
                        direction2 = DOWN
                    if direction == RIGHT:
                        direction2 = LEFT
                    if direction == LEFT:
                        direction2 = RIGHT
                    if chara_dict[chara_pos] == "girl":
                        if a == 0:
                            a += 1
                        elif a == 1:                
                            message = "うん"
                            a = 2
                        elif a == 2:                
                            message = "一緒に行く"
                            a = 3
                        elif a == 3:   
                            text_window = False
                            a = 0


text_window = False
最初からテキストウィンドウがあると変なので消しておきます。

chara_dict = {(3,2):"girl"}
座標をキーに指定して、キャラクター名を取り出すための辞書です。

x2,y2 = 3,2
二人目のキャラクターの座標です。

x,y = 0,0
プレイヤーの座礁です。

cx,cy = 0,0
プレイヤーの隣の座標を入れるための変数です。

chara_pos = 0
cxとcyをまとめて、()に入れるための変数です。

a = 0
セリフを変更するための変数です。

direction = DOWN
プレイヤーの最初の向きです。
direction2 = DOWN
二人目のキャラクターの最初の向きです。

if a == 0:
message = "わたし?"
これがないと二回目以降に最初のセリフが出てきません。

        elif event.key == K_z:
            if  direction == DOWN:
                cx = x
                cy = y + 1
            elif  direction == UP:
                cx = x
                cy = y - 1
            elif  direction == RIGHT:
                cx = x + 1
                cy = y
            elif  direction == LEFT:
                cx = x - 1
                cy = y

隣の座標をcxとcyに入れています。

chara_pos = (cx,cy)
cxとcyを一つにしています。

if chara_pos in chara_dict:
辞書の中に隣の座標が存在するか調べてます。
これがないと辞書にないキー(隣の座標)を指定したときにエラーが出ます。

text_window = True
テキストウィンドウを表示します。
if direction == DOWN:
direction2 = UP
if direction == UP:
direction2 = DOWN
if direction == RIGHT:
direction2 = LEFT
if direction == LEFT:
direction2 = RIGHT

二人目のキャラクターの向きを変えます。

if chara_dict[chara_pos] == "girl":
辞書にないキー(隣の座標)を指定するとここでエラーが出ます。
ゲームの画面ではキャラクターがいないところでZキーを押すとエラーが出ます。

細かい修正
辞書のキーには文字列以外も指定できるということで、キーを文字列から変更しました。f文字列を使う必要がなくなりました。

宝箱を開ける

会話するのとあまり変わらないのでここに書きました。

ここをクリックしてください

宝箱の画像はこのサイトからお借りするとよいです。
ぴぽや倉庫 ここからダウンロード

キャラチップ+.zipをダウンロードしましょう。

スクリーンショット (694) - コピー.png

import pygame
from pygame.locals import *
import sys

GS = 32
DOWN,LEFT,RIGHT,UP = 0,1,2,3

def split_image(image):
    """32x128のキャラクターイメージを32x32の4枚のイメージに分割
    分割したイメージを格納したリストを返す"""
    imageList = []
    for i in range(0, 128, GS):
        for j in range(0, 128, GS):
            surface = pygame.Surface((GS,GS))
            surface.blit(image, (0,0), (j, i,GS,GS))
            surface.set_colorkey(surface.get_at((0,0)), RLEACCEL)
            surface.convert()
            imageList.append(surface)
    return imageList


pygame.init()
screen = pygame.display.set_mode((160,200))
pygame.display.set_caption('宝箱')
chara_dict  = {"2,1":"treasure"}
#ここにキャラクターのパスを貼り付ける
playerImgList = split_image(pygame.image.load(パス))
#ここに宝箱のパスを貼り付ける
treasure = pygame.image.load(パス)  

x2,y2 = 2,1
x,y = 2,4
cx,cy = 0,0
chara_pos = 0
a = (64,0,GS,GS)
 
direction = DOWN
animcycle = 24  # アニメーション速度
frame = 0
clock = pygame.time.Clock()
 
while True:
    clock.tick(60)
    screen.fill((0,0,0))
    # 経過フレーム数に応じて表示する画像を変える
    frame += 1
    player = playerImgList[int(direction*4+frame/animcycle%4)]
    screen.blit(player, (x*GS, y*GS))
    screen.blit(treasure,(x2*GS,y2*GS), a)
    pygame.display.update()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type==KEYDOWN:
            if event.key==K_SPACE:
                pygame.quit()
                sys.exit()

            elif  event.key==K_DOWN:
                direction = DOWN
                y += 1      
            elif  event.key==K_UP:
                direction = UP
                y -= 1
            elif event.key==K_RIGHT:
                direction = RIGHT
                x += 1
            elif  event.key==K_LEFT:
                direction = LEFT
                x -= 1

            elif event.key == K_z:
                if  direction == DOWN:
                    cx = x
                    cy = y + 1
                elif  direction == UP:
                    cx = x
                    cy = y - 1
                elif  direction == RIGHT:
                    cx = x + 1
                    cy = y
                elif  direction == LEFT:
                    cx = x - 1
                    cy = y

                chara_pos = f"{cx},{cy}"
                if chara_pos in chara_dict:
                    print(cx,cy)
                    if chara_dict[chara_pos] == "treasure":
                        a = (64,64,GS,GS)


screen.blit(treasure,(x2*GS,y2*GS), a)

a = (64,0,GS,GS)からa = (64,64,GS,GS)に変更してます。
(画像の横座標、画像の縦座標、横サイズ、縦サイズ)

white - コピー.jpg

宿屋

ここをクリックしてください

矢印キーで移動して、左クリックで話しかけます。
はい、いいえを選ぶのもセリフを進めるのも左クリックです。

必要なもの

  • フォントファイル
  • プレイヤー画像
  • 宿屋のキャラクター画像
  • BGMのファイル
  • ボタンの音のファイル
  • 泊まった時のメロディのファイル

以下のサイトからダウンロードできます。

一般社団法人文字情報技術促進協議会(ここから、フォントファイルをダウンロード)
キャラクター画像
ピ!(ボタンの音)
ほのぼの01(泊まった時のメロディ)
BGM(ひとやすみ)
BGM(石畳の下で)

FileNotFoundError
というエラーが出たら、パスの前に r(アール) をつけましょう。r"パス"

import pygame
from pygame.locals import *
import sys
import time

GS = 32
DOWN,LEFT,RIGHT,UP = 0,1,2,3
Gold = 300
def split_image(image):
    """32x128のキャラクターイメージを32x32の4枚のイメージに分割
    分割したイメージを格納したリストを返す"""
    imageList = []
    for i in range(0, 128, GS):
        for j in range(0, 128, GS):
            surface = pygame.Surface((GS,GS))
            surface.blit(image, (0,0), (j, i,GS,GS))
            surface.set_colorkey(surface.get_at((0,0)), RLEACCEL)
            surface.convert()
            imageList.append(surface)
    return imageList

# テキストを改行して描画する関数
def draw_text(surface, message, pos, font, color=(255, 255, 255)):
    lines = message.split('\n')
    x, y = pos
    for line in lines:
        text_surface = font.render(line, True, color)
        surface.blit(text_surface, (x, y))
        y += text_surface.get_height()

pygame.init()
screen = pygame.display.set_mode((320,250))
pygame.display.set_caption('宿屋')
text_window = False
chara_dict  = {"3,0":"girl"}
#ここにフォントのパスを貼り付ける
font = pygame.font.Font(パス, 20)
# プレイヤーの画像のパスを貼り付ける
playerImgList = split_image(pygame.image.load(パス))
# 宿屋のキャラクター画像のパスを貼り付ける
playerImgList2 = split_image(pygame.image.load(パス))
# BGMのパスを貼り付ける
pygame.mixer.music.load(パス)
pygame.mixer.music.play(-1)
# ボタンの音のパスを貼り付ける
sound = pygame.mixer.Sound(パス)
# 泊まった時のメロディのパスを貼り付ける
sound2 = pygame.mixer.Sound(パス)
x2,y2 = 3,0
x,y = 3,2
mx,my = 0,0
cx,cy = 0,0
chara_pos = 0
a = 0
choose = 0
shop = 0
direction = DOWN
direction2 = DOWN
animcycle = 24  
frame = 0
action_number44 = 0
action_number45 = 0
Max_HP = 80
player_HP = 10
change = 0
inn_melody = 0
clock = pygame.time.Clock()
walking = False
# 半透明のSurfaceを作成
# はい、いいえ
transparent_surface3 = pygame.Surface((70, 20), pygame.SRCALPHA)
# RGBA (白, 透明度128)
transparent_surface3.fill((255, 255, 255, 128))  
# 半透明のSurfaceを作成
transparent_surface = pygame.Surface((320, 250), pygame.SRCALPHA)
transparent_surface.fill((0, 0, 0, change))  
 
while True:
    clock.tick(60)
    screen.fill((128,128,128))
    # 経過フレーム数に応じて表示する画像を変える
    frame += 1
    player = playerImgList[int(direction*4+frame/animcycle%4)]
    player2 = playerImgList2[int(direction2*4+frame/animcycle%4)]
    screen.blit(player, (x*GS, y*GS))
    screen.blit(player2, (x2*GS, y2*GS))
    #"はい"と"いいえ"の枠
    if choose == 1:
        pygame.draw.rect(screen, (0, 0, 0), Rect(250, 5, 70, 55))
        pygame.draw.rect(screen, (255, 255, 255), Rect(250, 5, 70, 55), 3)
        if mx >= 258 and mx <= 298:
            if my >= 10  and my <= 30:
                screen.blit(transparent_surface3, (258, 10))
                action_number44 = 1
            else:
                action_number44 = 0
                
            if my >=34  and my <= 54:
                screen.blit(transparent_surface3, (258, 34))
                action_number45 = 1
            else:
                action_number45 = 0
        else:
            action_number44 = 0
            action_number45 = 0
        text = font.render("はい", True, (255,255,255))                
        screen.blit(text, (258, 10))
        text1 = font.render("いいえ", True, (255,255,255))                
        screen.blit(text1, (258, 33))

    if a == 0:
        message = "ここはやどやです。\n5ゴールドに なりますが?"
    if text_window == True:
        pygame.draw.rect(screen, (0, 0, 0), Rect(10, 130, 270, 80))
        pygame.draw.rect(screen, (255, 255, 255), Rect(10, 130, 270, 80), 3)
        draw_text(screen , message, (18,135), font)
    if shop == 1 and a == 3 or a == 4:
        if change < 255 and a == 3:
            if inn_melody == 0:
                pygame.mixer.music.pause()
                sound2.play()
                inn_melody = 1
            change += 2
            time.sleep(0.01)
            if change >= 243:
                change = 255
            if change == 255:
                a = 4
        elif change > 0 and a == 4:
            change -= 2
            time.sleep(0.01)
            message = "またおこしくださいませ"
            if change == 1:
                change = 0
            if change == 0:
                a = 5
        transparent_surface.fill((0, 0, 0, change))  
        #透明のSurfaceを描画
        screen.blit(transparent_surface, (0, 0))
    if change == 0 and a == 5:
        player_HP = Max_HP
        choose = 0
        a = 7
    pygame.display.update()
    for event in pygame.event.get():
        mouse_pressed = pygame.mouse.get_pressed()
        mouse_pos = pygame.mouse.get_pos()
        mx = mouse_pos[0]
        my = mouse_pos[1]
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        elif mouse_pressed[0]:
            if shop == 0:
 
                if  direction == DOWN:
                    cx = x
                    cy = y + 1
                elif  direction == UP:
                    cx = x
                    cy = y - 1
                elif  direction == RIGHT:
                    cx = x + 1
                    cy = y
                elif  direction == LEFT:
                    cx = x - 1
                    cy = y

                chara_pos = f"{cx},{cy}"
                if chara_pos in chara_dict:
                    text_window = True
                    if direction == DOWN:
                        direction2 = UP
                    elif direction == UP:
                        direction2 = DOWN
                    elif direction == RIGHT:
                        direction2 = LEFT
                    elif direction == LEFT:
                        direction2 = RIGHT
                    if chara_dict[chara_pos] == "girl":
                        shop = 1
                        choose = 1

     #宿屋
            elif shop == 1:
                if choose == 1 and a == 0:
                    a = 1
                # はい お金ある
                elif action_number44 == 1 and a == 1 and Gold >= 5:
                    sound.play()
                    message = "ごゆっくり どうぞ"                           
                    a = 2                                
                    choose = 0
                    Gold -= 5                               
                elif shop == 1 and a == 2:
                    a = 3
                # はい お金ない    
                elif action_number44 == 1 and a == 1 and Gold <= 5:
                    message = "お金が足りません"
                    sound.play()
                    a = 6
                    choose = 0
                # いいえ 閉じる   
                elif action_number45 == 1 and a == 1:
                    sound.play()
                    text_window = False
                    choose = 0
                    a = 0
                    shop = 0

                # またおこし    
                elif a == 7:
                    pygame.mixer.music.unpause()
                    message = "またおこしくださいませ"
                    a = 8
                    time.sleep(0.3)
                # おかねがある 閉じる
                elif a == 8:
                    sound.play()
                    a = 0
                    text_window = False
                    shop  = 0
                    inn_melody = 0
                # お金がない 閉じる
                elif a == 6:
                    sound.play()
                    a = 0
                    text_window = False
                    shop = 0

        elif event.type == KEYDOWN:
            if  event.key==K_DOWN:
                direction = DOWN
                y += 1      
            elif  event.key==K_UP:
                direction = UP
                y -= 1
            elif event.key==K_RIGHT:
                direction = RIGHT
                x += 1
            elif  event.key==K_LEFT:
                direction = LEFT
                x -= 1
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?