0
1

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をつくってみる2 キャラクター移動

Last updated at Posted at 2024-10-03

お知らせ

キャラクターの描画のコードを修正しました。

記事全体の目次へ移動

GIF

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

walking_video.gif

キャラクターについて書いていこうと思いますが、aidiaryさんのコードを参考にした方が早いかもしれませんね。
人工知能に関する断創録

ぼくのコードはaidiaryさんのコードをちょっと短くしただけです。

キャラクターの描画

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

まずはキャラクターの画像をダウンロードしましょう。
キャラチップ.zipを選びましょう。
ぴぽや倉庫 ここからダウンロード

manto_12.png

トリミングします。と書きましたが、実はしなくてもいいです。
screen.blit(player,(64,64))のところを
screen.blit(player,(64,64),(0,0,32,32))と書くとそこだけ表示されます。
(0,0,32,32)
(キャラ画像の横座標、キャラ画像の縦座標、横の大きさ、縦の大きさ)
無題.png
失礼しました。

このコードを使用する際は、rを"パス"の前につけましょう。
つけないと、
FileNotFoundError
というエラーが出て、ファイルが正しく読み込まれません。

キャラクター
import pygame
import sys
from pygame.locals import *

pygame.init()
screen = pygame.display.set_mode((160, 160))
pygame.display.set_caption('chara only')
# ここにキャラクター画像ののパスを貼り付ける
player = pygame.image.load(パス)
while (1):
    screen.fill((0, 0, 0))
    screen.blit(player,(64,64),(0,0,32,32))
    pygame.display.update()
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

スクリーンショット (661).png

トリミング
いらなくなってしまいましたが、何か用途があったら使ってください。

image.png

import cv2
import numpy as np

# 背景色を指定(透明)
background_color = (0, 0, 0, 0)

# 元画像のパスを指定
input_img = cv2.imread(ここにパスを貼り付ける,cv2.IMREAD_UNCHANGED)
# トリミングする範囲を指定
output_img = input_img[0:32,0:32]
# 背景色を設定
bg_img = np.full((32, 32, 4), background_color, dtype=np.uint8)
bg_img[0:output_img.shape[0], 0:output_img.shape[1], :3] = output_img[:, :, :3]
bg_img[0:output_img.shape[0], 0:output_img.shape[1], 3] = output_img[:, :, 3]
# ファイル名
filename = 'image.png'
# トリミングした画像を新しいファイルに保存
cv2.imwrite(filename, output_img)       

print("完了しました")

TypeError: 'NoneType' object is not subscriptable
あるいは
FileNotFoundError
というエラーが出たら、ファイルが正しく読み込まれてません。

 フォルダー名が日本語なら英語に変えましょう。”新しいフォルダー”という名前もダメです。
 さらに、rを引用符の前につけましょう。

キャラクターの移動

ここをクリックしてください
キャラクターの移動
import pygame
from pygame.locals import *
import sys

pygame.init()
screen = pygame.display.set_mode((160,160))
pygame.display.set_caption('chara_move')
x,y = 2,2
GS = 32
#ここにキャラのパスを貼り付ける
player = pygame.image.load(パス)

while (1):
    screen.fill((0,0,0))
    screen.blit(player, (x*GS, y*GS), (0, 0, GS, GS))
    pygame.display.update()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        elif event.type==KEYDOWN:
            if event.key==K_DOWN:
                y += 1      
            elif event.key==K_UP:
                y -= 1
            elif event.key==K_RIGHT:
                x += 1
            elif event.key==K_LEFT:
                x -= 1

x,y = 0,0
マス単位の座標です。
ここを変えることでキャラクターの初期位置を変えることができます。

GS = 32
マスの大きさです。

screen.blit(player, (x*GS, y*GS))
マス単位の座標にマスの大きさをかけています。
x,y = 0, 0
(0*32, 0*32) つまり (0, 0)

キャラクターの描画では(64, 64)でしたね。これをここと同じように書くと
x,y = 2, 2
(2*32, 2*32) つまり (64, 64)

図で位置を表してみました。赤が(0, 0) 青が(64, 64)

マス - コピー.png

if event.key==K_DOWN:
何かキーが押された時。

