![見出し画像](https://assets.st-note.com/production/uploads/images/20204218/rectangle_large_type_2_c800d9f70b0991681c2f5c8c34dbdd0a.png?width=1200)
pyxelでRPG風のものを作る(2)
前回作ったRPGもどきは移動しかできなかったのでプレイヤーの攻撃処理と敵を追加して、もう少しゲームらしくしていきます。以下に前回のリンクを張っておきます。
それでは始めていきます。目標はなるべくコードがごちゃらないように、そして今後の拡張性にも少し気を使ってみます。今回は攻撃処理を追加して、攻撃の座標を取得するところまでです。
def __init__(self):
#Player status
self.Player = Player(8, 56)
self.player_move = 0
self.atc_flug = False
self.atc_count = 0
self.p_atc_x = 0
self.p_atc_y = 0
#Map status
self.stage_flug = 1
self.map_count_x = 1
self.map_count_y = 1
self.map_x = 0
self.map_y = 0
self.map_move = 0
#System status
self.game_start = False
self.game_over = False
pyxel.init(128,128)
#Image read
pyxel.load('C:/pyxel/image/pknights.pyxres')
pyxel.run(self.update, self.draw)
まず、init関数に今回使う変数を追加します。atc_flugは攻撃をしているかの判定、atc_countは攻撃硬直時間、p_atc_xとp_atc_yは攻撃座標に使います。
def update(self):
if pyxel.btnp(pyxel.KEY_S):
self.game_start = True
if pyxel.btnp(pyxel.KEY_Q):
pyxel.quit()
#Player attack
if pyxel.btnp(pyxel.KEY_SPACE):
self.atc_flug = True
#Player controll
self.Player_ctr()
update関数です。ここは変更はありません。攻撃処理はPlayer_ctrに持たせることとします。
def draw(self):
pyxel.cls(0)
#Draw tilemap
pyxel.bltm(0,0,0,0 + self.map_x,0 + self.map_y,16,16)
#Draw player
if self.atc_flug == True:
if self.Player.player_m == 0:
pyxel.blt(self.Player.player_x,self.Player.player_y,
0,0,16,8,8,14)
pyxel.blt(self.Player.player_x+8,self.Player.player_y,
0,0,24,8,8,14)
elif self.Player.player_m == 1:
pyxel.blt(self.Player.player_x,self.Player.player_y,
0,8,16,8,8,14)
pyxel.blt(self.Player.player_x-8,self.Player.player_y,
0,8,24,8,8,14)
elif self.Player.player_m == 2:
pyxel.blt(self.Player.player_x,self.Player.player_y,
0,16,16,8,8,14)
pyxel.blt(self.Player.player_x,self.Player.player_y-8,
0,16,24,8,8,14)
elif self.Player.player_m == 3:
pyxel.blt(self.Player.player_x,self.Player.player_y,
0,24,16,8,8,14)
pyxel.blt(self.Player.player_x,self.Player.player_y+8,
0,24,24,8,8,14)
else:
if self.Player.player_m == 0:
pyxel.blt(self.Player.player_x,self.Player.player_y,
0,0,0+self.Player.player_m2*8,8,8,14)
elif self.Player.player_m == 1:
pyxel.blt(self.Player.player_x,self.Player.player_y,
0,8,0+self.Player.player_m2*8,8,8,14)
elif self.Player.player_m == 2:
pyxel.blt(self.Player.player_x,self.Player.player_y,
0,16,0+self.Player.player_m2*8,8,8,14)
elif self.Player.player_m == 3:
pyxel.blt(self.Player.player_x,self.Player.player_y,
0,24,0+self.Player.player_m2*8,8,8,14)
#Draw title text
if self.game_start == False:
pyxel.cls(0)
pyxel.text(35, 40, "PYXEL KNIGHTS", 7)
pyxel.text(45, 70, "S = START ", 7)
pyxel.text(45, 80, "Q = QUIT ", 7)
else: #Draw player hp
pyxel.text(2, 122, "HP="+ str(self.Player.player_h),7)
#Draw gameover text
if self.game_over == True:
pyxel.cls(0)
pyxel.text(20, 30, "GAME OVER!", 7)
pyxel.text(80, 70, "R = RETRY ", 7)
pyxel.text(80, 80, "Q = QUIT ", 7)
draw関数です。今回追加したatc_flugの値を条件にして、プレイヤーの描画を変えていきます。攻撃中はプレイヤーの方向に対応した上下左右のマスに攻撃描画をします。
また、前回に追加してプレイヤーのHPとゲームオーバー時の描画を追加しています。
def Player_ctr(self):
#Get map coordinate
x = 16*(self.map_count_x-1)
y = 16*(self.map_count_y-1)
#Get player coordinate
move_map_x = int(self.Player.player_x / 8 + x)
move_map_y = int(self.Player.player_y / 8 + y)
#Plyer move
self.player_move = self.player_move + 1
if self.player_move > 6:
if pyxel.tilemap(0).get(move_map_x, move_map_y-1) < 32:
#Up
if pyxel.btnp(pyxel.KEY_UP):
self.Player.player_y = self.Player.player_y - 8
self.player_move = 0
self.Player.player_m = 2
if self.Player.player_m2 == 0: #Move animation
self.Player.player_m2 = 1
else:
self.Player.player_m2 = 0
if (self.Player.player_y - 8) < 0: #When map change
self.map_y = self.map_y - 16
self.Player.update(56, 120)
self.map_count_y = self.map_count_y - 1
self.map_move = 1
if pyxel.tilemap(0).get(move_map_x, move_map_y+1) < 32:
#Down
if pyxel.btnp(pyxel.KEY_DOWN):
self.Player.player_y = self.Player.player_y + 8
self.player_move = 0
self.Player.player_m = 3
if self.Player.player_m2 == 0: #Move animation
self.Player.player_m2 = 1
else:
self.Player.player_m2 = 0
if (self.Player.player_y + 8) > 128: #When map change
self.map_y = self.map_y + 16
self.Player.update(56, 8)
self.map_count_y = self.map_count_y + 1
self.map_move = 1
if pyxel.tilemap(0).get(move_map_x+1, move_map_y) < 32:
#Right
if pyxel.btnp(pyxel.KEY_RIGHT):
self.Player.player_x = self.Player.player_x + 8
self.player_move = 0
self.Player.player_m = 0
if self.Player.player_m2 == 0: #Move animation
self.Player.player_m2 = 1
else:
self.Player.player_m2 = 0
if (self.Player.player_x + 8) > 128: #When map change
self.map_x = self.map_x + 16
self.Player.update(8, 56)
self.map_count_x = self.map_count_x + 1
self.map_move = 1
if pyxel.tilemap(0).get(move_map_x-1, move_map_y) < 32:
#Left
if pyxel.btnp(pyxel.KEY_LEFT):
self.Player.player_x = self.Player.player_x - 8
self.player_move = 0
if self.Player.player_m2 == 0: #Move animation
self.Player.player_m2 = 1
else:
self.Player.player_m2 = 0
self.Player.player_m = 1
if (self.Player.player_x - 8) < 0: #When map change
self.map_x = self.map_x - 16
self.Player.update(120, 56)
self.map_count_x = self.map_count_x - 1
self.map_move = 1
if self.atc_flug == True:
self.atc_count = self.atc_count + 1
if self.atc_count > 8:
self.atc_count = 0
self.p_atc_x = 0
self.p_atc_y = 0
self.atc_flug = False
else:
if self.Player.player_m == 0:
self.p_atc_x = self.Player.player_x + 8
self.p_atc_y = self.Player.player_y
elif self.Player.player_m == 1:
self.p_atc_x = self.Player.player_x - 8
self.p_atc_y = self.Player.player_y
elif self.Player.player_m == 2:
self.p_atc_x = self.Player.player_x
self.p_atc_y = self.Player.player_y - 8
elif self.Player.player_m == 3:
self.p_atc_x = self.Player.player_x
self.p_atc_y = self.Player.player_y + 8
print(str(self.p_atc_x) + "," + str(self.p_atc_y))
Player_ctr関数です。攻撃処理のために if self.atk_flug == Trueから以下の部分を追加しました。
まずは、atc_countをカウントアップして攻撃処理を8フレーム持続するようにします。atc_count>8になった時点で、各種変数を0にして、atk_flugをFalseにします。
次に攻撃中の場合に攻撃座標を取得するようにします。player_mの値によって上下左右に分けて、プレイヤーの座標から8ずらします。
最後にprintを使ってコンソールで座標を見れるようにしておきましょう。
例えば初期位置の(8,56)で右を向いて攻撃すると、攻撃座標は(16,56)になります。
class Player:
def __init__(self, x, y):
self.player_x = x
self.player_y = y
self.player_h = 100
self.player_d = 0
self.player_m = 0
self.player_m2 = 0
def update(self, x, y):
self.player_x = x
self.player_y = y
App()
クラス部分には特に変更はありません。
全てつなげたソースコードは以下になります。
# -*- coding: utf-8 -*-
import pyxel
class App:
def __init__(self):
#Player status
self.Player = Player(8, 56)
self.player_move = 0
self.atc_flug = False
self.atc_count = 0
self.p_atc_x = 0
self.p_atc_y = 0
#Map status
self.stage_flug = 1
self.map_count_x = 1
self.map_count_y = 1
self.map_x = 0
self.map_y = 0
self.map_move = 0
#System status
self.game_start = False
self.game_over = False
pyxel.init(128,128)
#Image read
pyxel.load('C:/pyxel/image/pknights.pyxres')
pyxel.run(self.update, self.draw)
def update(self):
if pyxel.btnp(pyxel.KEY_S):
self.game_start = True
if pyxel.btnp(pyxel.KEY_Q):
pyxel.quit()
#Player attack
if pyxel.btnp(pyxel.KEY_SPACE):
self.atc_flug = True
#Player controll
self.Player_ctr()
def draw(self):
pyxel.cls(0)
#Draw tilemap
pyxel.bltm(0,0,0,0 + self.map_x,0 + self.map_y,16,16)
#Draw player
if self.atc_flug == True:
if self.Player.player_m == 0:
pyxel.blt(self.Player.player_x,self.Player.player_y,
0,0,16,8,8,14)
pyxel.blt(self.Player.player_x+8,self.Player.player_y,
0,0,24,8,8,14)
elif self.Player.player_m == 1:
pyxel.blt(self.Player.player_x,self.Player.player_y,
0,8,16,8,8,14)
pyxel.blt(self.Player.player_x-8,self.Player.player_y,
0,8,24,8,8,14)
elif self.Player.player_m == 2:
pyxel.blt(self.Player.player_x,self.Player.player_y,
0,16,16,8,8,14)
pyxel.blt(self.Player.player_x,self.Player.player_y-8,
0,16,24,8,8,14)
elif self.Player.player_m == 3:
pyxel.blt(self.Player.player_x,self.Player.player_y,
0,24,16,8,8,14)
pyxel.blt(self.Player.player_x,self.Player.player_y+8,
0,24,24,8,8,14)
else:
if self.Player.player_m == 0:
pyxel.blt(self.Player.player_x,self.Player.player_y,
0,0,0+self.Player.player_m2*8,8,8,14)
elif self.Player.player_m == 1:
pyxel.blt(self.Player.player_x,self.Player.player_y,
0,8,0+self.Player.player_m2*8,8,8,14)
elif self.Player.player_m == 2:
pyxel.blt(self.Player.player_x,self.Player.player_y,
0,16,0+self.Player.player_m2*8,8,8,14)
elif self.Player.player_m == 3:
pyxel.blt(self.Player.player_x,self.Player.player_y,
0,24,0+self.Player.player_m2*8,8,8,14)
#Draw title text
if self.game_start == False:
pyxel.cls(0)
pyxel.text(35, 40, "PYXEL KNIGHTS", 7)
pyxel.text(45, 70, "S = START ", 7)
pyxel.text(45, 80, "Q = QUIT ", 7)
else: #Draw player hp
pyxel.text(2, 122, "HP="+ str(self.Player.player_h),7)
#Draw gameover text
if self.game_over == True:
pyxel.cls(0)
pyxel.text(20, 30, "GAME OVER!", 7)
pyxel.text(80, 70, "R = RETRY ", 7)
pyxel.text(80, 80, "Q = QUIT ", 7)
def Player_ctr(self):
#Get map coordinate
x = 16*(self.map_count_x-1)
y = 16*(self.map_count_y-1)
#Get player coordinate
move_map_x = int(self.Player.player_x / 8 + x)
move_map_y = int(self.Player.player_y / 8 + y)
#Plyer move
self.player_move = self.player_move + 1
if self.player_move > 6:
if pyxel.tilemap(0).get(move_map_x, move_map_y-1) < 32:
#Up
if pyxel.btnp(pyxel.KEY_UP):
self.Player.player_y = self.Player.player_y - 8
self.player_move = 0
self.Player.player_m = 2
if self.Player.player_m2 == 0: #Move animation
self.Player.player_m2 = 1
else:
self.Player.player_m2 = 0
if (self.Player.player_y - 8) < 0: #When map change
self.map_y = self.map_y - 16
self.Player.update(56, 120)
self.map_count_y = self.map_count_y - 1
self.map_move = 1
if pyxel.tilemap(0).get(move_map_x, move_map_y+1) < 32:
#Down
if pyxel.btnp(pyxel.KEY_DOWN):
self.Player.player_y = self.Player.player_y + 8
self.player_move = 0
self.Player.player_m = 3
if self.Player.player_m2 == 0: #Move animation
self.Player.player_m2 = 1
else:
self.Player.player_m2 = 0
if (self.Player.player_y + 8) > 128: #When map change
self.map_y = self.map_y + 16
self.Player.update(56, 8)
self.map_count_y = self.map_count_y + 1
self.map_move = 1
if pyxel.tilemap(0).get(move_map_x+1, move_map_y) < 32:
#Right
if pyxel.btnp(pyxel.KEY_RIGHT):
self.Player.player_x = self.Player.player_x + 8
self.player_move = 0
self.Player.player_m = 0
if self.Player.player_m2 == 0: #Move animation
self.Player.player_m2 = 1
else:
self.Player.player_m2 = 0
if (self.Player.player_x + 8) > 128: #When map change
self.map_x = self.map_x + 16
self.Player.update(8, 56)
self.map_count_x = self.map_count_x + 1
self.map_move = 1
if pyxel.tilemap(0).get(move_map_x-1, move_map_y) < 32:
#Left
if pyxel.btnp(pyxel.KEY_LEFT):
self.Player.player_x = self.Player.player_x - 8
self.player_move = 0
if self.Player.player_m2 == 0: #Move animation
self.Player.player_m2 = 1
else:
self.Player.player_m2 = 0
self.Player.player_m = 1
if (self.Player.player_x - 8) < 0: #When map change
self.map_x = self.map_x - 16
self.Player.update(120, 56)
self.map_count_x = self.map_count_x - 1
self.map_move = 1
if self.atc_flug == True:
self.atc_count = self.atc_count + 1
if self.atc_count > 8:
self.atc_count = 0
self.p_atc_x = 0
self.p_atc_y = 0
self.atc_flug = False
else:
if self.Player.player_m == 0:
self.p_atc_x = self.Player.player_x + 8
self.p_atc_y = self.Player.player_y
elif self.Player.player_m == 1:
self.p_atc_x = self.Player.player_x - 8
self.p_atc_y = self.Player.player_y
elif self.Player.player_m == 2:
self.p_atc_x = self.Player.player_x
self.p_atc_y = self.Player.player_y - 8
elif self.Player.player_m == 3:
self.p_atc_x = self.Player.player_x
self.p_atc_y = self.Player.player_y + 8
print(str(self.p_atc_x) + "," + str(self.p_atc_y))
class Player:
def __init__(self, x, y):
self.player_x = x
self.player_y = y
self.player_h = 100
self.player_d = 0
self.player_m = 0
self.player_m2 = 0
def update(self, x, y):
self.player_x = x
self.player_y = y
App()
今回取得できた攻撃座標を使って、次回は敵を出現させて攻撃するところまで実装していこうと思います。
ここまで読んでいただきありがとうございます!