hit   今日   昨日

マップスクロール時、敵の行動について

[このトピックは解決済みです]

フォーラムルール
フォーラムルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Name: amuku
[URL]
Date: 2012年4月20日(金) 10:34
No: 1
(OFFLINE)

 マップスクロール時、敵の行動について

初投稿です。

DXライブラリ置き場 http://homepage2.nifty.com/natupaji/DxLib/dxprogram.html#N4

こちらの「マップスクロール」(スクロールが滑らかになる方)でマップを作りました。
質問なのですが、マップ上に敵がいます。
移動処理、当たり判定はなんとなく検討がついているので多分大丈夫なのですが、
自キャラが移動すると、モンスターもその方向に動き、また初期位置に戻る行動を繰り返してしまいます。
画面スクロールしても、敵をその場所に記憶させる事はできました。
例:自キャラが左へ移動→敵も一瞬左へ移動→すぐに初期位置に戻る

それと、マップスクロールを使っているため、ch.x、ch.yが機能しておらず、
キャラクターのアニメーションが向きしか機能していません。
(キャラの動きは旧ゲームプログラミング館19~22章)
どうすればマップスクロールに対応したアニメーションを行えるでしょうか。

ちなみに226~232行がキャラ、モンスター画像処理です。

コード張ります。
コード[C++]: 全て選択
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
#include "DxLib.h"
#include "def.h"
#include "Hit.h"
#include "Key.h"
 
// モンスター、プレイヤーの位置
int PlayerX , PlayerY;
int MonsterX,MonsterY;
 
// 移動しているかどうかのフラグ( 0:停止中  1:移動中 )
int Move;
 
// 各方向に移動する量
int MoveX, MoveY;
 
// 移動し始めてから何フレーム経過したかを保持する変数
int MoveCounter;
 
int hp = 1000,hp_max = 1000;    //初期HP
int ep = 0,ep_max = 1000;       //初期MP
int exp = 0,exp_max = 1000;     //初期EXP
int lvl = 1;
int MapDrawPointX , MapDrawPointY , MapDrawPointMonsX;      // 描画するマップ座標値
int DrawMapChipNumX , DrawMapChipNumY ; // 描画するマップチップの数
int idou = 0;                           //移動中の向きフラグ防止
int Key[256]; // キーが押されているフレーム数を格納する
int Stats_1 = OFF; //Item画面スイッチ処理
int ItemBox = OFF; //Item画面処理
int GameTime = 0;
 
 
ch_t ch;
mons_t mons;
 
extern int MapData[ MAP_HEIGHT ][ MAP_WIDTH ];
 