elif event.type==KEYDOWN:
ダウンキーが押されたとき。

y += 1
yを変更しています。

x,y = 0, 0 だと x,y = 0, 1 に変更。
screen.blit(player, (x*GS, y*GS))だから
(0*GS, 0*GS) だと (0*GS, 1*GS) に変更。
ピクセル単位の座標にすると (0, 0) が (0, 32) になります。

マス - コピー (2).png

キャラアニメ

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

ぴぽや倉庫 サイトへ移動

ここからキャラクターチップをダウンロードできます。
でもちょっと足りないので編集しましょう。
以下のコードで足りない画像を追加できます。

manto_12.png

player.png

上の画像が下の画像のようになります。

エラーが出たら、フォルダ名が日本語になってないか、ファイル名が数字で始まってないか確認しましょう。r文字も忘れずつけましょう。r"ファイルのパス"

画像編集

import cv2
import numpy as np

# 画像を読み込む(アルファチャンネルを含む)
image = cv2.imread(ここにキャラクター画像のパスを貼り付ける, cv2.IMREAD_UNCHANGED)

# 画像が正しく読み込まれたか確認
if image is None:
    print("画像が読み込まれませんでした。ファイルパスを確認してください。")
else:
    # コピーする部分の座標とサイズ
    x, y, w, h = 32, 0, 32, 128
    part = image[y:y+h, x:x+w]

    # 元の画像の右端に追加するために、新しい画像を作成
    new_width = image.shape[1] + w
    new_image = np.zeros((image.shape[0], new_width, 4), dtype=np.uint8)

    # 元の画像を新しい画像にコピー
    if image.shape[2] == 4:
        new_image[:, :image.shape[1], :] = image
    else:
        new_image[:, :image.shape[1], :3] = image
        new_image[:, :image.shape[1], 3] = 255  # アルファチャンネルを追加

    # コピーした部分を新しい画像の右端に追加
    if part.shape[2] == 4:
        new_image[:, image.shape[1]:, :] = part
    else:
        new_image[:, image.shape[1]:, :3] = part
        new_image[:, image.shape[1]:, 3] = 255  # アルファチャンネルを追加

    # 結果を保存
    cv2.imwrite('edited_image.png', new_image)
    print("完了しました")

フォルダ内のすべてのファイルに適用するコードもあります。
すべてのファイルに適用 クリックして移動

@@@@@@@@@@@@@@@@@@@@@@@@@@

キャラが、その場足踏みしているように見えるコードです。
aidiaryさんのコードを短くしたコードです。

キャラアニメ
import pygame
from pygame.locals import *
import sys


def split_image(image):
    """32x128のキャラクターイメージを32x32の4枚のイメージに分割
    分割したイメージを格納したリストを返す"""
    imageList = []
    for i in range(0, 128, GS):
        surface = pygame.Surface((GS,GS))
        surface.blit(image, (0,0), (i,0,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,160))
pygame.display.set_caption('chara anime')
x,y = 2,2
GS = 32
#ここにキャラのパスを貼り付ける
playerImgList = split_image(pygame.image.load(パス))  
# アニメーション速度
animcycle = 24  
frame = 0
clock = pygame.time.Clock()
 
while True:
    screen.fill((255,255,255))
    clock.tick(60)    
    # 経過フレーム数に応じて表示する画像を変える
    frame += 1
    player = playerImgList[int(frame/animcycle%4)]
    screen.blit(player, (x*GS, y*GS),(0,0,GS,GS))
    pygame.display.update()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        elif event.type==KEYDOWN:
            if event.key==K_DOWN:
                y += 1      
            elif event.key==K_UP:
                y -= 1
            elif event.key==K_RIGHT:
                x += 1
            elif event.key==K_LEFT:
                x -= 1

animcycle = 24
ずっと24のままです。

frame = 0 と frame += 1
数字が一つずつ増えていきます。frameと書いてあると、なじみのない人だとわかりにくく思えますが、frame が a でも同じです。数字が一つずつ増えていくことには変わりありません。

