トップページ > 過去ログ > 記事閲覧
fpsの表示と画像位置について
名前:I'll 日時: 2008/01/18 23:54

はじめまして、I'llと申します。 二か月前ぐらいからC言語を習っています。 今、シューティングゲームを製作しているのですが、fpsを画面下の左側に表示させたいのですがどうすればいいでしょうか。 あと、実機が画面外(上と下)にはみ出てしまうのですが、どうすればはみ出なくなりますか。 また、実機が弾を撃つと 中心からではなく 少し右側から撃ってしまうんですが 中心に変えるのはどうすればいいのでしょうか。 質問が多いですが、よろしくお願い致します。 OS:WindowsXP ライブラリ:DXライブラリ 開発言語:C言語 開発環境ソフト:Visual C++ 2005 Express Edition // BGMを読み込み、ハンドルを取得する sys.bgm = LoadSoundMem( "202_level1.mp3" ); ChangeVolumeSoundMem( 255/5, sys.bgm ); // 音量を下げる(0〜255) // ショットSEを読み込み、ハンドルを取得する sys.shot = LoadSoundMem( "normalShot.wav" ); // ヒットSEを読み込み、ハンドルを取得する sys.hit = LoadSoundMem( "hit.wav" ); // 爆発SEを読み込み、ハンドルを取得する sys.destroy = LoadSoundMem( "destroy.wav" ); // グラフィックのロード sys.pg = LoadGraph( "Ball.png" ) ; // プレイヤーの機体 sys.bgg = LoadGraph( "bg.png" ) ; // 背景チップ群 sys.eg[0] = LoadGraph( "chara.png" ) ; // 敵キャラ群 sys.efg = LoadGraph( "enemyBomb.png" ) ; // エフェクト群 sys.psg[0] = LoadGraph("Shot.PNG") ; // キャラクターの初期位置を画面下真ん中にセット sys.px = 640/2-32/*自機の横幅*//2 ; sys.py = 480-32/*自機の縦幅*/; // キャラクター操作関数をセット addTask(TASK_PLAYERINPUT, playerMove, 0, 0, 0, NULL); // 背景を描画する関数をセット/* 開始位置==bgTile末尾の1画面の先頭 */ addTask(TASK_BGMAP, bgMapping, 0, (MAP_H/CHIP_SIZE)*((sizeof(bgTile)/(MAP_W/CHIP_SIZE)) / (MAP_H/CHIP_SIZE)-1), 0, NULL); // 背景をスクロールする関数をセット //addTask(TASK_BGSCROLL, bgScroll, 8, 0, 0, NULL); // ループなしでデータが途切れるまでスクロール addTask(TASK_BGSCROLL, bgScroll, 8, 1, 0, NULL); // 最初の画面を永久にスクロール // プレイヤーを描画する関数をセット addTask(TASK_DRAWPG, drawPlayer, 0, 0, 0, NULL); // プレイヤーの動きを制限する関数をセット addTask(TASK_CLIPPLAYER, clipPlayer, 0, 0, 0, NULL); // 敵キャラを発生させる関数をセット addTask(TASK_GENERATEENEMY, generateEnemy, 0, 0, 0, NULL); // 弾の接触判定を取る関数をセット addTask(TASK_HITCOUNT, hitCount, 0, 0, 0, NULL); // BGM再生 PlaySoundMem( sys.bgm, DX_PLAYTYPE_LOOP ) ; // ループ while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) { // 画面を初期化する ClearDrawScreen() ; // 全部のタスクの処理 for(int i=0; i<TASK_MAX; i++){ tasks[i].task(tasks[i].p0, tasks[i].p1, tasks[i].p2, tasks[i].d); } // 裏画面の内容を表画面に反映させる ScreenFlip() ; } DxLib_End() ; // DXライブラリ使用の終了処理 return 0 ; // ソフトの終了 } int addTask(int ind, tasktype task, int p0, int p1, int p2, void* d) { if(tasks[ind].task == noop){ tasks[ind].p0 = p0; tasks[ind].p1 = p1; tasks[ind].p2 = p2; tasks[ind].task = task; tasks[ind].d = d; return 0; } else{ return -1; } } int searchBlankTask(int min, int max) { int i = min; while(i <= max){ if(tasks[i].task == noop){ return i; } i ++; } return -1; // 空きがない } int delTask(int ind) { tasks[ind].task = noop; if(tasks[ind].d != NULL){ // 確保したメモリを開放する free(tasks[ind].d); tasks[ind].d = NULL; } return 0; } int noop(int dmy0, int dmy1, int dmy2, void* dmy3) { return 0; } int playerMove(int dmy0, int dmy1, int dmy2, void* dmy3) { // キー入力取得 int Key = GetJoypadInputState( DX_INPUT_KEY_PAD1 ) ; // 上を押していたら上に進む if( Key & PAD_INPUT_UP ) sys.py -= 3 ; // 下を押していたら下に進む if( Key & PAD_INPUT_DOWN ) sys.py += 3 ; // 右を押していたら右に進む if( Key & PAD_INPUT_RIGHT ) sys.px += 3 ; // 左を押していたら左に進む if( Key & PAD_INPUT_LEFT ) sys.px -= 3 ; // Zを押していたらSHOT if( Key & PAD_INPUT_A &&pad==0 ){ pad=10; int ind = searchBlankTask(TASK_PLAYERSHOT_BEGIN, TASK_PLAYERSHOT_END); if(ind != -1){ NORMALSHOT* ns = (NORMALSHOT*)malloc(sizeof(NORMALSHOT)); memset(ns, 0, sizeof(NORMALSHOT)); // nsのメンバ変数をすべて0(NULL)で初期化 ns->speedX = 0; ns->speedY = -13; ns->taskIndex = ind; // 弾をタスクに登録して、 addTask(ind, playerShot, sys.px+16, sys.py, 0, ns); // ショット音を鳴らす PlaySoundMem( sys.shot, DX_PLAYTYPE_BACK ); } } if( pad>0) pad--; return 0; } int playerShot(int ox, int oy, int dmy2, void* shotinfo) { NORMALSHOT* ns = (NORMALSHOT*)shotinfo; DrawRectGraph(ox+ns->speedX, oy+ns->speedY, 0, 0, 22, 16, sys.psg[0], TRUE, FALSE); //DrawCircle(ox+ns->speedX, oy+ns->speedY, 10, GetColor(255, 255, 0), FALSE); // 次の発射地点を決める tasks[ ns->taskIndex ].p0 = ox+ns->speedX; // 次にこの関数が呼ばれる時の ox となる tasks[ ns->taskIndex ].p1 = oy+ns->speedY; // 次にこの関数が呼ばれる時の oy となる // 画面外に出たらタスクを消す if(ox < 0 - 10 || ox > 640 + 10 || oy < 0 - 10 || oy > 480 + 10){ delTask( ns->taskIndex ); } return 0; } // int bgMapping( 現在のスクロール量, bgTile内の読み込み開始行, 未使用, 未使用 ) int bgMapping(int dy, int line, int dmy2, void* dmy3) { // 現在表示すべき背景を作成する unsigned char newbg[ MAP_H/CHIP_SIZE+1 ][ MAP_W/CHIP_SIZE ]; BgCreate( (unsigned char*)newbg ); for(int x=0; x<MAP_W/CHIP_SIZE; x++){ for(int y=0; y<MAP_H/CHIP_SIZE + 1/*1行分多く描画する*/; y++){ DrawRectGraph(x*CHIP_SIZE+SPAN_LR, (y-1)*CHIP_SIZE+dy, newbg[y][x]%3*CHIP_SIZE+(newbg[y][x]%3+1)*8, newbg[y][x]/3*CHIP_SIZE+(newbg[y][x]/3+1)*8, CHIP_SIZE, CHIP_SIZE, sys.bgg, FALSE, FALSE); } } return 0; } int bgScroll(int scrollY, int IsLoop, int dmy2, void* dmy3) { // スクロールさせる tasks[ TASK_BGMAP ].p0 += scrollY; // 1行分以上スクロールした場合、次に読み込む開始行および表示位置を決める if(tasks[ TASK_BGMAP ].p0 / CHIP_SIZE){ // 読み込み行を1行上げる tasks[ TASK_BGMAP ].p1 -= (tasks[ TASK_BGMAP ].p0 / CHIP_SIZE); if(tasks[ TASK_BGMAP ].p1 < 0 && IsLoop == 0){ // マップ終端=bgTileの0行目は越えないようにする tasks[ TASK_BGMAP ].p1 = 0; tasks[ TASK_BGMAP ].p0 = CHIP_SIZE; } else{ tasks[ TASK_BGMAP ].p0 = tasks[ TASK_BGMAP ].p0 % CHIP_SIZE; } } #if 0 if(IsLoop){ // ループモードの場合、bgTile末尾の2画面を繰り返す // 1画面分スクロールしたなら、マップ頭を元の位置に戻す if(tasks[ TASK_BGMAP ].p0 == MAP_H){ tasks[ TASK_BGMAP ].p0 = 0; tasks[ TASK_BGMAP ].p1 = MAP_H/CHIP_SIZE-1; } } else{ // CHIP_SIZEと同じ値になったらラインをずらす if(tasks[ TASK_BGMAP ].p0 == CHIP_SIZE){ tasks[ TASK_BGMAP ].p0 = 0; // マップ終端でなければ if(bgTile[ tasks[ TASK_BGMAP ].p1 != 0){ // マップを進める tasks[ TASK_BGMAP ].p1 --; } } } #endif return 0; } int BgCreate(unsigned char* newbg) { if(tasks[ TASK_BGSCROLL ].p1 == 1){ // ループ背景の時 tasks[ TASK_BGMAP ].p1 %= (MAP_H/CHIP_SIZE); for(int i=0; i<((MAP_H/CHIP_SIZE)+1); i++){ // 転送する行 int srcline = i+tasks[ TASK_BGMAP ].p1+(sizeof(bgTile)/(MAP_W/CHIP_SIZE)-1); // 最終行を超えたら巻き戻す if(srcline >= sizeof(bgTile)/(MAP_W/CHIP_SIZE)){ memmove(newbg+(i*(MAP_W/CHIP_SIZE)), bgTile[ srcline-(MAP_H/CHIP_SIZE) ], (MAP_W/CHIP_SIZE)); } else{ memmove(newbg+(i*(MAP_W/CHIP_SIZE)), bgTile[ srcline ], (MAP_W/CHIP_SIZE)); } } } else{ memmove(newbg, bgTile[ tasks[ TASK_BGMAP ].p1 ], ((MAP_H/CHIP_SIZE)+1)*(MAP_W/CHIP_SIZE)); } return 0; } int drawPlayer(int dmy0, int dmy1, int dmy2, void* d) { // プレイヤーを描画する DrawGraph( sys.px , sys.py , sys.pg , TRUE ) ; return 0; } int clipPlayer(int dmy0, int dmy1, int dmy2, void* d) { if(sys.px < 0+SPAN_LR){ sys.px = 0+SPAN_LR; } if(sys.px > 640-32/*自機の横幅*/-SPAN_LR){ sys.px = 640-32-SPAN_LR; } // 縦はめりこみ許可 if(sys.py < 0-32/*自機の縦幅*//2){ sys.py = 0-32/*自機の縦幅*//2; } if(sys.py > 480-32/*自機の縦幅*/+32/*自機の縦幅*//2){ sys.py = 480-32+32/*自機の縦幅*//2; } return 0; } int generateEnemy(int dmy0, int dmy1, int dmy2, void* d) { if(rand()%ENCOUNT == 0){ int ind = searchBlankTask(TASK_ENEMY_BEGIN, TASK_ENEMY_END); if(ind != -1){ ENEMYDATA* en = (ENEMYDATA*)malloc(sizeof(ENEMYDATA)); memset(en, 0, sizeof(ENEMYDATA)); // enのメンバ変数をすべて0(NULL)で初期化 en->speedX = 0; en->speedY = 6; en->hp = 1; en->taskIndex = ind; // 敵をタスクに登録 int x = rand()%(MAP_W-32)+SPAN_LR; // 初期X位置 int y = -32; // 初期Y位置 addTask(ind, enemyMove, x, y, 0, en); } } return 0; } int enemyMove(int ox, int oy, int dmy2, void* enemyinfo) { ENEMYDATA* en = (ENEMYDATA*)enemyinfo; DrawRectGraph(ox+en->speedX, oy+en->speedY, 300, 48, 32, 32, sys.eg[0], TRUE, FALSE); // 次の発射地点を決める tasks[ en->taskIndex ].p0 = ox+en->speedX; // 次にこの関数が呼ばれる時の ox となる tasks[ en->taskIndex ].p1 = oy+en->speedY; // 次にこの関数が呼ばれる時の oy となる // 画面外に出たらタスクを消す if(ox < 0 - 32 || ox > 640 + 32 || oy < 0 - 32 || oy > 480 + 32){ delTask( en->taskIndex ); }

