制作日記3

アバター
SAI
記事: 115
登録日時: 14年前
住所: はひほーひ

制作日記3

投稿記事 by SAI » 14年前

2011年4月30日
ファイル同士の関係をまとめた図を作ってみた。
色々手直しを加えて、設計完了!
大まかな流れは全てファイルも関数も作っておきました。
それじゃあ早速自機を作るぞ!
FifthCannon先輩のコードを見る。
これはヒドイと思いながら、必要なコードを抜きだしました。
やっべ、もうファイル数がFifthCannonを越えるww
っげげ、ファイル迷子になりそう。関係図を書いておいてよかった。

なんだ貴様。10行上で定義した変数が未定義だと?ケンカうっとんのか!

ってメンバ関数じゃないと「オブジェクト名.」を先頭につけないといけないのか・・・。
クラスを導入してから意味不明なコンパイルエラーに悩まされる。
一つは打ち間違いだとわかったが、もうひとつが全然わからん・・・。
やっぱconstを使うのはやめよう・・・。

誰か私の代わりにコンパイルエラーをぶちのめしてくれ・・・orz

自機が出た。やった!
でも動かない。やってない!

せっかくデバッグ用ファイルを作ったけど、すんごい偉いところにあるので、下層のクラスを色々見るのには不向きそう。
やっぱりクラスの中身を見るには同じクラスの関数に限るよね。
でもそうなるとデバッグ用関数が散らばる・・・orz

自機動いた!やった!
しかし疲れる(-_-;)
楽しいけどね。

そんなわけで自機ができました。
まだ白丸が範囲内を高速&低速移動するだけですが、コード全体を見たい方はどうぞ。(下の方にあります)

それでは長い長い今回の追加分です。
ていうかさ、これってポイントの荒稼ぎじゃないの?
って思ってる人いるんでしょうかね?
一人でもいればやり方を変えますが。
まあ、ポイントをためても何にも貰えませんがねw
なんでこういう仕様なの?とか思ったら聞いてくださいね?

CODE:

//STGplayer.h

//STGのプレイヤー
#ifndef STGPLAYER_H
#define STGPLAYER_H

#include "main.h"
#include "STG.h"
#include "chara.h"


#define STG_INIT_X STAGEHALF_X  //初期値X座標
#define STG_INIT_Y 400  //初期値Y座標
#define MAXOLDPOS 60  //プレイヤーの座標保持フレーム数

#define PLAYERMIN_X STAGEMIN_X+10  //プレイヤーのフィールドを動き回れる限界
#define PLAYERMAX_X STAGEMAX_X-10  //プレイヤーのフィールドを動き回れる限界
#define PLAYERMIN_Y STAGEMIN_Y+10  //プレイヤーのフィールドを動き回れる限界
#define PLAYERMAX_Y STAGEMAX_Y-10  //プレイヤーのフィールドを動き回れる限界


//プレイヤークラス。STG中の各キャラ共通のクラスのため、オブジェクトは1つのみ