// マップとプレイヤーの描画関数
void GraphDraw( int ScrollX, int ScrollY )
{
    int j , i ;
 
    // 描画するマップチップの数をセット
    DrawMapChipNumX = 800 / MAP_SIZE + 2 ;
    DrawMapChipNumY = 600 / MAP_SIZE + 2 ;
 
    // 画面左上に描画するマップ座標をセット
    MapDrawPointX = PlayerX - ( DrawMapChipNumX / 2 - 1 ) ;
    MapDrawPointY = PlayerY - ( DrawMapChipNumY / 2 - 1 ) ;
    MapDrawPointMonsX = MonsterX - ( DrawMapChipNumX / 2 - 1 ) ;
 
    // マップを描く
    for( i = -1 ; i < DrawMapChipNumY ; i ++ )
    {
        for( j = -1 ; j < DrawMapChipNumX ; j ++ )
        {
            // 画面からはみ出た位置なら描画しない
            if( j + MapDrawPointX < 0 || i + MapDrawPointY < 0 ||
                j + MapDrawPointX >= MAP_WIDTH || i + MapDrawPointY >= MAP_HEIGHT ) continue ;
 
            // マップデータが0だったら四角を描画する
            if( MapData[ i + MapDrawPointY ][ j + MapDrawPointX ] == 0 )
            {
                DrawBox(j * MAP_SIZE + ScrollX,         i * MAP_SIZE + ScrollY,
                    j * MAP_SIZE + MAP_SIZE + ScrollX,  i * MAP_SIZE + MAP_SIZE + ScrollY,
                    GetColor( 0 , 200 , 200 ) , TRUE ) ;
            }
            // マップデータが0だったら四角を描画する
            if( MapData[ i + MapDrawPointY ][ j + MapDrawPointX ] == 1 )
            {
                DrawBox(j * MAP_SIZE + ScrollX,         i * MAP_SIZE + ScrollY,
                    j * MAP_SIZE + MAP_SIZE + ScrollX,  i * MAP_SIZE + MAP_SIZE + ScrollY,
                    GetColor( 0 , 100 , 0 ) , TRUE ) ;
            }
        }
    }
}
 
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
       
    int image[16];
    int ScrollX, ScrollY ;
 
    //画面サイズ
    SetGraphMode( 800 , 600 , 32 ) ;
 
    if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //ウィンドウ化と初期化処理
 
    ch.x    =320;
    ch.y    =160;
    ch.walking_flag=0;
    ch.muki=3;
 
    // プレイヤーの初期位置をセット
    PlayerX = 5 ;
    PlayerY = 5 ;
    MonsterX = 2;
    MonsterY = 2;
 
    // 最初は停止中(0)にしておく
    Move = 0 ;
 
    SetDrawScreen( DX_SCREEN_BACK ) ;                                                 //描画先を裏画面に設定
 
    //画像読み込み
    LoadDivGraph( "画像/char.png" , 16 , 4 , 4 , 32 , 32 , image ) ;//画像を分割してimage配列に保存
 
    while(!ProcessMessage() && !ClearDrawScreen() && gpUpdateKey()==0 && !Key[KEY_INPUT_ESCAPE]){
            //↑メッセージ処理        ↑画面をクリア         ↑キーボード入力状態取得       ↑ESCが押されると終了
 
        // 移動中ではない場合キー入力を受け付ける
        if( Move == 0 )
        {
            // キー入力を得る
//          Key[0] = GetJoypadInputState( DX_INPUT_KEY_PAD1 ) ;
           
            // キー入力に応じてプレイヤーの座標を移動
            if( (Key[ KEY_INPUT_LEFT] >= 1) && PAD_INPUT_LEFT && ch.muki == 1)
            {
                Move = 1 ;
                MoveX = -1 ;
                MoveY = 0 ;
            }
            if( (Key[ KEY_INPUT_RIGHT] >= 1) && PAD_INPUT_RIGHT && ch.muki == 3)
            {
                Move = 1 ;
                MoveX = 1 ;
                MoveY = 0 ;
            }
            if( (Key[ KEY_INPUT_UP] >= 1) && PAD_INPUT_UP && ch.muki == 0)
            {
                Move = 1 ;
                MoveX = 0 ;
                MoveY = -1 ;
            }
            if( (Key[ KEY_INPUT_DOWN] >= 1) && PAD_INPUT_DOWN && ch.muki == 2)
            {
                Move = 1 ;
                MoveX = 0 ;
                MoveY = 1 ;
            }
 
            // 進入不可能なマップだった場合は移動できない
            if( Move == 1 )
            {
                if( MapData[ PlayerY + MoveY ][ PlayerX + MoveX ] == 0 ||
                    MapData[ PlayerY + MoveY ][ PlayerX + MoveX ] == 2)
                {
                    Move = 0 ;
                }
                else
                {
                    MoveCounter = 0 ;
                }
            }
 
            // 停止中は画面のスクロールは行わない
            ScrollX = 0 ;
            ScrollY = 0 ;
        }
 
        // 移動中の場合は移動処理を行う
        if( Move == 1 )
        {
            MoveCounter +=4 ;
            idou = 1;
 
            // 移動処理が終了したら停止中にする
            if( MoveCounter == MOVE_FRAME )
            {
                Move = 0 ;
                idou = 0;
 
                // プレイヤーの位置を変更する
                PlayerX += MoveX ;
                PlayerY += MoveY ;
 
                // 停止中は画面のスクロールは行わない
                ScrollX = 0 ;
                ScrollY = 0 ;
            }
            else
            {
                // 経過時間からスクロール量を算出する
                ScrollX = -( MoveX * MAP_SIZE * MoveCounter / MOVE_FRAME ) ;
                ScrollY = -( MoveY * MAP_SIZE * MoveCounter / MOVE_FRAME ) ;
            }
        }
 
        // マップとプレイヤーを描画
        GraphDraw( ScrollX, ScrollY ) ;
 
        if(ch.x%32==0 && ch.y%32==0){         //座標が32で割り切れたら入力可能
            ch.walking_flag=1;         //歩くフラグを立てる。
            if     ( (Key[ KEY_INPUT_UP   ]  >= 1)
                    && Key[ KEY_INPUT_LEFT ]  == 0
                    && Key[ KEY_INPUT_DOWN ]  == 0
                    && Key[ KEY_INPUT_RIGHT]  == 0
                    && idou == 0)  //上ボタンが押されたら(それ以外を押されていなかったら)
                    ch.muki=0;         //上向きフラグを立てる
            else if( Key[ KEY_INPUT_LEFT ]  >= 1
                    && Key[ KEY_INPUT_UP ]  == 0
                    && Key[ KEY_INPUT_DOWN ]  == 0
                    && Key[ KEY_INPUT_RIGHT]  == 0
                    && idou == 0)  //左ボタンが押されたら
                    ch.muki=1;         //左向きフラグを立てる
            else if( Key[ KEY_INPUT_DOWN ]  >= 1
                    && Key[ KEY_INPUT_UP ]  == 0
                    && Key[ KEY_INPUT_LEFT ]  == 0
                    && Key[ KEY_INPUT_RIGHT]  == 0
                    && idou == 0)  //下ボタンが押されたら
                    ch.muki=2;         //下向きフラグを立てる
            else if( Key[ KEY_INPUT_RIGHT]  >= 1
                    && Key[ KEY_INPUT_UP ]  == 0
                    && Key[ KEY_INPUT_LEFT ]  == 0
                    && Key[ KEY_INPUT_DOWN]  == 0
                    && idou == 0)  //右ボタンが押されたら
                    ch.muki=3;         //右向きフラグを立てる
            else                                    //何のボタンも押されてなかったら
                    ch.walking_flag=0; //歩かないフラグを立てる
        }
 
//当たり判定
        MonsterHit();
 
 
//描画処理
    //キャラクター
        ch.img=image[ch.muki*4];            //画像をセット
        DrawGraph( ( PlayerX - MapDrawPointX ) * MAP_SIZE , ( PlayerY - MapDrawPointY ) * MAP_SIZE, ch.img , TRUE ) ;//画像を描画
    //モンスター
        mons.img=image[(mons.x%32+mons.y%32)/8 + mons.muki*4];            //画像をセット
        DrawGraph( ( MonsterX - MapDrawPointMonsX ) * MAP_SIZE , ( MonsterY - MapDrawPointY ) * MAP_SIZE, mons.img , TRUE ) ;//画像を描画
    //ステータス背景
        DrawBox(0,544,800,600,GetColor(0,125,120),TRUE );
    //HP表示
        DrawBox(89,555,91+WD          ,571,GetColor(0,0,0),FALSE);//メーターの枠を描画
        DrawBox(90,556,90+WD*hp/hp_max,570,GetColor(255,0,0),TRUE );//メーターの中身を描画
    //EP表示
        DrawBox(89,575,91+WD          ,591,GetColor(0,0,0),FALSE);//メーターの枠を描画
        DrawBox(90,576,90+WD*ep/ep_max,590,GetColor(0,200,120),TRUE );//メーターの中身を描画
        if(ep<ep_max) ep+=1;
    //EXP表示
        DrawBox(249,555,351+WD          ,591,GetColor(0,0,0),FALSE);//メーターの枠を描画
        DrawBox(250,556,250+(WD+100)*exp/exp_max,590,GetColor(0,255,0),TRUE );//メーターの中身を描画
    //文字表示
        DrawString(65,555,"HP",GetColor(0,0,0));
        DrawString(65,575,"EP",GetColor(0,0,0));
        DrawString(215,565,"EXP",GetColor(0,0,0));
        DrawFormatString(15,565, GetColor(0,0,0), "LV %d",lvl);
        DrawString(475,565,"Equip",GetColor(0,0,0));
 
        if(Key[ KEY_INPUT_A] == 1 && ItemBox == OFF){
            ItemBox = ON;
            Stats_1 = OFF;
        } else if(Key[ KEY_INPUT_A] == 2 && Stats_1 == ON){
            ItemBox = OFF;
        }
        if(ItemBox == ON){
            DrawBox(20,50,120,200,GetColor(0,125,120),TRUE );
            DrawString(30,60,"Item",GetColor(0,0,0));
            if(Key[ KEY_INPUT_A] == 0)Stats_1 = ON;
        }
 
        ScreenFlip();
    }
 
    DxLib_End();
    return 0;
}