Page: 1 |

Re: fpsの表示と画像位置について ( No.1 )
名前: 日時:2008/01/19 01:07

いっぺんにいろいろやろうとすると、 帰って混乱してバグを作り込んでしまいます。 1つ1つ確実に。 まずはFPSのテキトウなさんぷる。 #include "DxLib.h" int FpsFilp( void ); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { int GetFpsCnt = 0; //デフォルトではフルスクリーンモード起動となる ChangeWindowMode(TRUE); // 画面モードの変更 SetGraphMode( 640 , 480 , 16 ); DxLib_Init(); while(!ProcessMessage() && CheckHitKey(KEY_INPUT_ESCAPE )!=1 ) { // 画面の初期化 ClearDrawScreen() ; //FPSの表示 DrawFormatString( 0, 460, 0xFFFF0000,"FPS=%d", GetFpsCnt ); GetFpsCnt = FpsFilp(); } DxLib_End(); return TRUE; } int FpsFilp( void ) { static int fps = 0; static int cnt = 0; static int savetime = GetNowCount(); // 何度画面を入れ替えたかカウント ScreenFlip(); cnt++; // 1秒おきに更新入れ替えたカウントを更新 if ( savetime + 1000 <= GetNowCount()){ savetime = GetNowCount(); fps = cnt; cnt = 0; } return fps; }
Re: fpsの表示と画像位置について ( No.2 )
名前:ライブラリ使用者 日時:2008/01/19 01:20

