見出し画像

Lesson12 ボスキャラをつくろう

ボスキャラをつくります。サイズも動きも大きくしたいなと思います。

ここまで登場してきた敵キャラたちは自分で回転はしました。でもそれはあくまで自転でした。今回の敵キャラはある一定の場所を中心に公転させてみようと思います。

そのために数学的な計算方法を取り入れます。高校で習うものです。

とはいえ、当noteではもちろんコピペでOKです。細かいことは後半の解説でうだうだと述べたいと思います。

ではさっそくつくっていきましょう!


画像データ

いつものように画像データをどうぞ。最初に一括ダウンロードしていれば何もせずOKです。画像は game フォルダ > image フォルダに格納してください。

ではコードをいじっていきましょう。

enemy.py

#### enemy.py ####

############################################################################################
#### ライブラリの読み込み ####

############################################################################################
# ボスキャラの基本設定
class BossEnemy(Enemy):
    #### 初期化関数 ####
    def __init__(self, x, y, image, image_bomb, speed_x, speed_y, rotation_speed, start_angle, atk, enemy_hp, size_multiplier, dead_flag, circle_R):
        super().__init__(x, y, image, image_bomb, speed_x, speed_y, rotation_speed, start_angle, atk, enemy_hp, size_multiplier)
        self.dead_flag = dead_flag
        self.circle_R = circle_R

    #### 再表示関数 ####
    def update(self,player_turn):
        # 大回転の動作
        if player_turn == False:
            self.angle += self.rotation_speed
        else:
            self.angle = self.angle
        if self.enemy_hp > 0:
            orbit_x = self.x + int(self.circle_R * math.cos(math.radians(self.angle)))
            orbit_y = self.y - int(self.circle_R * math.sin(math.radians(self.angle)))
            rotation_ang = 90 + self.angle
            rotated_image = pygame.transform.rotate(self.original_image, rotation_ang)
            self.rect = rotated_image.get_rect(center=(orbit_x, orbit_y))
            self.image = rotated_image
            self.path.append((self.x, self.y))
        else:
            self.image =self.image_bomb
            self.speed_x = 0
            self.speed_y = 0
            self.rotation_speed = 0
            self.rect = self.image.get_rect(center=(self.x, self.y))
            if pygame.time.get_ticks()>self.explosion_time:
                self.kill()

############################################################################################

stage1.py

#### stage1.py ####

############################################################################################
#### ライブラリの読み込み ####

from enemy import Enemy,BossEnemy


############################################################################################ 
#### メインプログラム ####
def main(hp,mp,idx):
    ########################################################################################
    #### 初期設定 ####


    ########################################################################################
    #### コマンドボタンのスプライト ####

    
    ########################################################################################
    #### 壁のスプライト ####


    ########################################################################################
    #### ザコ敵のスプライト ####

    
    ########################################################################################
    #### ザコ敵のクローンスプライト ####

    
    ########################################################################################
    #### 同じ敵を複数作る場合 ####
    #### エネミーのスプライト ####

    
    ########################################################################################
    #### ボスキャラのスプライト ####
    boss_width = 200        # 横幅
    boss_height = 200       # 高さ
    image1 = pygame.image.load("image/space_kaseijin.png")
    image_boss = pygame.transform.scale(image1, (boss_width, boss_height))
    image2 = pygame.image.load("image/bakuhatsu4.png")
    image_bomb = pygame.transform.scale(image2, (boss_width, boss_height))
    boss_enemy_params = {
        'x': 780,
        'y': 360,
        'image': image_boss,
        'image_bomb': image_bomb,
        'speed_x': 0,
        'speed_y': 0,
        'rotation_speed': 5,
        'start_angle': -90,
        'atk': 5,
        'enemy_hp': 5,
        'size_multiplier': 1.0,
        'dead_flag': False,
        'circle_R': 100
        }
    boss_enemy = BossEnemy(**boss_enemy_params)
    single_enemies.add(boss_enemy)


    ########################################################################################


それぞれに追記できたら下記を実行してください。

>python main.py

するとこんな感じになるはずです☆

実行結果1: でっかいタコが出現


実行結果2: グルングルン回りますね

でっかいタコがグルングルンしましたか?これが今回追加したボスキャラです。パラメータを色々と変えることでいろんな動きができるようになりました。

特筆すべきは回転の質です。公転してます。

ある場所を中心としてグルングルンしてくれます。回転(自転)しながらさらに回転(公転)させることもできますが、今回は頭の方向を中心としています。

この動きが加わると敵キャラ制作に幅が産まれそうですね★


それでは詳しく解説していきます。
今回で敵キャラが出揃うので特別にすべて無料で公開していきます。


enemy.py

#### enemy.py ####

############################################################################################
#### ライブラリの読み込み ####

############################################################################################
# ボスキャラの基本設定
class BossEnemy(Enemy):
    #### 初期化関数 ####
    def __init__(self, x, y, image, image_bomb, speed_x, speed_y, rotation_speed, start_angle, atk, enemy_hp, size_multiplier, dead_flag, circle_R):
        super().__init__(x, y, image, image_bomb, speed_x, speed_y, rotation_speed, start_angle, atk, enemy_hp, size_multiplier)
        self.dead_flag = dead_flag      # 即死フラグ(未実装)
        self.circle_R = circle_R        # 大回転の半径