よろしくお願いします。

Name: amuku
[URL]
Date: 2012年4月20日(金) 10:39
No: 2
(OFFLINE)

 Re: マップスクロール時、敵の行動について

追記ですが、マップ等のデータは他にまとめてあり、
この後も張ったコード内は整理する予定です。
色々試してMapDrawPointMonsX等加えてますがすべて失敗に終わっています。
(張ってあるコードの状況は、敵と自キャラのX座標が同じになり、動いてもX座標のみ同じでずっとついてくる状況、
Y座標は上記のとおり、動いた後に初期値に戻る状況。)

Name: softya(ソフト屋)
(副管理人)
[URL]
伝説なるハッカー(987,514 ポイント)
Date: 2012年4月21日(土) 18:41
No: 3
(OFFLINE)

 Re: マップスクロール時、敵の行動について

すいません見逃していました。

【少し修正】
実行できるコードではないのでざっと見ての感想ですが、座標の管理が変にややこしくなっています。
MapDrawPointXとMapDrawPointYは必要ですが、MapDrawPointMonsXなんてものは必要ないはずです。
基本的には、すべてのキャラクタ等はMap座標で処理・管理して表示するときだけ表示座標に変換して表示する方式にしたほうが物事がシンプルになりますので、自キャラもモンスターも表示座標はMapDrawPointXとMapDrawPointYを全て基準にするべきです。

↓ こんなイメージです。
画面イメージ.png
画面イメージ.png (25.28 KiB) 表示数: 367 回
by softya(ソフト屋)

Name: amuku
[URL]
Date: 2012年4月25日(水) 09:15
No: 4
(OFFLINE)

 Re: マップスクロール時、敵の行動について

返答遅れました、ありがとうございます。
座標については理解しました。
描画処理については未だ解決していませんが、がんばってみます。

Name: amuku
[URL]
Date: 2012年4月25日(水) 10:55
No: 5
(OFFLINE)

 Re: マップスクロール時、敵の行動について

[解決!]

自己解決しました、ありがとうございました。


Return to C言語何でも質問掲示板

オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[35人]