fpsはそのまま。。 タスク処理のループ回数を秒で計算して、表示させるだけです。 playerMove()にて移動量変化させている場合に、上限下限の調整してないせいでしょうかね。 sys.py -= 3 で、0以下または640以上なら加えないとか。 勿論実機のサイズ考慮必要あり 弾はどこで打ってるのだろ。。 実機の真ん中は横幅/2しているので、弾の横幅を÷2し忘れているとか? (実機の真ん中が弾の左端になっていないかという事)
Re: fpsの表示と画像位置について ( No.3 )
名前:I'll 日時:2008/01/19 12:38

返信ありがとうございます。 >>通 様 fpsの表示はどこに入力すればいいのでしょうか。 全部、ソースを書きますので よろしくお願いします。 >>ライブラリ使用者様 どうしても、分かりませんのでソースコードを見て 修正していただけませんか? よろしくお願いいたします。 #include "DxLib.h" #include "shot.h" #include "enemy.h" #include "effect.h" #include <math.h> #define SPAN_LR 128 // 背景の左右の空き領域(の片方分のピクセル数) #define MAP_W (640-SPAN_LR*2) // マップ領域 横 #define MAP_H 480 // マップ領域 縦 #define CHIP_SIZE 32 // 背景チップは32x32ピクセルとする(マップ領域縦横の公約数でなくてはいけない) #define ENCOUNT 18 // 敵機が出てくる頻度(小さいほどたくさん出てきます) enum eTasks{ TASK_BEGIN = 0, // 全体のタスク開始番号 TASK_PLAYERINPUT = 0, // プレイヤーの入力を見る TASK_BGMAP , // 背景を描画する TASK_BGSCROLL , // 背景をスクロールする TASK_CLIPPLAYER , // プレイヤーの動ける領域を制限する TASK_DRAWPG , // プレイヤーを描画する TASK_GENERATEENEMY , // 敵キャラを発生させる TASK_HITCOUNT , // 自弾と敵機の接触判定を取る TASK_PLAYERSHOT_BEGIN = 10, // プレイヤー弾は10番から200番、つまり190発までなら画面上に表示可能 TASK_PLAYERSHOT_END = 200, TASK_ENEMY_BEGIN = 300, // 敵キャラは300番から350番、つまり50キャラまでなら画面上に表示可能 TASK_ENEMY_END = 350, TASK_ENEMYSHOT_BEGIN = 400, // 敵キャラ弾は400番から450番、つまり50発までなら画面上に表示可能 TASK_ENEMYSHOT_END = 450, TASK_ENEMYDESTROY_BEGIN = 500, // 敵キャラ爆発エフェクトは500番から550番、つまり50キャラまでなら画面上に爆発可能 TASK_ENEMYDESTROY_END = 550, TASK_MAX, }; typedef struct{ int px, py; // プレイヤーのX座標・Y座標 int bgg; // 背景チップグラフィックハンドル int pg; // プレイヤーグラフィックハンドル int efg; // エフェクトグラフィックハンドル int psg[ 10 ]; // プレイヤー弾グラフィックハンドル int esg[ 10 ]; // ザコ敵弾グラフィックハンドル int eg[ 10 ]; // ザコ敵たちのグラフィックハンドル int bgm; // BGMサウンドハンドル int shot; // ショットSEサウンドハンドル int hit; // ヒットSEサウンドハンドル int destroy; // 爆発SEサウンドハンドル // 必要なものを順次追加 } SYSTEMDATA; // グローバル変数として宣言 SYSTEMDATA sys; int pad=0; // タスクの構造体 typedef int (*tasktype)(int, int, int, void*); typedef struct{ int p0; // 引数1つ目を保存する変数 int p1; // 引数2つ目を保存する変数 int p2; // 引数3つ目を保存する変数 tasktype task; // int型戻り値、引数3つ取る関数ポインタ void* d; // 汎用データポインタ(※要メモリ確保) } TASKDATA; // グローバル変数として宣言 TASKDATA tasks[ TASK_MAX ]; // 最大に同時に回せるのはTASK_MAX個まで // プロトタイプ宣言 // タスクを追加する関数 int addTask(int ind, tasktype task, int p0, int p1, int p2, void* d); // タスクを消す関数(noopを代入するだけ) int delTask(int ind); // タスクの空きを探す関数 int searchBlankTask(int min, int max); // 現在の背景のチップを配置する関数 int BgCreate(unsigned char* newbg); // タスク int noop(int dmy0, int dmy1, int dmy2, void* dmy3); int playerMove(int dmy0, int dmy1, int dmy2, void* dmy3); int playerShot(int ox, int oy, int dmy2, void* shotinfo); //int bgMapping(int dmy0, int dmy1, int dmy2, void* dmy3); int bgMapping(int dy/*0~CHIP_SIZE*/, int line, int dmy2, void* dmy3); int bgScroll(int scrollY, int IsLoop, int dmy2, void* dmy3); int drawPlayer(int dmy0, int dmy1, int dmy2, void* d); int clipPlayer(int dmy0, int dmy1, int dmy2, void* d); int generateEnemy(int dmy0, int dmy1, int dmy2, void* d); int enemyMove(int ox, int oy, int dmy2, void* enemyinfo); int drawDestroy(int ox, int oy, int count, void* effectinfo); int hitCount(int dmy0, int dmy1, int dmy2, void* d); // 背景チップのマッピング unsigned char bgTile[][ MAP_W/CHIP_SIZE ] = { // 12*15個 ////////////////////////////////////////////////////////////////////////////////////////////////マップ終端 0, 1, 2, 6, 7, 8, 0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11, 3, 4, 5, 9, 10, 11, 6, 7, 8, 0, 1, 2, 6, 7, 8, 0, 1, 2, 9, 10, 11, 3, 4, 5, 9, 10, 11, 3, 4, 5, 0, 1, 2, 6, 7, 8, 0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11, 3, 4, 5, 9, 10, 11, 6, 7, 8, 0, 1, 2, 6, 7, 8, 0, 1, 2, 9, 10, 11, 3, 4, 5, 9, 10, 11, 3, 4, 5, 0, 1, 2, 6, 7, 8, 0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11, 3, 4, 5, 9, 10, 11, 6, 7, 8, 0, 1, 2, 6, 7, 8, 0, 1, 2, 9, 10, 11, 3, 4, 5, 9, 10, 11, 3, 4, 5, 0, 1, 2, 6, 7, 8, 0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11, 3, 4, 5, 9, 10, 11, 6, 7, 8, 0, 1, 2, 6, 7, 8, 0, 1, 2, 0, 1, 2, 6, 7, 8, 0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11, 3, 4, 5, 9, 10, 11, 6, 7, 8, 0, 1, 2, 6, 7, 8, 0, 1, 2, 9, 10, 11, 3, 4, 5, 9, 10, 11, 3, 4, 5, 0, 1, 2, 6, 7, 8, 0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11, 3, 4, 5, 9, 10, 11, 6, 7, 8, 0, 1, 2, 6, 7, 8, 0, 1, 2, 9, 10, 11, 3, 4, 5, 9, 10, 11, 3, 4, 5, 0, 1, 2, 6, 7, 8, 0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11, 3, 4, 5, 9, 10, 11, 6, 7, 8, 0, 1, 2, 6, 7, 8, 0, 1, 2, 9, 10, 11, 3, 4, 5, 9, 10, 11, 3, 4, 5, 0, 1, 2, 6, 7, 8, 0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11, 3, 4, 5, 9, 10, 11, 6, 7, 8, 0, 1, 2, 6, 7, 8, 0, 1, 2, 0, 1, 2, 6, 7, 8, 0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11, 3, 4, 5, 9, 10, 11, 6, 7, 8, 0, 1, 2, 6, 7, 8, 0, 1, 2, 9, 10, 11, 3, 4, 5, 9, 10, 11, 3, 4, 5, 0, 1, 2, 6, 7, 8, 0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11, 3, 4, 5, 9, 10, 11, 6, 7, 8, 0, 1, 2, 6, 7, 8, 0, 1, 2, 9, 10, 11, 3, 4, 5, 9, 10, 11, 3, 4, 5, 0, 1, 2, 6, 7, 8, 0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11, 3, 4, 5, 9, 10, 11, 6, 7, 8, 0, 1, 2, 6, 7, 8, 0, 1, 2, 9, 10, 11, 3, 4, 5, 9, 10, 11, 3, 4, 5, 0, 1, 2, 6, 7, 8, 0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11, 3, 4, 5, 9, 10, 11, 6, 7, 8, 0, 1, 2, 6, 7, 8, 0, 1, 2, // 最初の1画面分のチップ配列 0, 1, 2, 6, 7, 8, 0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11, 3, 4, 5, 9, 10, 11, 6, 7, 8, 0, 1, 2, 6, 7, 8, 0, 1, 2, 9, 10, 11, 3, 4, 5, 9, 10, 11, 3, 4, 5, 0, 1, 2, 6, 7, 8, 0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11, 3, 4, 5, 9, 10, 11, 6, 7, 8, 0, 1, 2, 6, 7, 8, 0, 1, 2, 9, 10, 11, 3, 4, 5, 9, 10, 11, 3, 4, 5, 0, 1, 2, 6, 7, 8, 0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11, 3, 4, 5, 9, 10, 11, 6, 7, 8, 0, 1, 2, 6, 7, 8, 0, 1, 2, 9, 10, 11, 3, 4, 5, 9, 10, 11, 3, 4, 5, 0, 1, 2, 6, 7, 8, 0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11, 3, 4, 5, 9, 10, 11, 6, 7, 8, 0, 1, 2, 6, 7, 8, 0, 1, 2, ////////////////////////////////////////////////////////////////////////////////////////////////マップ開始 }; int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { // 構造体を0(ゼロ)初期化 ZeroMemory(tasks, sizeof(tasks)); ZeroMemory(&sys, sizeof(sys)); // すべてのタスクをnoop for(int i=0; i<TASK_MAX; i++){ tasks[i].task = noop; } // 画面モードのセット SetGraphMode( 640 , 480 , 16 ) ; ChangeWindowMode(TRUE); // 重要! //SetUseDirectDrawFlag( FALSE ); if( DxLib_Init() == -1 ) // DXライブラリ初期化処理 { return -1; // エラーが起きたら直ちに終了 } // 描画先画面を裏画面にセット SetDrawScreen( DX_SCREEN_BACK ) ; // サウンドはストリーム再生する SetCreateSoundDataType( DX_SOUNDDATATYPE_MEMPRESS ) ; // BGMを読み込み、ハンドルを取得する sys.bgm = LoadSoundMem( "202_level1.mp3" ); ChangeVolumeSoundMem( 255/5, sys.bgm ); // 音量を下げる(0〜255) // ショットSEを読み込み、ハンドルを取得する sys.shot = LoadSoundMem( "normalShot.wav" ); // ヒットSEを読み込み、ハンドルを取得する sys.hit = LoadSoundMem( "hit.wav" ); // 爆発SEを読み込み、ハンドルを取得する sys.destroy = LoadSoundMem( "destroy.wav" ); // グラフィックのロード sys.pg = LoadGraph( "Ball.png" ) ; // プレイヤーの機体 sys.bgg = LoadGraph( "bg.png" ) ; // 背景チップ群 sys.eg[0] = LoadGraph( "chara.png" ) ; // 敵キャラ群 sys.efg = LoadGraph( "enemyBomb.png" ) ; // エフェクト群 sys.psg[0] = LoadGraph("Shot.PNG") ; // キャラクターの初期位置を画面下真ん中にセット sys.px = 640/2-32/*自機の横幅*//2 ; sys.py = 480-32/*自機の縦幅*/; // キャラクター操作関数をセット addTask(TASK_PLAYERINPUT, playerMove, 0, 0, 0, NULL); // 背景を描画する関数をセット/* 開始位置==bgTile末尾の1画面の先頭 */ addTask(TASK_BGMAP, bgMapping, 0, (MAP_H/CHIP_SIZE)*((sizeof(bgTile)/(MAP_W/CHIP_SIZE)) / (MAP_H/CHIP_SIZE)-1), 0, NULL); // 背景をスクロールする関数をセット //addTask(TASK_BGSCROLL, bgScroll, 8, 0, 0, NULL); // ループなしでデータが途切れるまでスクロール addTask(TASK_BGSCROLL, bgScroll, 8, 1, 0, NULL); // 最初の画面を永久にスクロール // プレイヤーを描画する関数をセット addTask(TASK_DRAWPG, drawPlayer, 0, 0, 0, NULL); // プレイヤーの動きを制限する関数をセット addTask(TASK_CLIPPLAYER, clipPlayer, 0, 0, 0, NULL); // 敵キャラを発生させる関数をセット addTask(TASK_GENERATEENEMY, generateEnemy, 0, 0, 0, NULL); // 弾の接触判定を取る関数をセット addTask(TASK_HITCOUNT, hitCount, 0, 0, 0, NULL); // BGM再生 PlaySoundMem( sys.bgm, DX_PLAYTYPE_LOOP ) ; // ループ while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) { // 画面を初期化する ClearDrawScreen() ; // 全部のタスクの処理 for(int i=0; i<TASK_MAX; i++){ tasks[i].task(tasks[i].p0, tasks[i].p1, tasks[i].p2, tasks[i].d); } // 裏画面の内容を表画面に反映させる ScreenFlip() ; } DxLib_End() ; // DXライブラリ使用の終了処理 return 0 ; // ソフトの終了 } int addTask(int ind, tasktype task, int p0, int p1, int p2, void* d) { if(tasks[ind].task == noop){ tasks[ind].p0 = p0; tasks[ind].p1 = p1; tasks[ind].p2 = p2; tasks[ind].task = task; tasks[ind].d = d; return 0; } else{ return -1; } } int searchBlankTask(int min, int max) { int i = min; while(i <= max){ if(tasks[i].task == noop){ return i; } i ++; } return -1; // 空きがない } int delTask(int ind) { tasks[ind].task = noop; if(tasks[ind].d != NULL){ // 確保したメモリを開放する free(tasks[ind].d); tasks[ind].d = NULL; } return 0; } int noop(int dmy0, int dmy1, int dmy2, void* dmy3) { return 0; } int playerMove(int dmy0, int dmy1, int dmy2, void* dmy3) { // キー入力取得 int Key = GetJoypadInputState( DX_INPUT_KEY_PAD1 ) ; // 上を押していたら上に進む if( Key & PAD_INPUT_UP ) sys.py -= 5 ; // 下を押していたら下に進む if( Key & PAD_INPUT_DOWN ) sys.py += 5 ; // 右を押していたら右に進む if( Key & PAD_INPUT_RIGHT ) sys.px += 5 ; // 左を押していたら左に進む if( Key & PAD_INPUT_LEFT ) sys.px -= 5 ; // Zを押していたらSHOT if( Key & PAD_INPUT_A &&pad==0 ){ pad=10; int ind = searchBlankTask(TASK_PLAYERSHOT_BEGIN, TASK_PLAYERSHOT_END); if(ind != -1){ NORMALSHOT* ns = (NORMALSHOT*)malloc(sizeof(NORMALSHOT)); memset(ns, 0, sizeof(NORMALSHOT)); // nsのメンバ変数をすべて0(NULL)で初期化 ns->speedX = 0; ns->speedY = -13; ns->taskIndex = ind; // 弾をタスクに登録して、 addTask(ind, playerShot, sys.px+16, sys.py, 0, ns); // ショット音を鳴らす PlaySoundMem( sys.shot, DX_PLAYTYPE_BACK ); } } if( pad>0) pad--; return 0; } int playerShot(int ox, int oy, int dmy2, void* shotinfo) { NORMALSHOT* ns = (NORMALSHOT*)shotinfo; DrawRectGraph(ox+ns->speedX, oy+ns->speedY, 0, 0, 22, 16, sys.psg[0], TRUE, FALSE); //DrawCircle(ox+ns->speedX, oy+ns->speedY, 10, GetColor(255, 255, 0), FALSE); // 次の発射地点を決める tasks[ ns->taskIndex ].p0 = ox+ns->speedX; // 次にこの関数が呼ばれる時の ox となる tasks[ ns->taskIndex ].p1 = oy+ns->speedY; // 次にこの関数が呼ばれる時の oy となる // 画面外に出たらタスクを消す if(ox < 0 - 10 || ox > 640 + 10 || oy < 0 - 10 || oy > 480 + 10){ delTask( ns->taskIndex ); } return 0; } // int bgMapping( 現在のスクロール量, bgTile内の読み込み開始行, 未使用, 未使用 ) int bgMapping(int dy, int line, int dmy2, void* dmy3) { // 現在表示すべき背景を作成する unsigned char newbg[ MAP_H/CHIP_SIZE+1 ][ MAP_W/CHIP_SIZE ]; BgCreate( (unsigned char*)newbg ); for(int x=0; x<MAP_W/CHIP_SIZE; x++){ for(int y=0; y<MAP_H/CHIP_SIZE + 1/*1行分多く描画する*/; y++){ DrawRectGraph(x*CHIP_SIZE+SPAN_LR, (y-1)*CHIP_SIZE+dy, newbg[y][x]%3*CHIP_SIZE+(newbg[y][x]%3+1)*8, newbg[y][x]/3*CHIP_SIZE+(newbg[y][x]/3+1)*8, CHIP_SIZE, CHIP_SIZE, sys.bgg, FALSE, FALSE); } } return 0; } int bgScroll(int scrollY, int IsLoop, int dmy2, void* dmy3) { // スクロールさせる tasks[ TASK_BGMAP ].p0 += scrollY; // 1行分以上スクロールした場合、次に読み込む開始行および表示位置を決める if(tasks[ TASK_BGMAP ].p0 / CHIP_SIZE){ // 読み込み行を1行上げる tasks[ TASK_BGMAP ].p1 -= (tasks[ TASK_BGMAP ].p0 / CHIP_SIZE); if(tasks[ TASK_BGMAP ].p1 < 0 && IsLoop == 0){ // マップ終端=bgTileの0行目は越えないようにする tasks[ TASK_BGMAP ].p1 = 0; tasks[ TASK_BGMAP ].p0 = CHIP_SIZE; } else{ tasks[ TASK_BGMAP ].p0 = tasks[ TASK_BGMAP ].p0 % CHIP_SIZE; } } #if 0 if(IsLoop){ // ループモードの場合、bgTile末尾の2画面を繰り返す // 1画面分スクロールしたなら、マップ頭を元の位置に戻す if(tasks[ TASK_BGMAP ].p0 == MAP_H){ tasks[ TASK_BGMAP ].p0 = 0; tasks[ TASK_BGMAP ].p1 = MAP_H/CHIP_SIZE-1; } } else{ // CHIP_SIZEと同じ値になったらラインをずらす if(tasks[ TASK_BGMAP ].p0 == CHIP_SIZE){ tasks[ TASK_BGMAP ].p0 = 0; // マップ終端でなければ if(bgTile[ tasks[ TASK_BGMAP ].p1 != 0){ // マップを進める tasks[ TASK_BGMAP ].p1 --; } } } #endif return 0; } int BgCreate(unsigned char* newbg) { if(tasks[ TASK_BGSCROLL ].p1 == 1){ // ループ背景の時 tasks[ TASK_BGMAP ].p1 %= (MAP_H/CHIP_SIZE); for(int i=0; i<((MAP_H/CHIP_SIZE)+1); i++){ // 転送する行 int srcline = i+tasks[ TASK_BGMAP ].p1+(sizeof(bgTile)/(MAP_W/CHIP_SIZE)-1); // 最終行を超えたら巻き戻す if(srcline >= sizeof(bgTile)/(MAP_W/CHIP_SIZE)){ memmove(newbg+(i*(MAP_W/CHIP_SIZE)), bgTile[ srcline-(MAP_H/CHIP_SIZE) ], (MAP_W/CHIP_SIZE)); } else{ memmove(newbg+(i*(MAP_W/CHIP_SIZE)), bgTile[ srcline ], (MAP_W/CHIP_SIZE)); } } } else{ memmove(newbg, bgTile[ tasks[ TASK_BGMAP ].p1 ], ((MAP_H/CHIP_SIZE)+1)*(MAP_W/CHIP_SIZE)); } return 0; } int drawPlayer(int dmy0, int dmy1, int dmy2, void* d) { // プレイヤーを描画する DrawGraph( sys.px , sys.py , sys.pg , TRUE ) ; return 0; } int clipPlayer(int dmy0, int dmy1, int dmy2, void* d) { if(sys.px < 0+SPAN_LR){ sys.px = 0+SPAN_LR; } if(sys.px > 640-32/*自機の横幅*/-SPAN_LR){ sys.px = 640-32-SPAN_LR; } // 縦はめりこみ許可 if(sys.py < 0-32/*自機の縦幅*//2){ sys.py = 0-32/*自機の縦幅*//2; } if(sys.py > 480-32/*自機の縦幅*/+32/*自機の縦幅*//2){ sys.py = 480-32+32/*自機の縦幅*//2; } return 0; } int generateEnemy(int dmy0, int dmy1, int dmy2, void* d) { if(rand()%ENCOUNT == 0){ int ind = searchBlankTask(TASK_ENEMY_BEGIN, TASK_ENEMY_END); if(ind != -1){ ENEMYDATA* en = (ENEMYDATA*)malloc(sizeof(ENEMYDATA)); memset(en, 0, sizeof(ENEMYDATA)); // enのメンバ変数をすべて0(NULL)で初期化 en->speedX = 0; en->speedY = 6; en->hp = 1; en->taskIndex = ind; // 敵をタスクに登録 int x = rand()%(MAP_W-32)+SPAN_LR; // 初期X位置 int y = -32; // 初期Y位置 addTask(ind, enemyMove, x, y, 0, en); } } return 0; } int enemyMove(int ox, int oy, int dmy2, void* enemyinfo) { ENEMYDATA* en = (ENEMYDATA*)enemyinfo; DrawRectGraph(ox+en->speedX, oy+en->speedY, 300, 48, 32, 32, sys.eg[0], TRUE, FALSE); // 次の発射地点を決める tasks[ en->taskIndex ].p0 = ox+en->speedX; // 次にこの関数が呼ばれる時の ox となる tasks[ en->taskIndex ].p1 = oy+en->speedY; // 次にこの関数が呼ばれる時の oy となる // 画面外に出たらタスクを消す if(ox < 0 - 32 || ox > 640 + 32 || oy < 0 - 32 || oy > 480 + 32){ delTask( en->taskIndex ); } // HPがゼロになったら消して爆発 if(en->hp <= 0){ int ind = searchBlankTask(TASK_ENEMYDESTROY_BEGIN, TASK_ENEMYDESTROY_END); if(ind != -1){ EFFECTDATA* ef = (EFFECTDATA*)malloc(sizeof(EFFECTDATA)); memset(ef, 0, sizeof(EFFECTDATA)); // efのメンバ変数をすべて0(NULL)で初期化 ef->x = 8; ef->y = 8; ef->w = 32; ef->h = 32; ef->key = 10; ef->dx = 40; ef->taskIndex = ind; addTask(ind, drawDestroy, ox, oy, 0, ef); } PlaySoundMem( sys.destroy, DX_PLAYTYPE_BACK ); delTask( en->taskIndex ); } return 0; } int drawDestroy(int ox, int oy, int count, void* effectinfo) { EFFECTDATA* ef = (EFFECTDATA*)effectinfo; if(count < ef->key){ DrawRectGraph(ox, oy, ef->dx*count+ef->x, ef->dy*count+ef->y, ef->w, ef->h, sys.efg, TRUE, FALSE); // 爆発しながら加速すると気持ちいいかも(´ー`)ノ tasks[ ef->taskIndex ].p1 += 16; } else{ delTask( ef->taskIndex ); } tasks[ ef->taskIndex ].p2 ++; return 0; } int hitCount(int dmy0, int dmy1, int dmy2, void* d) { for(int i=TASK_ENEMY_BEGIN; i<TASK_ENEMY_END; i++){ if(tasks[ i ].d != NULL){ ENEMYDATA* en = (ENEMYDATA*)tasks[ i ].d; int ex = tasks[ i ].p0 + 16; int ey = tasks[ i ].p1 + 16; for(int j=TASK_PLAYERSHOT_BEGIN; j<TASK_PLAYERSHOT_END; j++){ if(tasks[ j ].d != NULL){ int tx = tasks[ j ].p0 + 5; int ty = tasks[ j ].p1 + 5; int res = (int)sqrt((long double)(abs((tx - ex)*(tx - ex)+(ty - ey)*(ty - ey)))); // 三平方の定理により円形判定 if(res <= 16){ // 弾(10x10)より敵機(32x32)の方が大きい 半径16 PlaySoundMem( sys.hit, DX_PLAYTYPE_BACK ) ; en->hp --; delTask( j ); // ヒットした弾は消去 } } } } } return 0; }
Re: fpsの表示と画像位置について ( No.4 )
名前: 日時:2008/01/20 01:07

