インタラクティブ・ゲーム制作 <プログラミングコース>

Slides:



Advertisements
Similar presentations
1 C++ における OOP を用いた 書き方講座 H 山崎貴英. 2 今回の内容 OOP とは? C++ の超基礎 注釈 書いてあるコードはすべて一部抜粋。 コピペだと動かないよ!
Advertisements

オブジェクト指向 言語 論 第八回 知能情報学部 新田直也. 多相性(最も単純な例) class A { void m() { System.out.println( “ this is class A ” ); } } class A1 extends A { void m() { System.out.println(
C++ 基礎. 目次 C++ とは? C++ におけるオブジェクト指向 課題 C++ とは? Cには足りなかったものが付与されて出来た物 具体的には、 情報の隠蔽(カプセル化) 共通の名前付け(関数のオーバーロード) 再利用の仕組み クラスの導入 など オブジェクト指向 C++ では大規模なプログラミングの.
オブジェクト指向プログラミング(4) 静的分析(2)
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
~手続き指向からオブジェクト指向へ(Ⅰ)~
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
とても使いやすい Boost の serialization
情報工学演習I 第13回 C++の演習5(仮想関数).
とても使いやすい Boost の serialization
システムプログラミング 第5回 情報工学科 篠埜 功 ヒアドキュメント レポート課題 main関数の引数 usageメッセージ
プログラミング演習II 2004年10月19日(第1回) 理学部数学科・木村巌.
第8回 プログラミングⅡ 第8回
プロジェクト演習III,V <インタラクティブ・ゲーム制作> プログラミングコース
構造体.
プログラミング演習II 2004年12月 21日(第8回) 理学部数学科・木村巌.
インタラクティブ・ゲーム制作 <プログラミングコース>
社会人学習講座 「Javaプログラミング概論」
インタラクティブ・ゲーム制作 <プログラミングコース>
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
第6回独習Javaゼミ 第6章 セクション4~6 発表者 直江 宗紀.
第10回 プログラミングⅡ 第10回
補足説明.
~手続き指向からオブジェクト指向へ[Ⅱ]~
プログラミング2 関数
アルゴリズムとプログラミング (Algorithms and Programming)
情報工学演習I 第12回 C++の演習4(インライン展開).
インタラクティブ・ゲーム制作 <プログラミングコース>
オブジェクト指向 プログラミング 第十一回 知能情報学部 新田直也.
オブジェクト指向 プログラミング 第十三回 知能情報学部 新田直也.
暗黙的に型付けされる構造体の Java言語への導入
関数の定義.
プログラミング 4 記憶の割り付け.
復習 前回の関数のまとめ(1) 関数はmain()関数または他の関数から呼び出されて実行される.
プログラミング言語論 第五回 理工学部 情報システム工学科 新田直也.
C#言語ソースプログラムの原型 C言語 C#言語 Hello World! Hello Students! オマジナイ! 適当なクラス名
オブジェクト指向言語論 第十一回 知能情報学部 新田直也.
オブジェクト指向言語論 第八回 知能情報学部 新田直也.
プロジェクト演習Ⅱ インタラクティブゲーム制作
オブジェクト指向言語論 第十一回 知能情報学部 新田直也.
プロジェクト演習III,V <インタラクティブ・ゲーム制作> プログラミングコース
オブジェクト・プログラミング 第8回.
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
第1章 いよいよプログラミング!! ~文章の表示 printf~
アルゴリズムとプログラミング (Algorithms and Programming)
プロジェクト演習Ⅱ インタラクティブゲーム制作 イントロダクション2
オブジェクト指向 プログラミング 第九回 知能情報学部 新田直也.
オブジェクト指向プログラミング クラス 継承
プログラミング言語論 第十三回 理工学部 情報システム工学科 新田直也.
C#プログラミング実習 第3回.
計算機プログラミングI 木曜日 1時限・5時限 担当: 増原英彦 第1回 2002年10月10日(木)
復習 Cにおけるループからの脱出と制御 break ループを強制終了する.if文と組み合わせて利用するのが一般的. continue
オブジェクト指向言語論 第五回 知能情報学部 新田直也.
情報処理Ⅱ 第7回 2004年11月16日(火).
cp-3. サブクラス,継承 (C++ オブジェクト指向プログラミング入門)
cp-2. 属性,アクセサ (C++ オブジェクト指向プログラミング入門)
cp-1. クラスとメソッド (C++ オブジェクト指向プログラミング入門)
モジュール分割.
ソフトウェア工学 知能情報学部 新田直也.
フレンド関数とフレンド演算子.
Javaとは Javaとはオブジェクト指向言語でJava VM(Java仮想マシン)と呼ばれるプログラム上で動作します。
情報処理Ⅱ 2005年11月25日(金).
プロジェクト演習III,V <インタラクティブ・ゲーム制作> プログラミングコース
プロジェクト演習III,V <インタラクティブ・ゲーム制作> プログラミングコース
情報処理Ⅱ 小テスト 2005年2月1日(火).
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング 3 ポインタ(1).
計算機プログラミングI 第2回 2002年10月17日(木) 履習登録 複習 ライブラリの利用 (2.6-7) 式・値・代入 (2.6-8)
計算機プログラミングI 第10回 2002年12月19日(木) メソッドの再定義と動的結合 クイズ メソッドの再定義 (オーバーライド)
計算機プログラミングI 第5回 2002年11月7日(木) 配列: 沢山のデータをまとめたデータ どんなものか どうやって使うのか
Presentation transcript:

インタラクティブ・ゲーム制作 <プログラミングコース> 第2回 オブジェクト設計論 &C++お作法論

今日の内容 C++文法基礎 基本構造の復習 関数の中と外 お品書きと中身の分離 オブジェクト設計論 アクセス制御 コンストラクタ 継承

今日の課題 5/8の授業開始時までに 次の処理を行うプログラムを作ろう パズドラのダメージ計算プログラム パズルで消したドロップの種類と個数を入力 あらかじめ任意のモンスターを6体用意しておき、 それに基づいたダメージを計算 最低限の仕様は別途提示 実際のゲームにどこまで即すかは自由

前年度の復習も兼ねつつ プログラムの構造を再確認

これが最小単位のプログラム C++プログラムの 最小単位は「関数」 exeファイルを実行 (デバッグ開始)するとmain()関数から 処理が始まる main()内の処理が 上から順に実行され、 全部終わると プログラムは終了 int main(int argc, char *argv[]) { return 0; }

3DCGのための最小プログラム 「FKUTという道具を 使うよ」という宣言 fkut_SimpleWindow というクラスの オブジェクトを windowという 名前で作る そのwindowに対して 色々セッティングする ウィンドウを閉じるまで、 ぐるぐる回る // FKUT使うよ! #include "FKUT/FKUT.h“ int main(int argc, char *argv[]) { // ウィンドウ作るよ! fkut_SimpleWindow window; window.setSize(800, 600); window.setBGColor(0.3, 0.6, 0.8); window.open(); while(window.update() == true) { // ここに来週以降色々書く } return 0; }

使うよ宣言(インクルード) 関数を書くよりも前に宣言する必要がある #incude “使いたい ものを並べてある お品書きファイル” という書き方をする 複数使いたいものが ある場合は 複数includeすればいい // FKUT使うよ! #include "FKUT/FKUT.h“ int main(int argc, char *argv[]) { // ウィンドウ作るよ! fkut_SimpleWindow window; window.setSize(800, 600); window.setBGColor(0.3, 0.6, 0.8); window.open(); while(window.update() == true) { // ここに来週以降色々書く } return 0; }

作るよ定義(オブジェクト生成) プログラムで利用する ものは種類ごとに 「名前を付けて作る」 のが原則! その種類がクラス 個体がオブジェクト オブジェクトを作って良い場所は2箇所 関数内 クラスのメンバ // FKUT使うよ! #include "FKUT/FKUT.h“ int main(int argc, char *argv[]) { // ウィンドウ作るよ! fkut_SimpleWindow window; window.setSize(800, 600); window.setBGColor(0.3, 0.6, 0.8); window.open(); while(window.update() == true) { // ここに来週以降色々書く } return 0; }

作ったものに指示を出すよ (メンバ関数呼び出し) windowという名前で作ったものに指示を出して望み通りの 動きにしていく 「名前.命令(詳細);」とするのが基本形 この命令(メンバ関数)をどう用意するかが設計のポイント 変数も補助的に使う // FKUT使うよ! #include "FKUT/FKUT.h“ int main(int argc, char *argv[]) { // ウィンドウ作るよ! fkut_SimpleWindow window; window.setSize(800, 600); window.setBGColor(0.3, 0.6, 0.8); window.open(); while(window.update() == true) { // ここに来週以降色々書く } return 0; }

昨年度までの オブジェクト指向プログラミングとは 使うよ宣言インクルード! 名付けて作るよオブジェクト! オブジェクトの種類のことを「クラス」と 呼ぶことは知っておくと良いかも 今だ呼ぶんだメンバ関数! オブジェクトの種類ごとに持ち合わせている命令のことを「メンバ関数」と呼ぶ

今年度から学ぶのは 前スライドのように利用出来るクラスを自分で作れるようになる考え方 ゲームに関わる諸々を 「クラスで表せないか?」と考える とその技法 ゲームに関わる諸々を 「クラスで表せないか?」と考える ゲーム中のプレイヤーやモンスターなど プログラム中で扱う、ウィンドウや表示物も全てクラスで表し、オブジェクトとして扱う

さっきのここに注目 プログラムで利用するものは、利用するよりも前に宣言する ここが膨らんでいくのはちょっと困る 水色の部分 前回はここに色々と ブチ込んだ ここが膨らんでいくのはちょっと困る 結局ソースが長くなる そもそもFKUTはそんな長くない // FKUT使うよ! #include "FKUT/FKUT.h“ int main(int argc, char *argv[]) { // ウィンドウ作るよ! fkut_SimpleWindow window; window.setSize(800, 600); window.setBGColor(0.3, 0.6, 0.8); window.open(); while(window.update() == true) { // ここに来週以降色々書く } return 0; }

お品書きと中身の分離 // Monster.h #ifndef __MONSTER_H__ #include <string> enum Attrib { ATT_FIRE = 1, ATT_WATER, ATT_WOOD, ATT_LIGHT, ATT_DARK }; class Monster { public: void levelUp(); void init_HeraYs(); void print(); protected: std::string name; Attrib att; int type; int level, exp; int hitPoint, attack, heal; int cost; #endif // Monster.cpp #include “Monster.h” #include <iostream> using namespace std; void Monster::levelUp() { level++; hitPoint += 10; attack += 5; heal += 3; } void Monster::init_HeraYs() name = "ヘラ・イース”; att = ATT_WATER; type = 6; // 6が神だとする level = 50; exp = 883883; hitPoint = 2161; attack = 1183; heal = 238; cost = 40; void Monster::print() cout << name << “ Level:" << level << “, “; cout << "HP:" << hitPoint << “, “; cout << "攻撃:" << attack << “, “; cout << "回復:" << heal << endl;

これで使う側はスッキリ 圧倒的便利 しかも使い回しが 絶望的に楽 Monster.h/cppさえ もらってくれば、 他の人でもすぐ使える 1つのペアで1つの クラスを担当させる #include “Monster.h” int main(int argc, char *argv[]) { // Monster型のオブジェクト Monster monster; // 初期ステをヘラ・イースでセット monster.init_HeraYs(); // ここでいったん表示 monster.print(); // レベルを上げてから monster.levelUp(); // もっかい表示 return 0; }

注意点 ヘッダ側 cpp側 インクルードガード メンバ変数や、関数の引数・返値に出てくる型のヘッダはこちらでインクルード using namespaceは使わない方がよい 外から使う関数はpublic 内側に隠すものはprivate(protected) cpp側 対応するヘッダと、 メンバ関数で使う ヘッダをインクルード cpp内はusing namespace使用可 メンバ関数内からは、メンバ変数が.無しで直接見える 箱の中にいるイメージ 外部から引数を与えて挙動を制御できる

パズドラでわかる オブジェクト指向・続き うちの娘も最終進化形になりました ©2012-2013 GungHo Online Entertainment, Inc. All Rights Reserved.

オブジェクトとは 何かを表す変数や手続きがまとまっており、 メッセージを送る(メンバ関数を呼び出す) ことで様々な処理を実現できるもののこと このオブジェクトを作るための設計図が 「クラス」 その「クラス型の変数」がオブジェクト

ただ、ここまでの内容だけでは 不十分 Monsterというのは抽象的な括り ValkyrieやHeraYsもクラスになり得る スキルやパラメータの伸びは種類ごとに違う ValkyrieやHeraYsもクラスになり得る 同じ種類のモンスターを複数所持することは 十分あり得るので でも別々のクラスにしちゃうと、 パーティを配列で表現出来ない…… ちょっと高度ですが、継承で実現できます

トピック:コンストラクタ メンバ変数に初期値は必ず入れなくてはいけない クラス名と同じ メンバ関数を作る 0になっている保証は ない!! オブジェクト生成時に 自動的に呼び出される /* ヘッダにお品書きを書いた上で、cpp側に次のように書く */ Monster::Monster() { setInit_HeraYs(); } /* ここからmain関数内 */ Monster heraYs; // この時点で初期値が入る

[補足] コンストラクタとデストラクタ コンストラクタは、オブジェクト生成時 呼ばれる関数 デストラクタは オブジェクト消滅時呼ばれる処理 関数内に宣言して、 処理がそこを通った時 あるクラスのメンバ 変数になっていて、 そのオブジェクトが 生成された時 newされた時 デストラクタは オブジェクト消滅時呼ばれる処理 オブジェクトを宣言 した場所から抜ける時 あるクラスのメンバ 変数になっていて、 そのオブジェクトが 生成された時 deleteされた時

ここで一考 Monsterクラスに 全てのモンスターのデータを突っ込む? モンスターの 種類ごとに別々の クラスを用意する? 配列でまとめられる 引数で種類を指定して処理を切り替える Monsterクラスが 肥大化する! モンスターの 種類ごとに別々の クラスを用意する? 1つのクラスで 1種類のモンスターを表せる それぞれのクラスで 共通点が多い 配列にまとめられない

共通点と相違点を括り出す どんなモンスターも モンスターごとに 変えたいのは メンバ変数は同じ メンバ関数の構成も 同じ 初期値そのもの 初期値セット処理 レベルアップ処理 卵付与処理 ダメージ計算処理 スキル処理 リーダースキル処理 表示処理 モンスターごとに 変えたいのは 初期値そのもの レベルアップの伸び率 スキル処理の中身 リーダースキル処理の中身

共通点だけをクラス化 この場合はMonster という「抽象的」な 概念を表す 先ほどの状態から 具体的な数値を 取り除く // Monster.h #ifndef __MONSTER_H__ #include <string> enum Attrib { ATT_FIRE = 1, ATT_WATER, ATT_WOOD, ATT_LIGHT, ATT_DARK }; class Monster { private: std::string name; Attrib att; int type; int level, exp; int hitPoint, attack, heal; int cost; public: Monster(); virtual ~Monster() {}; virtual void levelUp() {}; virtual void init() {}; void print(); #endif この場合はMonster という「抽象的」な 概念を表す 先ほどの状態から 具体的な数値を 取り除く そして関数には virtualを付けて、 何もしない中身を 書いておく {}を付けて;

特定のモンスターを 表すクラスを作る 共通点をまとめた 「抽象クラス」の ヘッダをinclude 継承を指示 クラス名の横に注目 特定のモンスターで処理変えたいものを宣言 中身はいつも通りcpp // Valkyrie.h #ifndef __VALKYRIE_H__ #include “Monster.h” class Valkyrie : public Monster { public: Valkyrie(); ~Valkyrie(); void levelUp(); void init(); }; #endif

上級者向け:純粋仮想関数 virtual void levelUp() {}; こうすると、何もしないどころか 中身が無い状態になるので、 必ず継承してからじゃないと使えない クラスにすることができる 実装を強制することができるので、クラスの 使い方を伝える1つのメッセージになる

継承したクラスの使い方 普通に宣言して使う、でもいいんですが、 メリットが薄い Monster型ポインタを使う方法を伝授 .ではなく、 ->でメンバを呼び出す newしたら必ずdelete Monster型を継承して いれば、何型でも newして代入できる #include “Valkyrie.h” int main(int argc, char *argv[]) { // Monster型のポインタ Monster *monster = NULL; // ヴァルキリー爆誕! monster = new Valkyrie(); // ここでいったん表示 monster->print(); // レベルを上げてから monster->levelUp(); // もっかい表示 // 最後必ずdeleteすること delete monster; return 0; }

課題の最低限の仕様 Monsterクラスを継承して、 自分の好きなモンスターを最低5体実装する それらを配列で持ち、 適当にレベルを上げる この状態で、 「5色のドロップが何回消えたか」を 入力し、色に対応したいモンスターが その回数分攻撃するとする そのトータルダメージを計算して求める

例えば 次のような構成で 闇が3回、水が1回 消えた場合 パーティ構成は プログラム内に 直接記述でも可 897, 1062, 1051, 1138 水 626 フレンド:闇 1327  闇が3回、水が1回  消えた場合 3*(807+1062+1051+1138+1327)+1*(626) パーティ構成は プログラム内に 直接記述でも可 各色が消えた回数をキーボードから入力 「cin >> intの変数;」 とすることで入力が 取れる

ガチ勢はもっと実際の仕様に 即して好き放題やっていい リーダースキルに よる倍率補正計算 属性やコンボ数など 正確な計算のためには何個ずつ消えたかの 入力も必要 副属性の処理 回復量の計算 スキルの処理 モンスターも入力で選べるようにする 被ダメシミュレート 敵もクラス化して 対戦相手として 処理して……etc

実感して欲しいこと クラスとして、オブジェクトとして表すことのメリット グラフィックはなくても、データ構造でゲームはシミュレートできる パズル制作側と数値計算側で、 作業分担が出来そうな気がする!

To be continued…