11
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

HALAdvent Calendar 2016

Day 19

C++覚えたてでゲームのシーン管理

Posted at

できる友達のコードチラッと見てC++かっけぇと思い

「あ…ありのまま 今 起こった事を話すぜ!」

初めての触ったプログラミング言語 c言語 を片手にぶらさげて一年間課題をこなしてきた俺だが
ふと、隣の坊やのディスプレイを覗き込んだら…

「こ こんなコード俺ぁみたことねぇぜ」

その坊やは授業でまだ扱ってない C++ でコードを書いていた。

坊やは俺に、**「貧弱ぅ 貧弱うぅ!!」**と言わんばかりの顔でこっちをみて笑った。

自分のコードの一部分をC++で書いてみよう

もうジョジョネタで続き書くのさすがに辛いからやめとこ。

友達がC++でコード書いてて自分も手出してみようと思いゲームのシーン管理の部分をクラス化
してみようと思いました。

今までのシーン管理

今まではメインループに関数を分けて Switch文で、どこのシーンの処理に行くか決めていました。
どのシーンに行けばいいかを持つ変数を

enum SCENE{
 TITLE,
 GAME,
 RESULT
};

// while(ループ)関数の中
switch(scene){          //scene変数はグローバル変数
 case SCENE::TITLE:
   Title();             //ゲームタイトルの処理関数
   break;
 case SCENE::GAME:
   Game();              //ゲームプレイ中の処理関数
   break;
 case SCENE::RESULT:
   Result();            //ゲーム結果の処理関数
   break;
 default:
   break;
}

大体こんな感じで書いてました。
Switch文の意図はどのシーンに行くかを決めたかっただけでしたが、
結果的に、それぞれの処理を全部書くことになってしまいました。
それぞれの処理関数のなかでシーンを変えてるので んーなんだかなぁ

Swicth文はシーンの切り替えだけにしたいよ

タイトルシーン君、ゲームシーン君、リザルトシーン君
そしてこの三つの シーン君 を制御する シーン管理先生 みたいな環境の教室にしていこう。

C++でクラス化してみようかな

とは言うものの全く何をどうすれば分からない。
自分ではどうすれば良くなるのかもサッパリだったので Google先生に 「教えてくれぃ」と懇願しました。

C++で検索すると出るわ出るわ大量の情報が

どうやらクラス(class)ってのを使うらしいなぁ

ちょっと書いてみよう
タイトルのシーンを作ろう
[タイトルシーン君]

class TitleScene {
  public: 
    void Update ();   //タイトルシーン(でタイトル画面のアニメーションとか)の更新関数
    void Draw();       //タイトルシーン(でタイトル画面を描画したりとか)の描画関数
  private:
    //タイトルシーンで必要なもの タイトル画面の画像とか…
}

なんか、構造体に似てるよなぁ
TitleSceneクラスは
 タイトルシーンでの更新ができる
 タイトルシーンでの描画ができる
 タイトルシーンでのタイトル画像とかを持ってる
みたいな感じかな

public private (protected)のアクセス指定子

public と private はアクセス制限の役割があるらしい

public は外からも使える  
private はPlayerクラスの中でしか使えない
(protected はPlayerクラスの中と Playerクラスを継承したクラスの中でしか使えない)

「privateの中は俺しか扱えねえぜ!」ってノリだな

※詳しくはGoogle先生に聞いてくれぃ

継承を使ってみよう

タイトルシーン君ができたので、ゲームシーン君、リザルトシーン君も同じように作ったぞ。
[ゲームシーン君]

class GameScene {
  public: 
    void Update ();   //ゲームシーン(でプレイヤーや敵の移動とか)の更新関数
    void Draw();       //ゲームシーン(でプレイヤーや敵の描画したりとか)の描画関数
  private:
    //ゲームシーンで必要なもの プレイヤーや敵とか…
}

[リザルトシーン君]

class ResultScene {
  public: 
    void Update ();   //リザルトシーン(で最終スコアやランキングとか)の更新関数
    void Draw();       //ゲームシーン(で最終スコアやランキングの描画したりとか)の描画関数
  private:
    //リザルトシーンで必要なもの ゲームクリアの画像とか最終スコアとか…
}