エネミークラスというのを以前作りましたが、今回はそれのバージョンアップ版としてボスエネミークラスというのをつくりました。

class BossEnemy(Enemy): の部分で基本パラメータはエネミークラスから継承させています。こうすることでエネミークラスに使っていたものがすべてボスエネミーでも使えるようになります。

また新たなパラメータとして「即死フラグ」と「大回転の半径」を新設しました。
「大回転の半径」で中心から離れた位置を公転できるようになります。
「即死フラグ」はまだ実装していません。うちの生徒さんが「即死攻撃」が好きなので入れてありますが、そのうち使えるようになるといいなと思っています。

    #### 再表示関数 ####
    def update(self,player_turn):
        # 大回転の動作
        if player_turn == False:                                                    # 動作中
            self.angle += self.rotation_speed                                       # 円周上を移動
        else:                                                                       # 一時停止中
            self.angle = self.angle                                                 # 回転停止
        if self.enemy_hp > 0:
            orbit_x = self.x + int(self.circle_R * math.cos(math.radians(self.angle)))  # 円運動の x 座標計算
            orbit_y = self.y - int(self.circle_R * math.sin(math.radians(self.angle)))  # 円運動の y 座標計算
            rotation_ang = 90 + self.angle                                              # 画像の回転角度
            rotated_image = pygame.transform.rotate(self.original_image, rotation_ang)  # 画像を回転
            self.rect = rotated_image.get_rect(center=(orbit_x, orbit_y))               # 円周の座標に画像の中心を合わせる
            self.image = rotated_image
            self.path.append((self.x, self.y))
        else:
            self.image =self.image_bomb                                 # 爆発画像をセット
            self.speed_x = 0                                            # 移動停止
            self.speed_y = 0                                            # 移動停止
            self.rotation_speed = 0                                     # 回転停止
            self.rect = self.image.get_rect(center=(self.x, self.y))    # 新座標にセット
            if pygame.time.get_ticks()>self.explosion_time:             # 1秒経過したら
                self.kill()                                             # グループから削除

############################################################################################

大回転の座標(位置)を数学を用いて計算し、新たに描画するように再表示関数をつくっています。

import math

というライブラリ読み込みを覚えていますか?やっとここで出番です。
数学的な計算をするためのライブラリです。今回は二か所で使っています。

math.cos(math.radians(self.angle))
  意味:「数学の cos(コサイン)を使って角度を計算」
math.sin(math.radians(self.angle))
  意味:「数学の sin(サイン)を使って角度を計算」

コサインってなに?

三角比と呼ばれる数学用語です。詳しくは高校数学で勉強しますが、要点をまとめると「大回転の半径とコサインをかけ算すると横方向(x)の位置が判明する」という使い方です。
なのでコサインを使ってx座標を計算して再表示させています。

サインってなに?

三角比と呼ばれる数学用語です。詳しくは高校数学で勉強しますが、要点をまとめると「大回転の半径とサインをかけ算すると縦方向()の位置が判明する」という使い方です。
なのでサインを使って座標を計算して再表示させています。

それぞれで使う角度もラジアン(rad)で計算しています。
ディグリー(30°など)で計算するとなんかうまくいきませんでした。

ラジアンってなに?

教えません。高校数学で勉強してください★(逃げ逃げ…)

他には?

ザコエネミー同様、ボスエネミーにもHPが存在します。0になると爆発するように組んであります。つまり今後プレイヤー側にも攻撃手段が実装されるということです。お楽しみに★


stage1.py

#### ライブラリの読み込み ####

from enemy import Enemy,BossEnemy       # enemy.pyからEnemyクラス、BossEnemyクラスを読み込む

おなじみライブラリ読み込みです。 BossEnemy クラスを読み込んでいます。

    #### ボスキャラのスプライト ####
    boss_width = 200        # 横幅
    boss_height = 200       # 高さ
    image1 = pygame.image.load("image/space_kaseijin.png")                  # 画像読込
    image_boss = pygame.transform.scale(image1, (boss_width, boss_height))  # サイズ変更
    image2 = pygame.image.load("image/bakuhatsu4.png")                      # 画像読込
    image_bomb = pygame.transform.scale(image2, (boss_width, boss_height))  # サイズ変更
    boss_enemy_params = {               # ボスのパラメータ
        'x': 780,                       # 初期 x 座標
        'y': 360,                       # 初期 y 座標
        'image': image_boss,            # 通常画像
        'image_bomb': image_bomb,       # 爆発画像
        'speed_x': 0,                   # x方向への移動速度
        'speed_y': 0,                   # y方向への移動速度
        'rotation_speed': 5,            # 回転速度
        'start_angle': -90,             # 初期角度
        'atk': 5,                       # ダメージ倍率
        'enemy_hp': 5,                  # HP
        'size_multiplier': 1.0,         # サイズ倍率
        'dead_flag': False,             # 一撃フラグ(未実装)
        'circle_R': 100                 # 大回転の半径
        }
    boss_enemy = BossEnemy(**boss_enemy_params)                 # Boss_Enemyクラスを継承
    single_enemies.add(boss_enemy)                              # リストに追加

