カニ足移動を直す
前回までのプレイヤーはどの方向に移動してもこっちを向いていました(こっち見んな!)。これはドラクエ1と同じ移動方式です。これだとあまりかっこよくないので移動する方向をちゃんと向くようにしてみます。
サンプルスクリプト
#!/usr/bin/env python # -*- coding: utf-8 -*- import pygame from pygame.locals import * import sys import os SCR_RECT = Rect(0, 0, 640, 480) ROW,COL = 15,20 GS = 32 DOWN,LEFT,RIGHT,UP = 0,1,2,3 map = [[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]] 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 is -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 def draw_map(screen): """マップを描画する""" for r in range(ROW): for c in range(COL): if map[r][c] == 0: screen.blit(grassImg, (c*GS,r*GS)) elif map[r][c] == 1: screen.blit(waterImg, (c*GS,r*GS)) def is_movable(x, y): """(x,y)は移動可能か?""" # マップ範囲内か? if x < 0 or x > COL-1 or y < 0 or y > ROW-1: return False # マップチップは移動可能か? if map[y][x] == 1: # 水は移動できない return False return True pygame.init() screen = pygame.display.set_mode(SCR_RECT.size) pygame.display.set_caption(u"PyRPG 06 カニ足移動を直す") # イメージロード playerImgList = split_image(load_image("player.png")) # プレイヤー grassImg = load_image("grass.png") # 草地 waterImg = load_image("water.png") # 水 x,y = 1,1 # プレイヤーの位置(単位:マス) direction = DOWN animcycle = 24 # アニメーション速度 frame = 0 clock = pygame.time.Clock() while True: clock.tick(60) # 経過フレーム数に応じて表示する画像を変える frame += 1 playerImg = playerImgList[direction*4+frame/animcycle%4] draw_map(screen) # マップ描画 screen.blit(playerImg, (x*GS,y*GS)) # プレイヤー描画 pygame.display.update() for event in pygame.event.get(): if event.type == QUIT: sys.exit() if event.type == KEYDOWN and event.key == K_ESCAPE: sys.exit() # プレイヤーの移動処理 if event.type == KEYDOWN and event.key == K_DOWN: direction = DOWN if is_movable(x, y+1): y += 1 if event.type == KEYDOWN and event.key == K_LEFT: direction = LEFT if is_movable(x-1, y): x -= 1 if event.type == KEYDOWN and event.key == K_RIGHT: direction = RIGHT if is_movable(x+1, y): x += 1 if event.type == KEYDOWN and event.key == K_UP: direction = UP if is_movable(x, y-1): y -= 1
イメージの分割
まず、プレイヤーが各方向を向いている画像を用意します。
足踏みさせる(2008/5/29)で紹介したようにこの一枚絵を32x32ピクセル、4x4=16枚の画像に分割してリストに格納します。今回はforループが二重になっている点に注意してください。
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
この関数は下のように使います。
# イメージロード playerImgList = split_image(load_image("player.png")) # プレイヤー
playerImgListには分割された画像16枚が入ります。たとえば、playerImgList[4]には上の4番目の画像(左を向いたプレイヤー)が格納されています。
どの方向を向いているか?
DOWN,LEFT,RIGHT,UP = 0,1,2,3 direction = DOWN # プレイヤーの移動処理 if event.type == KEYDOWN and event.key == K_DOWN: direction = DOWN if is_movable(x, y+1): y += 1 if event.type == KEYDOWN and event.key == K_LEFT: direction = LEFT if is_movable(x-1, y): x -= 1 if event.type == KEYDOWN and event.key == K_RIGHT: direction = RIGHT if is_movable(x+1, y): x += 1 if event.type == KEYDOWN and event.key == K_UP: direction = UP if is_movable(x, y-1): y -= 1
向いている方向によって画像を切り替えたいので、まずは、プレイヤーの向いている方向を表す変数directionを用意します。 directionはDOWN(下向き)で初期化しています。次に移動したときに方向を変えたいのでキーイベントの移動処理の部分に向きを変える処理を付け加えます。移動した方向(キーを押した方向)に応じてdirectionの値を変えています。ここで、移動先に障害物があって移動できなかった場合でも向いている方向を変えている点に注意してください。ドラクエでは壁があって進めなくてもプレイヤーの向きだけは変わっていました。
キャラクターアニメーション
# 方向がなく足踏みさせるだけの場合 playerImg = playerImgList[frame/animcycle%4] ↓ # 向いている方向がある場合 playerImg = playerImgList[direction*4+frame/animcycle%4]
最後にプレイヤーが向いている方向に合わせてキャラクターアニメーションを変える処理です。これは、少し修正するだけで簡単に直せます。足踏みさせる(2008/5/29)では方向がなかったのでdirectionは関係ありませんでしたが、今回は directionによって表示する画像を変えます。これは、添字にdirection*4を足してやるだけでOKです。なぜかは実際に計算してみるとわかります。frame/animcycle%4の部分は0〜3の値を取ることは足踏みさせる(2008/5/29)で解説済みです。なので各directionを取るときの添字の値は
direction=DOWN (0) → 0 〜 3 direction=LEFT (1) → 4 〜 7 direction=RIGHT (2) → 8 〜 11 direction=UP (3) → 12 〜15
となります。イメージの分割の画像番号と比べてみてください。ちゃんとdirectionと対応した画像が選択されてますね!