これで生徒は全員そろったね!

ここで 更新関数(void update())と描画関数(void Draw())はみんな内容は違うけどもってるよね

ここで継承の出番!!

新しくクラスを追加するよ

class BaseScene{
  public:
    virtual void Update()=0;
    virtual void Draw()=0;
}

このクラスはタイトルシーン、ゲームシーン、リザルトシーンの大元となるクラスだよ。
関数の後に =0 が付いているのは この関数の中身は 空っぽ っていう意味。

意味わかんないかも知れないけどもう少し我慢してくれ!

さっきのタイトルシーン、ゲームシーン、リザルトシーンに変更を加えるよ

class TitleScene:public BaseScene{   // :public  BaseScene
  public:
    //さっきと同じ
  private
    //さっきと同じ
}

これは三つのシーン君はベースシーンを継承したことになるよ!
※継承はGoogle先生に詳しく聞いてください

シーン管理クラスを作ろう

タイトルシーン君、ゲームシーン君、リザルトシーン君は教室にいるね!
あとは三つのシーン君を 管理する シーン管理先生を作るぞ!

[シーン管理先生]

class SceneManager{
  public:
    enum SCENE{
      TITLE,
      GAME,
      RESULT
    };
    static void ChangeScene(SCENE scene);     //シーンを引数によって変える関数
    static void Update();                     //現在のシーンの更新関数
    static void Render();                     //現在のシーンの描画関数
  private:
    static BaseScene* m_pScene;               //現在のシーン
}

[シーン管理先生の関数の中身]

BaseScene *SceneManager::m_pScene=NULL;       //始めはシーンを空にしておこう

void SceneManager::ChangeScene(SCENE scene){
  
  if(m_pScene != NULL){
    delete m_pScene;
  }
  
  switch(scene){          //引数のシーン
    case SCENE::TITLE:
      m_pScene = new TitleScene();      //タイトルシーンを現在のシーンにする
      break;
    case SCENE::GAME:
      m_pScene = new GameScene();       //ゲームシーンを現在のシーンにする
      break;
    case SCENE::RESULT:
      m_pScene = new ResultScene();     //リザルトシーンを現在のシーンにする
      break;
    default:
      break;
  }

}

void SceneManager::Update(){
  m_pScene->Update();         //現在のシーンの更新関数
}

void SceneManager::Render(){
  m_pScene->Draw();           //現在のシーンの描画関数
}

後半になるにつれ説明が雑になってしまったけど、こうすればswitch文の中身はシーンの切り替えだけで済んだね!

BaseSceneを継承したことによって、
BaseSceneに TitleScene,GameScene,ResultSceneがそれぞれ new できる。

※継承はGoogle先生に詳しく聞いてください

まとめ

この記事だけではすべてを伝えられなかったけど、C++でゲームのコード書きたいって思ってる人は
参考にしてください

このやり方は他の記事を参考にしています。

私が友達に継承を教えたとき

アイドルには色んなアイドルがいるよね!

アイドルは大まかに 歌う、踊る、握手会 ができるよね!  
そしてアイドル名がある!

class アイドル{
  publuc: 
    歌う
    踊る
    握手会
    virtual 掛け声(挨拶的なやつ)
  private:
    アイドル名
}

アイドルはアイドルでも色々いるよね
乃木坂46や欅坂46のふたつのアイドルを例に挙げよう(私は乃木坂好きです)

どちらのグループも 歌う、踊る、握手会ができる!
アイドル名もある!
掛け声はあるがそれぞれグループで内容が違うからグループ内で変更できるように
virtual を付けておこう

ふっふっふ 継承じゃー

class 乃木坂46:public アイドル{
  public:
    掛け声
}


class 欅坂46:public アイドル{
  public:
    掛け声
}

継承すれば継承先は継承元のメンバ関数、メンバ変数を持ってることになる

つまり、これだけで 乃木坂46 も 欅坂46 も歌う、踊るなどができるぞ!

掛け声はそれぞれの クラスで 内容書き換えればよし!!!

11
16
2

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
11
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?