player = playerImgList[frame//animcycle%4)]
キャラクター画像はリストに入っている。
計算式でインデックスを決めている。

playerImgList[0]
playerImgList[1]
playerImgList[2]
playerImgList[3]

%の計算

a = 0//3%3
b = 1//3%3
c = 2//3%3

d = 3//3%3
e = 4//3%3
f = 5//3%3

g = 6//3%3
h = 7//3%3
i = 8//3%3

j = 9//3%3
k = 10//3%3
l = 11//3%3

print(a,b,c,d,e,f,g,h,i,j,k,l)
このコードをちょっと動かしてみてください。
結果は思った通りでしたか?思った通りならこのまま進んで問題ないです。
思ったのとは違ったのなら、立ち止まって考えてみましょう。

%の計算

a = 0//3%3 0割る3で0、0%3余り0
b = 1//3%3
c = 2//3%3

d = 3//3%3 3割る3で1、1%3余り1
e = 4//3%3 4割る3で1.33……整数除算で小数点以下が切り捨てられ1、1%3余り1
f = 5//3%3

g = 6//3%3
h = 7//3%3
i = 8//3%3

j = 9//3%3 9割る3で3、3%3割り切れるので余り0
k = 10//3%3
l = 11//3%3

向きを変えながら歩く

ここをクリックしてください
向きを変える
import pygame
from pygame.locals import *
import sys


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,160))
pygame.display.set_caption('walking')
x,y = 2,2
GS = 32
DOWN,LEFT,RIGHT,UP = 0,1,2,3
#ここキャラのパスを貼り付ける
playerImgList = split_image(pygame.image.load(パス))  # プレイヤーx,y = 1,1
direction = DOWN
animcycle = 24  # アニメーション速度
frame = 0
clock = pygame.time.Clock()
 
while True:
    clock.tick(60)
    screen.fill((255,255,255))
    # 経過フレーム数に応じて表示する画像を変える
    frame += 1
    player = playerImgList[int(direction*4+frame/animcycle%4)]
    screen.blit(player, (x*GS, y*GS))
    pygame.display.update()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        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

スクロール

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

 キャラクターの移動処理にはスクロールというものがあるのですが、ぼくは理解してないので紹介だけしておきます。
(aidiaryさんの記事です)
タイルスクロール
変更箇所(すべて変更済みのコードです)
pygame.quit()をつけてます。

        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()#ここ
                sys.exit()

()をつけたり、isを==に変えたりしてます。

def load_image(filename, colorkey=None):
    filename = os.path.join("data", filename)
    try:
        image = pygame.image.load(filename)
    except (pygame.error, message):#ここ
        print ("Cannot load image:"), filename#ここ
        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

int()をつけてます。

    def draw(self, screen, offset):
        """マップを描画する"""
        offsetx, offsety = offset
        # マップの描画範囲を計算
        startx = int(offsetx / GS)#ここ
        endx = int(startx + SCR_RECT.width/GS + 1)#ここ
        starty = int(offsety / GS)#ここ
        endy = int(starty + SCR_RECT.height/GS + 1)#ここ

