HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2010
0927
ミント敵の間隔を作るには?6解決


ミント

リンク

2010/9/27(Mon) 08:31:49|NO.35164

どうもお久しぶりです。そうでない方は初めまして。


あれからSTGを盛り込んでこれたので細かいところを修正しているのですが、
敵の出てくる間隔をうまく作れなくって困っています。


いつものように小さいプログラムを出します
------------------------------------------------------------------------

screen 0,380,450 ;サイズ ;画像を読み込む buffer 2 picload "素材7.bmp" gsel 0 TKMAX = 5 ;敵の最大数 repeat TKMAX ;5 teki.cnt = 0 ;フラグ tekix.cnt = 0 : tekiy.cnt = 0 ;座高 loop ;**********メインループ************************ *メイン color 0,0,0 : boxf gosub *敵の処理 ;****************描画*************************** ;敵 repeat TKMAX ;5 if teki.cnt = 1{ pos tekix.cnt,tekiy.cnt ;敵の座標 gmode 2,26,22,255 : gcopy 2,67,8 }loop ;*************************************** font "MS明朝",20,1 ;フォント,大きさ,太文字 pos 0,110 : color 255,0,0 mes "敵チェックカウンター " + TK_KAN ;*************画面更新************************** redraw 1 ;画面に反映される redraw 0 ;画面に反映されない await 15 goto *メイン ;****************敵の処理***************************** *敵の処理 repeat TKMAX ;5 // TK_KAN += 1 ;カウンター // if TK_KAN >= 200 : TK_KAN == 0 ;場所 // if TK_KAN <= 1 or TK_KAN <= 2{ if teki.cnt = 0{ teki.cnt = 1 ;フラグ tekix.cnt = 100.0 : tekiy.cnt = 0.0 } // } ;敵のスピード if teki.cnt = 1{ tekiy.cnt+=1.0 }loop return
----------------------------------------------------------------------
コメントアウトしているのが追加前です。
このままだと敵同士が同じところに重なってしまいます。

なので、間隔を作れば敵が重ならないと考えました。
それがコメントアウトしているところです。
ですが間隔の作り方を間違っていると思います・・・