class CPlayer
{
private:
	CPosition pos;	//座標
	CPosition oldpos[MAXOLDPOS];	//プレイヤーがいた座標をMAXOLDPOSフレームにわたって保存
	int power;	//パワー。一時的なもの
	int graze;	//グレイズカウント
	int grazetime;	//グレイズしていない時間をカウント
	int slowFlag;	//低速移動フラグ 1なら低速、2なら超低速
	int statusijo[MAX_STATUSIJO];	//状態異常の管理、状態
	int statusijo_time[MAX_STATUSIJO];	//状態異常の時間をカウント

public:
	CPlayer()
	{
		pos.x=STG_INIT_X;
		pos.y=STG_INIT_Y;
		for(int i=0; i 0) slowFlag=1;	//シフトで低速
	 else slowFlag=0;
	//ここに超低速の判定を入れる
	
	 double playerspeed = pchara->getspd();
	 if(slowFlag==1)	//低速
		 playerspeed = pchara->getslowspd();
	 else if(slowFlag==2)	//超低速
		 playerspeed=SUPERSLOWSPEED;

     if(CheckStatePad(pad.down)>0) 
     {
            if(CheckStatePad(pad.right)>0)
            {
                    pos.x += playerspeed*ROOT2;
                    pos.y += playerspeed*ROOT2;
            }
            else if(CheckStatePad(pad.left)>0)
            {
                    pos.x -= playerspeed*ROOT2;
                    pos.y += playerspeed*ROOT2;
            }
            else  pos.y += playerspeed;
     }
     else if(CheckStatePad(pad.up)>0) 
     {
            if(CheckStatePad(pad.right)>0)
            {
                    pos.x += playerspeed*ROOT2;
                    pos.y -= playerspeed*ROOT2;
            }
            else if(CheckStatePad(pad.left)>0)
            {
                    pos.x -= playerspeed*ROOT2;
                    pos.y -= playerspeed*ROOT2;
            }
            else  pos.y -= playerspeed*ROOT2;
     }
     else if(CheckStatePad(pad.right)>0)
            pos.x += playerspeed*ROOT2;
     else if(CheckStatePad(pad.left)>0)
            pos.x -= playerspeed*ROOT2;

}


//以下雑用関数

//プレイヤーの旧座標を更新するための関数
void CPlayer::renew_oldpos_mf()
{
	for(int i=MAXOLDPOS; i PLAYERMAX_X)	pos.x=PLAYERMAX_X;
	if(pos.yPLAYERMAX_Y)	pos.y=PLAYERMAX_Y;
}

//プレイヤーを描画
void CPlayer::drawSTGplayer(CCharacter* pchara)
{
	DrawCircle( int(pos.x), int(pos.y), 10,color.white, TRUE ) ;	//仮の自機

}



//デバグ用関数
void CPlayer::drawCPlayer()
{
        DrawFormatStringToHandle(0,10,color.white,font[2],"x:%.0f",pos.x);
        DrawFormatStringToHandle(0,24,color.white,font[2],"y:%.0f",pos.y);
        DrawFormatStringToHandle(0,38,color.white,font[2],"power:%d",power);

}


//chara.cpp

//STGとRPG合わせた各キャラの情報
#ifndef CHARA_H
#define CHARA_H

#include 
using namespace std;

#define SUPERSLOWSPEED 0.5  //超低速移動のスピード。固定値。


//キャラクタークラス。操作可能なキャラクター数オブジェクトを作る。
class CCharacter
{
private:	
	int STGgraph;	//STG用グラフィック

	int RPGgraph;	//RPG用グラフィック
	string name;	//キャラ名
	//このへんSTG用変数
	int MAXHP;	//STGとRPGで共通
	int HP;		//STGとRPGで共通
	int MAXMP;
	int MP;
	int atk;	//基礎攻撃力
	double BASEspd;	//キャラ固有の高速移動力
	double spd;	//現在の高速移動力
	double BASEslowspd;	//キャラ固有の低速移動力
	double slowspd;	//現在の低速移動力
	int BASEitemborderMIN;	//キャラの基礎アイテム上部回収ライン
	int itemborder;	//現在のアイテム上部回収ライン
	int BASEitemabsorbrange;	//キャラの基礎アイテム吸収半径
	int itemabsorbrange;	//現在のアイテム吸収半径
	double bombgauge;	//ボムゲージ
	int equipweight;	//装備による重さ
	//この辺RPG用変数





	//この辺装備用変数

	int equipshot[2];	//装備しているショット。保存するのは識別番号
	int equipmagic[2];	//装備している魔法。
	int equipbomb[2];	//装備しているボム。
	int equipother;	//その他の装備
	int equipitem;	//装備しているアイテム。

public:
	double getspd(){ return spd;}
	double getslowspd(){ return slowspd;}
	

	CCharacter(string Iname,int IMAXHP,int IHP,int IMAXMP,int IMP,int Iatk,double IBspd,double Ispd,double IBslowspd,double Islowspd,int IBitemborMIN,int Iitembor,
		int IBitemabsR,int IitemabsR,double Ibombgauge,                int* IEshot,int* IEmagic,int* IEbomb,int IEother,int IEitem)
	{
		name=Iname;
		MAXHP=IMAXHP;
		HP=IHP;
		MAXMP=IMAXMP;
		MP=IMP;
		atk=Iatk;
		BASEspd=IBspd;
		spd=Ispd;
		BASEslowspd=IBslowspd;
		slowspd=Islowspd;
		BASEitemborderMIN=IBitemborMIN;
		itemborder=Iitembor;
		BASEitemabsorbrange=IBitemabsR;
		itemabsorbrange=IitemabsR;
		bombgauge=Ibombgauge;
		equipweight=0;
		
		equipshot[0]=IEshot[0];
		equipshot[1]=IEshot[1];
		equipmagic[0]=IEmagic[0];
		equipmagic[1]=IEmagic[1];
		equipbomb[0]=IEbomb[0];
		equipbomb[1]=IEbomb[1];
		equipother=IEother;
		equipitem=IEitem;
	}