/ を // にします。

    def update(self):
        # キャラクターアニメーション(frameに応じて描画イメージを切り替える)
        self.frame += 1
        self.image = self.images[self.direction*4+self.frame//self.animcycle%4]#ここ

(aidiaryさんの記事です)
ピクセルスクロール
変更箇所。(変更済みのコードです)
/ を // にしてます。

        # プレイヤーの移動処理
        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#ここ

これ以外はタイルベーススクロールと同じところを変更してください。

マウス移動(白背景)

左クリックでキャラクターが移動します。

ここをクリックしてください
マウス移動

import pygame
import sys
import struct
import os

from pygame.locals import *

pygame.init()
screen=pygame.display.set_mode((480,480))
pygame.display.set_caption("マウス移動")
GS = 32
x,y = 7,7
vx,vy = 0,0
mx,my = 7,7
DOWN,LEFT,RIGHT,UP = 0,1,2,3
direction = DOWN

def main():
    global game_state,chara,x,y
    
    # キャラクターチップをロード
    Player.images["player"] = split_image(pygame.image.load(ここにキャラのパスを貼り付ける))

    player = Player("player")

    clock = pygame.time.Clock()
    running = True
    while running:
        clock.tick(60)
        screen.fill((255,255,255))
        player.draw()
        player.update()
        pygame.display.update()
        for event in pygame.event.get():
            if event.type==QUIT:
                pygame.quit()
                sys.exit()
                pygame.display.update()


def split_image(image):
    """128x128のキャラクターイメージを32x32の16枚のイメージに分割
    分割したイメージを格納したリストを返す"""
    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

class Player:
    
    speed = 4  # 1フレームの移動ピクセル数
    animcycle = 24  # アニメーション速度
    frame = 0
    images = {}
    def __init__(self, name):
        self.name = name  # プレイヤー名(ファイル名と同じ)
        self.image = self.images[name][0]  # 描画中のイメージ
        
        self.rect = self.image.get_rect(topleft=(x*GS, y*GS))
        
        self.moving = False  # 移動中か?
    def update(self):
        global x,y,vx,vy,direction,mx,my
        
        """プレイヤー状態を更新する。"""
    
        # プレイヤーの移動処理
        if self.moving == True:
            # ピクセル移動中ならマスにきっちり収まるまで移動を続ける
            self.rect.move_ip(vx, vy)
            if self.rect.left % GS == 0 and self.rect.top % GS == 0:  # マスにおさまったら移動完了
                self.moving = False
                x = int(self.rect.left / GS)
                y = int(self.rect.top / GS)
        else:
            # 入力があったら移動を開始する(速度をセットする)
            if y < my:
                direction = DOWN  
                vx, vy = 0, self.speed
                self.moving = True
            elif y > my:
                direction = UP
                vx, vy = 0, -self.speed
                self.moving = True
            elif x > mx:
                direction = LEFT
                vx, vy = -self.speed, 0
                self.moving = True
            elif x < mx:
                direction = RIGHT
                vx, vy = self.speed, 0
                self.moving = True
            mouse_pressed = pygame.mouse.get_pressed()
            if mouse_pressed[0]:
                mouse_pos = pygame.mouse.get_pos()
                mx = mouse_pos[0]  
                my = mouse_pos[1] 
                mx = mx // GS
                my = my // GS

        # キャラクターアニメーション(frameに応じて描画イメージを切り替える)
        self.frame += 1
        self.image = self.images[self.name][int(direction*4+self.frame/self.animcycle%4)]
    def draw(self):
        px = self.rect.topleft[0]
        py = self.rect.topleft[1]
        screen.blit(self.image, (px,py))


if __name__ == "__main__":
        main()

Player.images["player"] = split_image(pygame.image.load(ここにパスを貼り付け))
[""]にはファイル名を書きます。
player = Player("player")
("")にもファイル名を書きます。

マウス移動(マップ)

ここをクリックしてください aidiaryさんのフォルダをお借りすると速やかに実行できるかと思います。いつもaidiaryさん頼りで申し訳ないです。(汗)

rpg17 サイトへ移動

マウス移動(マップ)

import pygame
from pygame import *
import sys
import struct
import os

pygame.init()
screen=pygame.display.set_mode((640,480))
x,y = 1,1
vx,vy = 0,0
mx,my = 1,1
nx,ny = 0,0
DOWN,LEFT,RIGHT,UP = 0,1,2,3
direction = DOWN
TRANS_COLOR = (190,179,145)  # マップチップの透明色
while(True):
    screen.fill((0,0,0))
    pygame.display.update()     


    SCR_RECT = Rect(0, 0, 640, 480)
    GS = 32
    DOWN,LEFT,RIGHT,UP = 0,1,2,3

    def main():
        global game_state,chara,x,y
        pygame.init()
        screen = pygame.display.set_mode(SCR_RECT.size)
        pygame.display.set_caption("マウス移動")
        font = pygame.font.Font(フォントのパス, 30)        
        
        # キャラクターチップをロード
        load_charachips("data", "charachip.dat")

        # マップチップをロード
        load_mapchips("data", "mapchip.dat")
        # マップとプレイヤーを作成
        map = Map("field")
        player = Player("swordman_female")
        num1 = str(x)
        num2 = str(y)

        clock = pygame.time.Clock()
        running = True
        while running:
            clock.tick(60)
            offset = calc_offset(player)
            map.draw(screen, offset)
            player.draw(screen, offset)
            player.update(map,offset)
            text1 = font.render(num1+"  "+num2, True, (255,255,255))                
            screen.blit(text1, (16, 16))
            num1 = str(x)
            num2 = str(y)
                            
            pygame.display.update()
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    sys.exit()
    def load_charachips(dir, file):
        """キャラクターチップをロードしてCharacter.imagesに格納"""
        file = os.path.join(dir, file)
        fp = open(file, "r")
        for line in fp:
            line = line.rstrip()
            data = line.split(",")
            chara_id = int(data[0])
            chara_name = data[1]
            Player.images[chara_name] = split_image(load_image("charachip", "%s.png" % chara_name))
        fp.close()
    def load_mapchips(dir, file):
        """マップチップをロードしてMap.imagesに格納"""
        file = os.path.join(dir, file)
        fp = open(file, "r")
        for line in fp:
            line = line.rstrip()
            data = line.split(",")
            mapchip_id = int(data[0])
            mapchip_name = data[1]
            movable = int(data[2])  # 移動可能か?
            transparent = int(data[3])  # 背景を透明にするか?
            if transparent == 0:
                Map.images.append(load_image("mapchip", "%s.png" % mapchip_name))
            else:
                Map.images.append(load_image("mapchip", "%s.png" % mapchip_name, TRANS_COLOR))
            Map.movable_type.append(movable)
        fp.close()

    def calc_offset(player):
        """オフセットを計算する"""
        offsetx = player.rect.topleft[0] - SCR_RECT.width/2
        offsety = player.rect.topleft[1] - SCR_RECT.height/2
        return offsetx, offsety

    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

    def split_image(image):
        """128x128のキャラクターイメージを32x32の16枚のイメージに分割
        分割したイメージを格納したリストを返す"""
        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

    class Map:
        # main()のload_mapchips()でセットされる
        images = []  # マップチップ(ID->イメージ)
        movable_type = []  # マップチップが移動可能か?(0:移動不可, 1:移動可)
        def __init__(self, name):
            self.name = name
            self.row = -1  # 行数
            self.col = -1  # 列数
            self.map = []  # マップデータ(2次元リスト)
            self.charas = []  # マップにいるキャラクターリスト#追加した
            self.load()
        def draw(self, screen, offset):
            """マップを描画する"""
            offsetx, offsety = offset
            # マップの描画範囲を計算
            startx = int(offsetx / GS)
            endx = int(startx + SCR_RECT.width/GS + 1)
            starty = int(offsety / GS)
            endy = int(starty + SCR_RECT.height/GS + 1)
            # マップの描画

            for y in range(starty, endy):
                for x in range(startx, endx):
                    # マップの範囲外はデフォルトイメージで描画
                    # この条件がないとマップの端に行くとエラー発生
                    if x < 0 or y < 0 or x > self.col-1 or y > self.row-1:
                        screen.blit(self.images[self.default], (x*GS-offsetx,y*GS-offsety))
                    else:
                        screen.blit(self.images[self.map[y][x]], (x*GS-offsetx,y*GS-offsety))
        def is_movable(self, x, y):
            """(x,y)は移動可能か?"""
            # マップ範囲内か?
            if x < 0 or x > self.col-1 or y < 0 or y > self.row-1:
                return False
            # マップチップは移動可能か?
            if self.movable_type[self.map[y][x]] == 0:
                return False
            # キャラクターと衝突しないか?#追加した
            for chara in self.charas:
                if chara.x == x and chara.y == y:
                    return False       

            return True
        def load(self):
            """バイナリファイルからマップをロード"""
            file = os.path.join("data", self.name + ".map")
            fp = open(file, "rb")
            # unpack()はタプルが返されるので[0]だけ抽出
            self.row = struct.unpack("i", fp.read(struct.calcsize("i")))[0]  # 行数
            self.col = struct.unpack("i", fp.read(struct.calcsize("i")))[0]  # 列数
            self.default = struct.unpack("B", fp.read(struct.calcsize("B")))[0]  # デフォルトマップチップ
            # マップ
            self.map = [[4 for c in range(self.col)] for r in range(self.row)]
            for r in range(self.row):
                for c in range(self.col):
                    self.map[r][c] = struct.unpack("B", fp.read(struct.calcsize("B")))[0]
            fp.close()

    class Player:
        
        speed = 4  # 1フレームの移動ピクセル数
        animcycle = 24  # アニメーション速度
        frame = 0
        images = {}
        def __init__(self, name):
            self.name = name  # プレイヤー名(ファイル名と同じ)
            self.image = self.images[name][0]  # 描画中のイメージ
            
            self.rect = self.image.get_rect(topleft=(x*GS, y*GS))
            
            self.moving = False  # 移動中か?
        def update(self, map,offset):
            global x,y,vx,vy,direction,mx,my
            offsetx, offsety = offset
            px = self.rect.topleft[0]
            py = self.rect.topleft[1]
            
            """プレイヤー状態を更新する。
            mapは移動可能かの判定に必要。"""
            # プレイヤーの移動処理
            if self.moving == True:
                # ピクセル移動中ならマスにきっちり収まるまで移動を続ける
                self.rect.move_ip(vx, vy)
                if self.rect.left % GS == 0 and self.rect.top % GS == 0:  # マスにおさまったら移動完了
                    self.moving = False
                    x = int(self.rect.left / GS)
                    y = int(self.rect.top / GS)
            else:
                # キー入力があったら移動を開始する(速度をセットする)
                if y < my:
                    direction = DOWN  # 移動できるかに関係なく向きは変える
                    if map.is_movable(x, y+1):
                        vx, vy = 0, self.speed
                        self.moving = True
                elif x > mx:
                    direction = LEFT
                    if map.is_movable(x-1, y):
                        vx, vy = -self.speed, 0
                        self.moving = True
                elif x < mx:
                    direction = RIGHT
                    if map.is_movable(x+1, y):
                        vx, vy = self.speed, 0
                        self.moving = True
                elif y > my:
                    direction = UP
                    if map.is_movable(x, y-1):
                        vx, vy = 0, -self.speed
                        self.moving = True
                mouse_pressed = pygame.mouse.get_pressed()
                if mouse_pressed[0]:
                    mouse_pos = pygame.mouse.get_pos()
                    mx = mouse_pos[0] +offsetx 
                    my = mouse_pos[1] +offsety
                    mx = mx // GS
                    my = my // GS

            # キャラクターアニメーション(frameに応じて描画イメージを切り替える)
            self.frame += 1
            self.image = self.images[self.name][int(direction*4+self.frame/self.animcycle%4)]
        def draw(self, screen, offset):
            """オフセットを考慮してプレイヤーを描画"""
            offsetx, offsety = offset
            px = self.rect.topleft[0]
            py = self.rect.topleft[1]
            screen.blit(self.image, (px-offsetx, py-offsety))#ないと透明になる


    if __name__ == "__main__":
            main()

    for event in pygame.event.get():
        if event.type==QUIT:
            pygame.quit()
            sys.exit()

セーブとロード

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

Sキーを押すと、座標を保存します。別の場所に移動して、Lキーを押してみてください。座標を保存した場所に戻ります。

import pygame
from pygame.locals import *
import sys
import pickle

pygame.init()
screen = pygame.display.set_mode((160,160))
pygame.display.set_caption('save load')
x,y = 2,2
GS = 32
#ここにキャラクター画像のパスを貼り付ける
player = pygame.image.load(パス)

while (1):
    screen.fill((0,0,0))
    screen.blit(player, (x*GS, y*GS))
    pygame.display.update()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        elif event.type==KEYDOWN:
            if event.key==K_DOWN:
                y += 1      
            elif event.key==K_UP:
                y -= 1
            elif event.key==K_RIGHT:
                x += 1
            elif event.key==K_LEFT:
                x -= 1

            elif event.key==K_s:
                # ゲームの状態を辞書として定義
                save_data = {
                    "x": x,"y": y           
                }

                # ゲームの状態をファイルに保存
                with open('save_data.pickle', 'wb') as file:
                    pickle.dump(save_data, file)
                    print("セーブしました")
            elif event.key==K_l:
                # セーブデータを読み込む
                with open('save_data.pickle', 'rb') as file:
                    loaded_save_data = pickle.load(file)
                    x = save_data["x"]
                    y = save_data["y"]
                    print("ロードしました")

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


0
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?