>> if TK_KAN <= 1 or TK_KAN <= 2{
のところを「 or TK_KAN <= 3」と追加しても何故か3匹目が出てきません・・・

>> if TK_KAN >= 200 : TK_KAN == 0
のところの数字を変えると間隔を変えれます。



フラグで管理してみたり調べたりしましたが、どうも自分の納得いく結果になりませんでした。
乱数でバラバラに置くことが一応可能ですが、それだと敵の配置をコントロールできません。

やりたいことを画像で出すとこんなかんじです。
http://www.dotup.org/uploda/www.dotup.org1168935.bmp



どのようにすれば敵の出る間隔を作れますでしょうか?
それでは宜しくお願いします。



この記事に返信する


Ve

リンク

2010/9/27(Mon) 10:01:35|NO.35165

一般的なSTGならステージデータに、敵の配置データも組み込むけど、
そこまで単純に敵が出続けるなら…


screen 0,380,450 ;サイズ ;画像を読み込む buffer 2 ;picload "素材7.bmp" gsel 0 TKMAX = 5 ;敵の最大数 dim teki,TKMAX ;フラグ ddim tekix,TKMAX ;座標X ddim tekiy,TKMAX ;座標Y ;**********メインループ************************ *メイン redraw 0 ;画面に反映されない color 0,0,0 : boxf gosub *敵の処理 ;****************描画*************************** ;敵 gmode 2,26,22;,255 repeat TKMAX ;5 if teki.cnt = 1{ pos tekix.cnt,tekiy.cnt ;敵の座標 gcopy 2,67,8 } loop ;*************************************** font "MS明朝",20,1 ;フォント,大きさ,太文字 pos 0,110 : color 255,0,0 mes "敵チェックカウンター " + TK_KAN ;*************画面更新************************** redraw 1 ;画面に反映される await 15 goto *メイン ;****************敵の処理***************************** *敵の処理 repeat TKMAX ;5 if TK_KAN >= 200 { ;場所 ;if TK_KAN <= 1 or TK_KAN <= 2{ if teki.cnt = 0{ teki.cnt = 1 ;フラグ tekix.cnt = 100.0 : tekiy.cnt = 0.0 TK_KAN == 0 } }else{ TK_KAN += 1 ;カウンター } ;敵のスピード if teki.cnt = 1{ tekiy.cnt+=1.0 ;画面端に行くと消える if tekiy.cnt>ginfo_sizey : teki.cnt=0 } loop return

他に気になった変更点

後、整数型の配列に小数点を含む実数型の数値を代入してる配列は
ddim 命令を使った配列に変えました。

gmode 2はp4は要らないのでコメントアウトしました。
gmode 命令は1度命令を実行すると以後のgcopyに反映されるので描画ループ前に移動しました。

TK_KAN>=200を判定するif命令に else を加えました。
TK_KANが200以上になるとTK_KANのカウンタを止めます。

redraw 0を移動させました。



ミント

リンク

2010/9/27(Mon) 11:27:58|NO.35166

>>Veさん
おお!これがまさにやりたいことです!


>>一般的なSTGならステージデータに、敵の配置データも組み込むけど、
他のソースとかではそうみたいですねー。テキストで配置を決めてるみたい。
ちなみに自分にはまだ理解できない領域かもしれないっと思って触ってないです・・・(まだ9ヶ月)



>>後、整数型の配列に小数点を含む実数型の数値を代入してる配列は
うっかり癖で小数点を扱ってしまった・・・もうしわけない。


>>gmode 命令は1度命令を実行すると以後のgcopyに反映されるので描画ループ前に移動しました。
きずかなかったorz

gmode 2,26,22 : gcopy 2,67,8 → repeatに戻る
前回の「gcopy 2,67,8」が残ったまま「gmode 2,26,22 : gcopy 2,67,8」に突入するってことですね。



>>TK_KAN>=200を判定するif命令に else を加えました。
なるほど「else」ですか。
何故今まで「else」でやろうと思わなかったんだ・・・



お答えいただきありがとうございます!
無事解決しました!本当にありがとうございます。



26℃

リンク

2010/9/27(Mon) 11:50:54|NO.35167

repeat
title ""+time
time+
if time\100=0:mes "敵"
wait 1
loop

\の余りを使うといいよ。



ミント

リンク

2010/9/27(Mon) 12:34:30|NO.35168

>>26℃さん
なるほど。
余りのことも忘れてました・・・orz


色々試してみて自分に合った方法でやろうかと思います。
アドバイスありがとうございます。



SYAM

リンク

2010/9/27(Mon) 12:51:34|NO.35169

>理解できない領域かもしれない

多分そんなことないよ!
ここまでのサンプルが分かるくらい理解できていれば、あとはファイルからのテキスト読み出し命令と getstr 命令が分かればイケるよ!


#define DATAFILENAME "enemy.txt" #define MAX_ENEMY 16 // *** テスト用データ生成 *** buf="#100\n0,0,1,1\n#200\n300,0,-1,1\n#300\n0,0,1,1\n#400\n300,0,-1,1\n#500\n50,0,1,1\n250,0,-1,1\n#550\n50,0,1,1\n250,0,-1,1\n#600\n50,0,1,1\n250,0,-1,1\n#1500\n" notesel buf notesave DATAFILENAME // *** テスト用データ生成ここまで *** exist DATAFILENAME sdim enemydata,strsize // 敵データファイルの読込先. notesel enemydata noteload DATAFILENAME *INITIALIZE // 敵ひとつ分のデータ. sdim enemystr,256 // 敵データから一行読み出すときに使う. sdim valuestr,16 // 敵データから数値1つ読み出すときに使う. dim enemies,MAX_ENEMY,5 // 敵データの二次元配列. // 0 : 敵存在フラグ. 今いる敵は1 , いないなら0 // 1 : 敵の X 座標 // 2 : 敵の Y 座標 // 3 : 敵の X 方向の速度. // 4 : 敵の Y 方向の速度. dim new_enemy,5 // 敵データから敵ひとつ分読み出すときに使う. progress = 0 // 敵配置の進行を表す現在時刻. next_progress = -1 // 次の敵配置時刻. enemy_line = 0 // 現在の敵データの参照位置.(enemydataの現在参照行) // // メインループ. // *MAIN_ROUTINE repeat // 動き関連の処理をここから呼び出す. gosub *MOVE_ENEMIES gosub *ENEMY_PROGRESS // 終わってたら終わる. if(done) { dialog "終了" end } // 描画を全部ここでやる. redraw 0 color 0,0,0 boxf color 255,255,255 gosub *DRAW_ENEMIES redraw 1 title "progress = "+progress // 次の時刻に進める. progress++ wait 1 loop // // 今いる敵を画面に描く. 説明不要ですね. // *DRAW_ENEMIES repeat MAX_ENEMY : e = cnt if(enemies(e,0) != 0) { pos enemies(e,1),enemies(e,2) mes "敵" } loop return // // 今いる敵を動かす. // *MOVE_ENEMIES repeat MAX_ENEMY : e = cnt if(enemies(e,0) != 0) { // 次の位置 = 現在位置 + 速度 enemies(e,1) += enemies(e,3) enemies(e,2) += enemies(e,4) // 画面外に出たらいなくなる if( (enemies(e,1)<0) || (enemies(e,1)>ginfo_winx) ) { enemies(e,0)=0 } if( (enemies(e,2)<0) || (enemies(e,2)>ginfo_winy) ) { enemies(e,0)=0 } } loop return // // 敵配置の進行. // *ENEMY_PROGRESS if(next_progress <= progress) { // 次の敵出現時刻になった. repeat // もうデータがないや.終了! if(enemy_line>=notemax):done=1:break // 敵データから一行読み込む. noteget enemystr,enemy_line : enemy_line++ // 空行や ";"で始まる行は無視. if(enemystr=""):continue if(strmid(enemystr,0,1)=";"):continue if(strmid(enemystr,0,1)="#") { // "#"で始まる行は、次の処理時刻を示す. next_progress=int(strmid(enemystr,1,999)) break } else { // それら以外だったら、敵データをひとつ読み出す. idx=0 repeat 4 // ","区切りで4つのデータを読み出す. getstr valuestr,enemystr,idx,',' new_enemy(cnt)=int(valuestr) idx+=strsize loop gosub *MAKE_ENEMY // 敵ひとつ作る // まだ敵データがあるかもしれないので, // ここでは break しない. } await 1 loop } return // // 敵をひとつ追加. // *MAKE_ENEMY repeat MAX_ENEMY : e = cnt if(enemies(e,0)==0) { // 今画面に出ていない敵がいたらそれを使う. enemies(e,0)=1 // 読み出した敵データをコピー. repeat 4 enemies(e,(cnt+1)) = new_enemy(cnt) loop break; } loop return


敵データの形式はふつうのテキストファイルなので、メモ帳ででも開けます。

- 何もない行と";"で始まる行は無視(注釈とか書きやすいように...) - 行が"#"で始まってたら、その時刻になるまで待つ。 - それ以外は、","区切りの4つの数値を座標、速度として敵を1つ出現させる。
…のようになっています。
ここでいう「時刻」は、これまで他の方が挙げたサンプルのような、次の時刻までの差でなく全体を通しての時刻で表現されてるので注意してください。



ミント

リンク

2010/9/28(Tue) 11:35:11|NO.35177

>>SYAMさん
ひぇー見たことがない宣言ばかりだ・・・
自分がいかに同じもので済ませてたかバレバレですな・・・

これを理解するのは当分先になりそうです。
1つ1つヘルプを見ながら理解できるところから解体しようかと思います。



わざわざソースコードとアドバイスありがとうございます!



ONION software Copyright 1997-2023(c) All rights reserved.