[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
先日作ったプログラムをこんな感じ↓に分割して読み込めるようにしてみました。
まずはグローバル変数と関数のプロトタイプ宣言をヘッダファイルに書き出して
「ファイルの分割 その3」で書いた方法で分割しました。
こうしておけば、処理ごとにcppファイルを増やしていけるので、後で見る時に解りやすそうです。
上記のプロジェクトファイルはコチラ↓
https://blog.cnobi.jp/v1/blog/user/63629cf35d5259ece1529ed13f0745b1/1238765873
アップするファイルがコレであってるのか不安なのですが・・・
解凍したファイルのship01.slnをクリックしてVC++を立ち上げてF5でコンパイルすれば
動くと思います。
ちゃんと動くとこんな感じです↓
ちなみに分割する前のプロジェクトファイルはコチラ↓
https://blog.cnobi.jp/v1/blog/user/63629cf35d5259ece1529ed13f0745b1/1238765869
もう一度0からゲームを作って行こうと思って、まずは自機移動プログラムを作ってみました。
今まで、一番の悩みどころだったのが変数の扱い方。
グローバル変数とローカル変数の使い分けがイマイチ良く判ってなくて
例えば、自機や敵の移動関数を作って移動させる処理を関数の中だけで終わらせてしまうと
当たり判定を別の関数で行おうと思った時に、自機や敵の位置を知る為の変数が必要ですが
敵や自機の移動をローカル変数で行っている場合、当たり判定関数からは敵&自機位置の変数を
参照出来ないので、どうすれば???となっていました。
グローバル変数を使えば問題無いのですが、そうするとグロバール変数を使いまくらないと
いけなくなりそうで、プログラムが肥大化した時に大変そうです。
ちなみに
グローバル変数は一度宣言すれば、プログラムが終了するまで有効。
ローカル変数は関数のなかだけでしか有効ではない。
と言った感じだと思います。
で、色々と調べたりしてみたのですが良く判らないので、考えるよりも自分がわかる方法
(グローバル変数を使う)で作って行こうと思った訳です。
で、まずこんなプログラムを作ってみました↓
**************************************************************
#include "DxLib.h"
typedef struct{//自機構造体
int x,y,img;
}ch_t;
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
int image[16];//自機画像配列変数宣言
char Key[256];//キー情報
int katamuki;//自機傾き用変数宣言
ch_t ch;//構造体用
if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //ウィンドウ化と初期化処理
ch.x =300;//自機初期位置x
ch.y =360;//自機初期位置y
katamuki=4;//傾き初期位置
SetDrawScreen( DX_SCREEN_BACK ) ; //描画先を裏画面に設定
LoadDivGraph( "ship.png" , 9 , 9 , 1 , 48 , 48 , image ) ;//画像を分割してimage配列に保存
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
//↑メッセージ処理 ↑画面をクリア ↑キーボード入力状態取得 ↑ESCが押されると終了
int color_white;
color_white= GetColor( 255 , 255 , 255 ) ;//色取得
static int gtime;//ゲームカウンタ
gtime++;
////////////////////////自機移動////////////////////////////////////////////////////////////////
if( Key[ KEY_INPUT_UP ] == 1 ) //上ボタンが押されたら
ch.y=ch.y-4; //上向きフラグを立てる
if( Key[ KEY_INPUT_LEFT ] == 1 ) //左ボタンが押されたら
{ ch.x=ch.x-4; //左向きフラグを立てる
if(gtime%4 == 0) katamuki--;}else//傾ける
{if(katamuki<4)
if(gtime%4 == 0) katamuki++;}//ボタンが押されてなくて傾いていたら戻す
if( Key[ KEY_INPUT_DOWN ] == 1 ) //下ボタンが押されたら
ch.y=ch.y+4; //下向きフラグを立てる
if( Key[ KEY_INPUT_RIGHT] == 1 ) //右ボタンが押されたら
{ ch.x=ch.x+4; //右向きフラグを立てる
if(gtime%4 == 0) katamuki++;}else//傾ける
{if(katamuki>4)
if(gtime%4 == 0) katamuki--;} //ボタンが押されてなくて傾いていたら戻す
if( ch.x<140 ) { ch.x=140; }//画面からはみ出さないようにする処理
if( ch.x>452 ) { ch.x=452; }
if( ch.y<0 ) { ch.y=0; }
if( ch.y>432 ) { ch.y=432; }
if( katamuki<0 ) {katamuki=0;}//傾き過ぎないようにする処理
if( katamuki>8 ) {katamuki=8;}
ch.img=image[katamuki];
//SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 0 ) ;
DrawGraph( ch.x , ch.y , ch.img , TRUE ) ;
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////fps表示////////////////////////////////////////////////////////////
static int FpsTime[2]={0,},FpsTime_i=0;
static double Fps=0.0;
if(FpsTime_i== 0)
FpsTime[0]=GetNowCount(); //1周目の時間取得
if(FpsTime_i==49){
FpsTime[1]=GetNowCount(); //50周目の時間取得
Fps = 1000.0f / ((FpsTime[1] - FpsTime[0]) / 50.0f);//測定した値からfpsを計算
FpsTime_i=0;
}
else
FpsTime_i++; //現在何周目かカウント
if(Fps != 0)
DrawFormatString(520,440,color_white,"FPS %.1f",Fps); //fpsを表示
////////////////////////////////////////////////////////////////////////////////////////
ScreenFlip();
}
DxLib_End();
return 0;
}
**************************************************************
とりあえずメインループに全ての処理を書いています。
ただ、これだとプログラムが大きくなってくると訳がわからなくなって困るので
処理ごとに関数化したのがコレ↓
**************************************************************
#include "DxLib.h"
typedef struct{//自機構造体
int x,y,img;
}ch_t;
//変数宣言&初期化//
int g_image[16];//自機画像配列変数宣言
char Key[256];//キー情報
int g_katamuki=4;//自機傾き用変数宣言
static int g_gtime=0;//ゲームカウンタ
ch_t ch;//自機構造体用
////////////////////////////
//関数のプロトタイプ宣言//
void haikei0();
void jikimove();
void fps();
////////////////////////////
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //ウィンドウ化と初期化処理
SetDrawScreen( DX_SCREEN_BACK ) ; //描画先を裏画面に設定
ch.x =300;//自機初期位置x
ch.y =360;//自機初期位置y
LoadDivGraph( "ship.png" , 9 , 9 , 1 , 48 , 48 , g_image ) ;//画像を分割してg_image配列に保存
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
//↑メッセージ処理 ↑画面をクリア ↑キーボード入力状態取得 ↑ESCが押されると終了
haikei0();
jikimove();
fps();
g_gtime++;
ScreenFlip();
}
DxLib_End();
return 0;
}
////////////////////////背景表示////////////////////////////////////////////////////////////////
//引数 なし
//返値 なし
void haikei0(){
int color_haikei;
color_haikei= GetColor( 0 , 105 , 105 ) ;//色取得
DrawBox ( 140 , 0 , 500 , 480 , color_haikei , TRUE) ; // 四角形を描画
}
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////自機移動////////////////////////////////////////////////////////////////
//引数 なし
//返値 なし
void jikimove(){
if( Key[ KEY_INPUT_UP ] == 1 ) //上ボタンが押されたら
ch.y=ch.y-4; //上向きフラグを立てる
if( Key[ KEY_INPUT_LEFT ] == 1 ) //左ボタンが押されたら
{ ch.x=ch.x-4; //左向きフラグを立てる
if(g_gtime%4 == 0) g_katamuki--;}else//傾ける
{if(g_katamuki<4)
if(g_gtime%4 == 0) g_katamuki++;}//ボタンが押されてなくて傾いていたら戻す
if( Key[ KEY_INPUT_DOWN ] == 1 ) //下ボタンが押されたら
ch.y=ch.y+4; //下向きフラグを立てる
if( Key[ KEY_INPUT_RIGHT] == 1 ) //右ボタンが押されたら
{ ch.x=ch.x+4; //右向きフラグを立てる
if(g_gtime%4 == 0) g_katamuki++;}else//傾ける
{if(g_katamuki>4)
if(g_gtime%4 == 0) g_katamuki--;} //ボタンが押されてなくて傾いていたら戻す
if( ch.x<140 ) { ch.x=140; }//画面からはみ出さないようにする処理
if( ch.x>452 ) { ch.x=452; }
if( ch.y<0 ) { ch.y=0; }
if( ch.y>432 ) { ch.y=432; }
if( g_katamuki<0 ) {g_katamuki=0;}//傾き過ぎないようにする処理
if( g_katamuki>8 ) {g_katamuki=8;}
ch.img=g_image[g_katamuki];
//SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 0 ) ;
DrawGraph( ch.x , ch.y , ch.img , TRUE ) ;
}
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////fps表示////////////////////////////////////////////////////////////
//引数 なし
//返値 なし
void fps(){
int color_white;
color_white= GetColor( 255 , 255 , 255 ) ;//色取得
static int FpsTime[2]={0,},FpsTime_i=0;
static double Fps=0.0;
if(FpsTime_i== 0)
FpsTime[0]=GetNowCount(); //1周目の時間取得
if(FpsTime_i==49){
FpsTime[1]=GetNowCount(); //50周目の時間取得
Fps = 1000.0f / ((FpsTime[1] - FpsTime[0]) / 50.0f);//測定した値からfpsを計算
FpsTime_i=0;
}
else
FpsTime_i++; //現在何周目かカウント
if(Fps != 0)
DrawFormatString(520,440,color_white,"Fps %.1f",Fps); //fpsを表示
DrawFormatString(520,420,color_white,"g_gtime %1d",g_gtime); //g_gtimeを表示
}
////////////////////////////////////////////////////////////////////////////////////////
**************************************************************
FPSの表示方法はC言語何でも質問サイトさんのを丸写しです。
メイン関数で宣言されているのは
haikei0();
jikimove();
fps();
g_gtime++;
ScreenFlip();
だけなので、後でチェックする時にわかりやすかと思います。
で、これを分割してコンパイル出来るようにしようと思っているのですが
どういう風に分割するかで悩み中です^^;
ブログで動画を公開されていて、そのスピード感あふれる作りに密かに期待していたんですよね。
システムとしては3種類の武器とボムがあり、敵を沢山倒すとパワーアップする模様。
武器ゲージが余っているので、今後増える予定なのかもしれません。
で、早速プレイ。
予想通り、スピード感たっぷりで敵の出現テンポも良く、気持ちよくプレイ出来ます。
なんとなく超連射68kを思い出しました。
画像を見ると弾幕ゲーみたいですが、弾速はとても速いです。
かといって避けれない訳ではなく、ちゃんと避けれるように作られているので、上手く避けれると
弾が速い分、爽快です^^
現在はステージ1のみプレイ出来るのですが、とても面白かったので今後に期待大です^^
ここ最近、全くプログラム関連の記事を書いてませんでしたが、そもそも書かなくなったキッカケは
C言語/C++に関してかなり挫折してたんですよね。
本やネットのサンプルを参考に簡単なプログラムなら作れるのですが、殆ど真似してるような物で
ちゃんと理解出来てないので、応用が利かないんです。
以前シューティングゲームプログラミングという本を購入したのですが、この本はC++で作成されて
いるのと、独自のライブラリを作成してゲームを作っていくので、全くの初心者の私には難しい本
でした。
で、C言語あってのC++だろうって事で、まずはC言語を覚えようと思って、この本を購入しました。
この本はVC++2008EE(使うのはC言語)とDXライブラリを使ってゲームを作る解説をしていくので
良いかなぁと。
で、読んでみたのですが、一つのサンプルを膨らませる感じでゲームを作っていくので
こんな風にプログラムを作っていくんだな~と言う、プログラムの流れを理解するのには
良い感じです。
ただ、ゲームを動かす為の関数が最初から用意されており、それの解説がなく
いきなり、その関数を使ってのゲーム作成に入っていくので、全くの初心者が読むと理解出来ないかも。
この本の他に、C言語の入門書みたいなのが欲しい所です。
と言う訳で、そろそろゲーム作成を再開させようかと思っているのですが、もう一度C言語で
0から作ってみて、それでも挫折してしまったらHSPで作ります^^;
北米版、1990円でした。このソフト日本版もあるのですがプレミアが付いているみたいで
結構高かったんですよね。
でも北米版だと2000円程度で購入出来るようだったので北米版を購入しました。
で、早速プレイしようと思って起動させてみたのですが・・・
問題が発生したと表示されて全く動きません(汗)
アレレ?XBOX360でも起動可能って事で買ったのに何故???と思いググってみたら
本体の画面の設定を480Pに設定しないと起動出来ない模様。
で、設定を変えたら無事起動しました^^
収録ゲームは
◇RYGAR(アルゴスの戦士)
◇スターフォース
◇雷牙
◇PLEIADS(プレアデス)
◇SWIMMER(スイマー)
◇SENJYO
◇ボンジャック
◇ピンボールアクション
◇テクモカップ
◇ソロモンの鍵
◇テクモボウル
の11種類。
起動して驚いたのは日本語表示されている点。北米版を買ったはずなのに何故???
と思い調べてみると、本体の言語の設定が日本語だと日本版となり、英語だと英語版に
勝手に切り替わるようです。
日本語設定で起動させると
アルゴスの戦士となりますが、これが英語設定だと
RYGAR(アルゴスの戦士の海外名)となります。
北米版では日本版がプレイ出来ないから、日本版のTECMO CLASSIC ARCADEにプレミアが
付いているんだと思っていたのですが、北米版でも日本版がプレイ出来るとなると
日本版のTECMO CLASSIC ARCADEには、他に何か魅力があるんでしょうか。
ゲームソフト自体の出来も良く出来ていて、ゲーム毎に画面や難易度設定等もあります。
他にもインストカードを見れるモード等もあり、こういうソフトにしてはかなり充実した内容ではないかと。
移植度も、特に問題ないと思います。たまに音楽がおかしくなる時があるのですが
XBOX360でプレイしているからでしょうかね?
簡単に収録ゲームを紹介。
@スターフォース
言わずと知れた名作STG。テンポ良く進んでいくゲーム展開や軽快なBGMと相まって
かなり面白いです。隠しフューチャーも多数存在し、現在のSTGのお手本のような作品。
コレが目的で、このソフトを購入しました^^
@アルゴスの戦士
ヨーヨーのような武器を使って進む横スクロールのアクションゲーム。難易度はかなり高めで
当時もクリア出来ませんでしたが、久々にプレイしたら速攻でゲームオーバーになりました^^;
@ソロモンの鍵
ブロックを消したり出したりして扉まで進むパズルゲーム。
アーケードでは殆どプレイしませんでしたがセガマークIII版でプレイしまくってました。
@ボンジャック
画面内の爆弾を全部取していくジャンプアクションゲーム。点火する順番に爆弾を取ると高得点。
BGMがオリジナルと違っていましたが、プレイ感覚は問題なし。
@スイマー
流れてくる敵や流木などを避けながらゴールを目指すゲーム。
子供の頃、近所の駄菓子屋でアップライトの筐体でプレイしていました。
リバーパトロールもプレイしたいな~。
@テクモカップ
テーブル型のような筐体で上下に分かれてプレイするサッカーゲーム。トラックボールでプレイします。
当時のゲーセンには必ずあったのではないかと思うくらい良く見かけました。
対戦プレイが熱いです^^
@雷牙
横スクロールのSTG。このゲーム初めてプレイしましたが、B級な感じがとても好きです^^;
左右に打ち分けるシステムで、同時プレイもあり。音楽もFM音源ですし、結構面白いですよ。
@テクモボウル
アメフトのゲーム。アメフトのルールがわからないので、良くわかりません(汗)
@SENJYO
照準を動かして敵を撃つ3DSTG?凄く難しいです。
@プレアデス
インベーダーとギャラクシアンとムーンクレスタを足して3で割ったようなSTG。
色使いといい、音楽といい、昔のゲームって感じがして良いです。
@ピンボールアクション
ピンボールのゲームです。このゲームだけ何故かボタンの反応がとても悪いです。
と言う訳で、11個もゲームが入っていますし、移植度も問題ないみたいなので
結構お買い得な気がします。入手しにくいのが難点ですが^^;
| 07 | 2026/08 | 09 |
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 | 31 |
好きなSTGは、怒首領蜂大往生、エスプガルーダ(2)等の弾幕STGやら雷電シリーズなんかの非弾幕、バトルガレッガ、グラディウスシリーズ、R-TYPE等、STGなら何でも好きです。
音楽がカッコイイSTGが特に好きで、並木学氏は最高!