ボスエネミーのパラメータを設定して、インスタンスを生成しています。

生成されたインスタンスは single_enemies というグループに追加しています。UFO単体と同じグループですね。

同じグループがゲームループにすでに記載してあるのですぐに表示されるようになります。

以上でボスエネミーの実装を終わります。

ここからはいつものように解説付きコードを掲載しておきます。


enemy.py

#### enemy.py ####

############################################################################################
#### ライブラリの読み込み ####

############################################################################################
# ボスキャラの基本設定
class BossEnemy(Enemy):
    #### 初期化関数 ####
    def __init__(self, x, y, image, image_bomb, speed_x, speed_y, rotation_speed, start_angle, atk, enemy_hp, size_multiplier, dead_flag, circle_R):
        super().__init__(x, y, image, image_bomb, speed_x, speed_y, rotation_speed, start_angle, atk, enemy_hp, size_multiplier)
        self.dead_flag = dead_flag      # 即死フラグ(未実装)
        self.circle_R = circle_R        # 大回転の半径

    #### 再表示関数 ####
    def update(self,player_turn):
        # 大回転の動作
        if player_turn == False:                                                    # 動作中
            self.angle += self.rotation_speed                                       # 円周上を移動
        else:                                                                       # 一時停止中
            self.angle = self.angle                                                 # 回転停止
        if self.enemy_hp > 0:
            orbit_x = self.x + int(self.circle_R * math.cos(math.radians(self.angle)))  # 円運動の x 座標計算
            orbit_y = self.y - int(self.circle_R * math.sin(math.radians(self.angle)))  # 円運動の y 座標計算
            rotation_ang = 90 + self.angle                                              # 画像の回転角度
            rotated_image = pygame.transform.rotate(self.original_image, rotation_ang)  # 画像を回転
            self.rect = rotated_image.get_rect(center=(orbit_x, orbit_y))               # 円周の座標に画像の中心を合わせる
            self.image = rotated_image
            self.path.append((self.x, self.y))
        else:
            self.image =self.image_bomb                                 # 爆発画像をセット
            self.speed_x = 0                                            # 移動停止
            self.speed_y = 0                                            # 移動停止
            self.rotation_speed = 0                                     # 回転停止
            self.rect = self.image.get_rect(center=(self.x, self.y))    # 新座標にセット
            if pygame.time.get_ticks()>self.explosion_time:             # 1秒経過したら
                self.kill()                                             # グループから削除

############################################################################################


stage1.py

#### stage1.py ####

############################################################################################
#### ライブラリの読み込み ####

from enemy import Enemy,BossEnemy       # enemy.pyからEnemyクラス、BossEnemyクラスを読み込む


############################################################################################ 
#### メインプログラム ####
def main(hp,mp,idx):
    ########################################################################################
    #### 初期設定 ####


    ########################################################################################
    #### コマンドボタンのスプライト ####

    
    ########################################################################################
    #### 壁のスプライト ####


    ########################################################################################
    #### ザコ敵のスプライト ####

    
    ########################################################################################
    #### ザコ敵のクローンスプライト ####

    
    ########################################################################################
    #### 同じ敵を複数作る場合 ####
    #### エネミーのスプライト ####

    
    ########################################################################################
    #### ボスキャラのスプライト ####
    boss_width = 200        # 横幅
    boss_height = 200       # 高さ
    image1 = pygame.image.load("image/space_kaseijin.png")                  # 画像読込
    image_boss = pygame.transform.scale(image1, (boss_width, boss_height))  # サイズ変更
    image2 = pygame.image.load("image/bakuhatsu4.png")                      # 画像読込
    image_bomb = pygame.transform.scale(image2, (boss_width, boss_height))  # サイズ変更
    boss_enemy_params = {               # ボスのパラメータ
        'x': 780,                       # 初期 x 座標
        'y': 360,                       # 初期 y 座標
        'image': image_boss,            # 通常画像
        'image_bomb': image_bomb,       # 爆発画像
        'speed_x': 0,                   # x方向への移動速度
        'speed_y': 0,                   # y方向への移動速度
        'rotation_speed': 5,            # 回転速度
        'start_angle': -90,             # 初期角度
        'atk': 5,                       # ダメージ倍率
        'enemy_hp': 5,                  # HP
        'size_multiplier': 1.0,         # サイズ倍率
        'dead_flag': False,             # 一撃フラグ(未実装)
        'circle_R': 100                 # 大回転の半径
        }
    boss_enemy = BossEnemy(**boss_enemy_params)                 # Boss_Enemyクラスを継承
    single_enemies.add(boss_enemy)                              # リストに追加


    ########################################################################################

この記事が気に入ったらサポートをしてみませんか?