	//デバグ用関数
	void drawCCharacter();
};

#endif



//STG.h

//STGを司るファイル
#ifndef STG_H
#define STG_H

#define STAGEMIN_X 20  //ステージの大きさと位置 横最小座標
#define STAGEMIN_Y 10  //ステージの大きさと位置 縦最小座標
#define STAGEMAX_X 470  //ステージの大きさと位置 横最大座標
#define STAGEMAX_Y 460  //ステージの大きさと位置 縦最大座標
#define STAGEHALF_X (STAGEMIN_X+STAGEMAX_X)/2  //ステージの中心X
#define STAGEHALF_Y (STAGEMIN_Y+STAGEMAX_Y)/2  //ステージの中心Y


#define MAX_STATUSIJO 15  //状態異常の種類の数


void calcSTG();
void drawSTG();

#endif




//STG.cpp


#include "DxLib.h"
#include "STG.h"
#include "STGplayer.h"
#include "main.h"
#include "chara.h"


static CPlayer Player;
int a[2]={0};
static CCharacter ark("ark",120,100,50,40,20,4,4,2,2,150,150,100,100,0,a,a,a,0,0);


//STG計算部
void calcSTG()
{
	//プレイヤーの旧座標を更新するための関数
	Player.renew_oldpos_mf();
	//プレイヤーの動きを制御
	Player.STGplayermove_mf(&ark);
	//プレイヤーを画面内に押し戻す関数
	Player.playerbackfield_mf();

	
}

//STG描画部
void drawSTG()
{
	//プレイヤーを描画
	Player.drawSTGplayer(&ark);



	//外枠描画
	DrawBox( STAGEMIN_X, STAGEMIN_Y , STAGEMAX_X , STAGEMAX_Y , color.red , FALSE) ;
	//以下デバグ用関数
	ark.drawCCharacter();
	Player.drawCPlayer();


}


CPlayerクラスは、STG時の自機の情報を管理するクラスです。
よってオブジェクトは1つのみ。

CPosition pos; は、pos.xとpos.yの、座標のことです。
vectorでもいいかな?と思いましが、3文字ですぐわかるのでposにしました。

grazetime 地霊殿にある、グレイズでアイテムを引き寄せるシステムのための変数です。どれくらいの時間グレイズをしていないか管理します。

int statusijo[MAX_STATUSIJO]; 状態異常になったら、ここにレベルをブチ込みます。これで複数の状態異常にもなれますね。(なりたかねーよ
状態異常がstatusijoなのは、troubleだと長いし打ち間違えそうだからです。

CCharacterクラス
これはSTGとRPGを合わせて、登場するキャラクターの数だけオブジェクトを作ります。
STGのときは出場するキャラのポインタを渡してあんなことやこんなことをさせます。

移動速度がいくつもあるのは、装備による重さで速さが変わるからです。
アイテム上部回収ラインはグレイズや装備で変化しますし、アイテム吸収範囲も装備で変わります。
(しかしabsorbはもっと短くならんものか(-_-;))

ボムゲージは、ボムのゲージです。
まんまやないか。

段々たまっていき、MAXになるとボムが使えます。ただし1つまでです。ためておけません。

equip~系の変数は、そのまま装備です。
配列が2つあるのは、高速と低速でショット、魔法、ボムが変わるからです。
(魔法は花映塚のチャージ2みたいなもんです)

double getslowspd(){ return slowspd;}で間違えて
double getslowspd(){ return getslowspd;}と打ったら、意味不明なコンパイルエラーに苦しみました。怖い怖い。

コンストラクタがやったら長いですが、これはロードしてそのままコンストラクタにブチ込もうと考えてたからです。やめました。短くします。

ステージの大きさは、450×450の正方形になってます。
これは対称性を高めるためです。弾幕美を追求。

状態異常は15種類になってますが、今んところそんなに考えてません。
火傷(火属性。防御減少)
凍結(水属性。動きが遅くなる)
衰弱(風属性。攻撃減少)
麻痺(雷属性。低速不能)
毒(地属性。徐々にダメージ。死にはしない)

うん、5種類しかない(´・ω・`)ショボーン
他にもアイテム蒐集不能とか、操作が上下左右反転とかあったら面白いなあ。

アバター
SAI
記事: 115
登録日時: 14年前
住所: はひほーひ

RE: 制作日記3

投稿記事 by SAI » 14年前

ファイル関係がちと変わったので再掲。
gameoverとendingが格下げされてます。
画像が粗い代わりに60kbまで下がってます。2000×2000なのに。
さすが、不可逆圧縮です。
画像


そしてプロジェクトです。今度は1週間ですw
http://firestorage.jp/download/0895d2d8 ... d5ea7a78c2

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 15年前

Re: 制作日記3

投稿記事 by Dixq (管理人) » 14年前

CCharacterクラスはパラメータを持っているだけですか?
CCharacterクラスが持っているものはPlayerを継承したクラスが持つべきものではないかと思います。

私のイメージでは
なんらかのBaseClassがあって、そこから派生した
キャラクタクラスがあって、
そこから「プレイヤー」「敵」「ボス」が派生するのではないかと思います。

プレイヤーは沢山仕事がありますが、プレイヤーが抱え込むのではなく、細かくクラスに分けてそのオブジェクトを持つと良いと思います。
後、せっかくクラスで書いているなら制御部もクラスにしては?
GameManager的な感じで。
main.cppは

int main(){
  CGameManager GameMgr;
  if( GameMgr.Initialize() == false ){
    return -1;
  }
  GameMgr.Main();
  GameMgr.Finalize();
  return 0;
}
  
のように呼び出せば良いのではないかと思います。

・・とまぁ適当に聞き流してください^^;

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 15年前

Re: 制作日記3

投稿記事 by Dixq (管理人) » 14年前

ものすごい適当にクラス図書いてみました。
http://dixq.net/img/bbs/chat/class_sample.png
見た目良く分からないですが、敵は抽象クラスのつもりです。

アバター
SAI
記事: 115
登録日時: 14年前
住所: はひほーひ

Re: 制作日記3

投稿記事 by SAI » 14年前

アドバイスありがとうございます。
根幹部なので、まだプログラムの組み方がわからない私にとってはとてもありがたいです。

チャットでGRAMさんに継承の概念について教わり、そのメリットに
\おお~/ \マジか/ \やべぇw/
となったので、改造して継承をバンバン使っていきたいと思います。

>CCharacterクラスはパラメータを持っているだけですか?
今のところ、持っているだけです。多分関数とかそのうち追加することでしょう。

>CCharacterクラスが持っているものはPlayerを継承したクラスが持つべきものではないかと思います。
う~ん難しくてよくわからないです(-_-;)
最終的な(一番派生先の)プレイヤーに関するクラスは全ての処理や変数を一手に引き受けているということでしょうか?

今回私は分業化を目標にやってみました。(自己流(元はQ流・・・?)なので少なからず間違ってるでしょう)
私の現在の考えでは、CPlayerクラスはおそらく最終派生クラスになり、STG時の自機の処理を引き受けます。
一方CCharacterクラスも多分最終派生クラスになり、キャラクターに関する情報を管理します。主に引数に使われ、処理はあまりしません。
そのうち作るであろうRPGのクラスでは(名前どうしよう(°□°;))、CPlayerクラスと同様にCCharacterの情報を受け、こっちはRPGの自機の処理をします。
こうすることでお互いの関わりを極力減らすようにしようと考えました。
この考え方だと、クラスを継承しても、CPlayerクラスとCCharacterクラスが親戚にはならない気がします。
クラスの派生におけるこうした分業の考え方が間違ってるんでしょうか?

制御部もクラスにとのことですが、これも継承で似通った部分を統一しちゃおうということでしょうか?
う~ん、めんどくさそう・・・。ファイル迷子にはなりますが、複雑な部分では(まだ)ないので、今回は遠慮しようかな・・・。

わざわざクラス図を書いていただいてありがとうございます!
これを参考に継承をしていきたいと思います。