>>fpsの表示はどこに入力すればいいのでしょうか。 前提を確認しますがFPSとはどういう物か わかっていますか? これが分かればわたしの張ったソースである程度 分かると思うのですが。。。 簡単に言うと、FPS(フレーム・パー・セコンド)とは 元来、動画などのフレームレートで1秒あたりに画面 が更新された回数の目安を表す単位です。 画面の更新とは、DXライブラリではずばり、 「ScreenFlip関数」がやってくれます。 つまり1秒間に何回この関数を呼び出したかを 調べれば、ある程度の目安になるFPSは求めることが 出来ます。 前に紹介したコードでは秒間このScreenFlipが 何回呼び出せたかをカウントしてるだけです。 よく見たらちょっとありえないコードだったので コードを修正し関数を呼ぶだけでOKなようにしました。 /* * 関数名:FpsFilp * 概 要:ScreenFlipの代わりに呼ぶだけ版 * 引 数: * [i]:x FPSを表示する位置X座標 * [i]:y FPSを表示する位置Y座標 * [i]:color FPSの表示文字列色 * 戻り値:ScreenFlip関数と同じ */ int FpsFilp( int x, int y, int color ) { int ret = 0; static int fps = 0; static int cnt = 0; static int savetime = GetNowCount(); DrawFormatString( x, y, color ,"FPS=%d", fps ); ret = ScreenFlip(); cnt++; if ( savetime + 1000 <= GetNowCount()){ savetime = GetNowCount(); fps = cnt; cnt = 0; } return ret; } やってることは上で述べたとおりです。 この関数をScreenFlip関数の代わりに呼ぶだけです ※ただし、この方法はもろにカウントしている  だけなのではっきり言って精度は無いに等しいです >どうしても、分かりませんのでソースコードを >見て 修正していただけませんか? あまり言いたくは無いのですが、せっかくここまで 綺麗なコードが書けてるのならば、Debugの技術を 磨きましょう。 他人にやってもらっては身につきません。 少なくとも、「playerMove()にて」と指摘されて いるのですから、何が分からないのかを説明して もらえないでしょうか? >実機が弾を撃つと 中心からではなく 少し右側から // 次の発射地点を決める ここのあたりを調整すればよいかと。
Re: fpsの表示と画像位置について ( No.5 )
名前:I'll 日時:2008/01/20 01:33

いろいろ、教えていただき ありがとうございます。 fps表示については、書き込む場所部分が分からずにいました。 そのまま、コピーして、どこに置き換えればいいのか分かりませんでした。 弾の地点については、もう少し頑張ってみます。

Page: 1 |