本記事では、プレイヤーが木を伐採することで「木材」と「リンゴ」を取得できるバックパック(インベントリ)システムを実装する。
インベントリ構造の設計
プレイヤークラスに辞書型の item_inventory を導入し、以下のアイテムを管理する:
- wood(木材)
- apple(リンゴ)
- corn(トウモロコシ)
- tomato(トマト)
アイテム追加メカニズム
Level クラスに player_add(item) メソッドを定義し、プレイヤーのインベントリを更新する。このメソッドは Tree クラスから呼び出されるため、Tree の初期化時にコールバック関数として渡す必要がある。
Tree クラスとの連携
Tree インスタンス生成時に player_add 関数を引数として受け取り、内部で保持する。木が破壊された際には木材を、リンゴが収穫された際にはリンゴをそれぞれインベントリに追加する。
コード変更ポイント
Player クラス (player.py)
class Player(pygame.sprite.Sprite):
def __init__(self, pos, group, collision_sprites, tree_sprites):
# ... 既存コード ...
self.item_inventory = {
'wood': 0,
'apple': 0,
'corn': 0,
'tomato': 0
}
self.tree_sprites = tree_sprites
Level クラス (level.py)
class Level:
def setup(self):
# ... 他のオブジェクト初期化 ...
for obj in tmx_data.get_layer_by_name('Trees'):
Tree(
pos=(obj.x, obj.y),
surf=obj.image,
groups=[self.all_sprites, self.collision_sprites, self.tree_sprites],
name=obj.name,
on_item_collect=self.player_add # コールバック関数を渡す
)
for obj in tmx_data.get_layer_by_name('Player'):
if obj.name == 'Start':
self.player = Player(
pos=(obj.x, obj.y),
group=self.all_sprites,
collision_sprites=self.collision_sprites,
tree_sprites=self.tree_sprites
)
def player_add(self, item_name):
if item_name in self.player.item_inventory:
self.player.item_inventory[item_name] += 1
Tree クラス (sprites.py)
class Tree(Generic):
def __init__(self, pos, surf, groups, name, on_item_collect):
super().__init__(pos, surf, groups)
self.on_item_collect = on_item_collect
# ... 他の初期化 ...
def damage(self):
self.health -= 1
# リンゴをランダムに収穫
if len(self.apple_sprites.sprites()) > 0:
apple = choice(self.apple_sprites.sprites())
Particle(pos=apple.rect.topleft, surf=apple.image, groups=self.groups[0], z=LAYERS['fruit'])
self.on_item_collect('apple')
apple.kill()
# 木が倒れた場合
if self.health <= 0 and self.alive:
Particle(self.rect.topleft, self.image, self.groups[0], LAYERS['fruit'], 300)
self.image = self.stump_surf
self.rect = self.image.get_rect(midbottom=self.rect.midbottom)
self.hitbox = self.rect.copy().inflate(-10, -self.rect.height * 0.6)
self.on_item_collect('wood')
self.alive = False