|
|
|
2014/8/17(Sun) 17:05:05|NO.63891
音ゲーの譜面(楽譜)を複数表示したいのですが
#include "d3m.hsp" //タイマーだけ利用(timeGetTimeを使用してるだけだから精度は良くない)
dim key,6
KEY_CODE = 0,'Z','X','C','V','B'
KEY_POSX = 41
KEY_POSY = 423
BAR_SIZEX = 100
BAR_SIZEY = 20
PERFECT_LINE = 400
PERFECT_RANGE = 40 //PERFECT_LINEから上下にずれてもperfectになるサイズ
//背景バッファ初期化
buffer 1
color 0,0,0 :boxf:color 255,255,255
repeat 5
line BAR_SIZEX+cnt*BAR_SIZEX,0,BAR_SIZEX+cnt*BAR_SIZEX,640
loop
line 0,PERFECT_LINE,500,PERFECT_LINE
gsel 0
gakuhu = "12345" ;0は無表示,1〜5はz〜bボタンを押す
tenpo = 80 ;テンポの速さ
onebeat = 60000/tenpo //一拍の時間(ms)
perfect_tim = (1.0*PERFECT_LINE/480.0)*onebeat //バー発生からPERFECT_LINEまでの時間
movms = (480.0/onebeat) //1msの移動量(1画面の縦サイズを一拍の時間で割る)
dim bt1,strlen(gakuhu)
dim bt2,strlen(gakuhu)
dim bt3,strlen(gakuhu)
dim bt4,strlen(gakuhu)
dim bt5,strlen(gakuhu)
dim gakuhuend
repeat 6
sbuf = strmid(gakuhu,cnt,1)
if sbuf = "1"{
bt1(cnt)=1
}
if sbuf = "2"{
bt2(cnt)=1
}
if sbuf = "3"{
bt3(cnt)=1
}
if sbuf = "4"{
bt4(cnt)=1
}
if sbuf = "5"{
bt5(cnt)=1
}
if sbuf = "*"{
gakuhuend=cnt
}
loop
font "",30
start_tim = d3timer() //開始時間
repeat
redraw 0
gmode 0
pos 0,0
celput 1//背景画面コピー
if (onebeat*gcnt) <= (d3timer()-start_tim) {//一拍ずつの経過時間を越えた
use=0
gaku=int(strmid (gakuhu,gcnt,1))
bar_start_tim=onebeat*gcnt //バー発生時間
gcnt+1
}
etim=d3timer()-start_tim //開始からの経過時間
bar_tim=etim-bar_start_tim //バー発生からの経過時間(これにmovmsを掛けてバー座標にする)
repeat 6-1,1
getkey key(cnt),KEY_CODE(cnt)
color 255,255*key(cnt),255
pos KEY_POSX+BAR_SIZEX*(cnt-1),KEY_POSY
mes strf("%c",KEY_CODE(cnt))
loop
if gaku {
if use=0 {
color 255,255,0
boxf (gaku*BAR_SIZEX)-BAR_SIZEX,movms*bar_tim-BAR_SIZEY/2,gaku*BAR_SIZEX,movms*bar_tim+BAR_SIZEY/2 //バーの基準点を中央に変更
}
}
//ヒット表示
if hitf<6 and hitf>0{//perfect=白、good=黄色、miss=赤
if hitf<4 {
color 255,255,63+hitf*64
boxf hit_line_posx-BAR_SIZEX,hit_line_posy-BAR_SIZEY/2+hitf*3,hit_line_posx,hit_line_posy+BAR_SIZEY/2-hitf*3
}
color 255,255-128*(use_bak=3),255-128*(use_bak>1)
circle hit_line_posx-65-hitf*2,PERFECT_LINE-15-hitf*2,hit_line_posx-35+hitf*2,PERFECT_LINE+15+hitf*2,1
circle hit_line_posx-80-hitf*4,PERFECT_LINE-30-hitf*4,hit_line_posx-20+hitf*4,PERFECT_LINE+30+hitf*4,0
hitf++
}
if (key(gaku)=1)&(use=0)&(gaku!0) {
hitf=1 //ヒット表示フラグ
hit_line_posx=gaku*BAR_SIZEX
hit_line_posy=movms*bar_tim //ヒットした時の座標を保存
if abs(PERFECT_LINE-hit_line_posy) <= PERFECT_RANGE {//差がPERFECT_RANGE以下ならperfect
ms="perfect" :use=1
}else{//PERFECT_RANGE*2以下ならgoodでそれより大きければmiss
if abs(PERFECT_LINE-hit_line_posy) <= (PERFECT_RANGE*2) {ms="good" :use=2}else{ms="miss" :use=3 }
}
use_bak=use
}
pos 500,0
color 255,255,255
mes ms
redraw 1
await 16
loop
↑は譜面が1つずつしか表示できませんでした。どうすれば譜面を複数表示できるでしょうか?
| |
|
2014/8/17(Sun) 23:42:21|NO.63918
複数表示というのは、
「1拍目と2拍目を同時に流したい」
「ZレーンとXレーンで同時押しするバーを流したい」
のどちらでしょうか。
|
|
2014/8/18(Mon) 00:07:08|NO.63920
複数の物を同時に動かしたいなら、最低でも1フレーム(メインループ一回)中に
物の数の分だけの座標処理と表示処理が必要です。
スクリプトをざっと見る限り、黄色いバー(譜面?)の座標・表示処理は
1フレームに一回ずつしか行われていないようなので、その辺りから処理を見直して下さい。
処理の流れが分からないのであれば
今やろうとしている事に関係ない処理は一旦コメントアウトして
必要な処理の流れだけ追いかければ大分分かりやすくなります。
(今回の場合ならヒット表示の処理は必要ないのでコメントアウト可能)
それでも難しいのであれば必要な処理だけ組み込んだスクリプトを
一から作り直した方が無理に今のスクリプトを修正するより
結果的に完成が早くなる事も多いです。
|
|
2014/8/18(Mon) 11:24:23|NO.63928
>たんすさん
1拍目と2拍目を同時に流したいの方です。
|
|
2014/8/18(Mon) 19:20:06|NO.63945
思ったのだけれど
dim bt1,strlen(gakuhu)
dim bt2,strlen(gakuhu)
dim bt3,strlen(gakuhu)
dim bt4,strlen(gakuhu)
dim bt5,strlen(gakuhu)
dim gakuhuend
repeat 6
sbuf = strmid(gakuhu,cnt,1)
if sbuf = "1"{
bt1(cnt)=1
}
if sbuf = "2"{
bt2(cnt)=1
}
if sbuf = "3"{
bt3(cnt)=1
}
if sbuf = "4"{
bt4(cnt)=1
}
if sbuf = "5"{
bt5(cnt)=1
}
if sbuf = "*"{
gakuhuend=cnt
}
loop
ここの変数群があとの処理で全然使われていないのだけれど……
|
|
2014/8/19(Tue) 11:25:54|NO.63971
皆さん、ありがとうございます。
もうちょっと見直してみたいと思います。
|
|
2014/8/22(Fri) 01:11:23|NO.64133
複数表示に対応させていたら時間がかかりました。
モジュール型変数を用いて音符(バー)単位で管理しています。
#include "d3m.hsp" //タイマーだけ利用(timeGetTimeを使用してるだけだから精度は良くない)
//++++++++バー個別のデータ保持用
#module bar _Lane , _Ypos , flg_Hit
#modinit int _p1 , int _p2 , double _p3 , int _p4
//int _p1 :レーン番号(0〜4)
//int _p2 :拍番号、楽譜解読時のcnt値を使う
//doubke _p3 :Y移動量
//int _p4 :テンポ
_Lane = _p1
_Ypos = 480.0 - ( _p3 * _p2 * 60000.0 / _p4) //初期Y位置を計算
flg_hit = 0 //判定したかのフラグ
return
#modcfunc mod_get_lane //レーン取得用
return _Lane //レーン番号(0〜5)を返す。
#modcfunc mod_get_Ypos //Y位置取得用
return _Ypos //初期Y位置を返す。
#modcfunc mod_get_flg //判定したか否かの状態を取得
return flg_hit
#modfunc mod_set_flg int _p5
flg_hit = _p5
return
#global
//--------
dim key,6
//++++++++定数初期化
KEY_CODE = 'Z','X','C','V','B'
KEY_POSX = 41
KEY_POSY = 423
BAR_SIZEX = 100 //バーの幅
BAR_SIZEY = 20 //バーの高さ
PERFECT_LINE = 400 //判定線のY座標
PERFECT_RANGE = 40 //PERFECT_LINEから上下にずれてもperfectになるサイズ
ON_Draw = 5 //同時表示する拍数
tenpo = 120 ;テンポの速さ
onebeat = 60000 / tenpo //一拍の時間(ms)
perfect_tim = (1.0 * PERFECT_LINE / 480.0) * onebeat //バー発生からPERFECT_LINEまでの時間
movms = (480.0 / onebeat) / ON_Draw //1msの移動量(1画面の縦サイズを一拍の時間で割る)
//変数初期化
dim hit_f,5 //キー入力とバーの判定を行ったら値が1になり、ヒットエフェクトのカウントになる。
dim hit_y,5 //ヒットエフェクトのY位置
dim use_bak,5 //ヒットエフェクトの色を決める値。評価で切り替える。
//--------
//++++++++背景バッファ初期化
buffer 1
color 0,0,0 :boxf:color 255,255,255
repeat 5
line BAR_SIZEX + (cnt * BAR_SIZEX) , 0 , BAR_SIZEX + (cnt * BAR_SIZEX) , 640
loop
line 0 , PERFECT_LINE , 500 , PERFECT_LINE
//判定エリアを仮表示
color 0,0,128
line 0,PERFECT_LINE - PERFECT_RANGE , 500 , PERFECT_LINE - PERFECT_RANGE
line 0,PERFECT_LINE + PERFECT_RANGE , 500 , PERFECT_LINE + PERFECT_RANGE
color 0,128,0
line 0,PERFECT_LINE - PERFECT_RANGE- PERFECT_RANGE , 500 , PERFECT_LINE - PERFECT_RANGE- PERFECT_RANGE
line 0,PERFECT_LINE + PERFECT_RANGE+ PERFECT_RANGE , 500 , PERFECT_LINE + PERFECT_RANGE+ PERFECT_RANGE
//--------
//++++++++楽譜準備
gakuhu = "000000112233445506789*" ;0は無表示,1〜5はz〜bボタンを押す
dim gakuhuend
repeat strlen( gakuhu ) //楽譜変換
sbuf = strmid( gakuhu , cnt , 1 )
//newmod モジュール型変数配列名(mod_v),モジュール型変数タイプ(bar),レーン番号,拍数(cnt),移動量,テンポ
if sbuf = "1"{ newmod mod_v,bar,0,cnt,movms,tenpo} //単音のみ
if sbuf = "2"{ newmod mod_v,bar,1,cnt,movms,tenpo}
if sbuf = "3"{ newmod mod_v,bar,2,cnt,movms,tenpo}
if sbuf = "4"{ newmod mod_v,bar,3,cnt,movms,tenpo}
if sbuf = "5"{ newmod mod_v,bar,4,cnt,movms,tenpo}
if sbuf = "6"{ newmod mod_v,bar,0,cnt,movms,tenpo : newmod mod_v,bar,1,cnt,movms,tenpo} //同時押し対応
if sbuf = "7"{ newmod mod_v,bar,1,cnt,movms,tenpo : newmod mod_v,bar,2,cnt,movms,tenpo}
if sbuf = "8"{ newmod mod_v,bar,2,cnt,movms,tenpo : newmod mod_v,bar,3,cnt,movms,tenpo}
if sbuf = "9"{ newmod mod_v,bar,3,cnt,movms,tenpo : newmod mod_v,bar,4,cnt,movms,tenpo}
if sbuf = "*"{ gakuhuend=cnt}
loop
//--------
gsel 0
gmode 0
font "",30
start_tim = d3timer() //開始時間
repeat
redraw 0 //描写停止
gosub *clr_screen //画面初期化
gosub *get_beat //拍数のカウント
etim = d3timer() - start_tim //開始からの経過時間
await 0
repeat 5 //キー入力を判定する。
getkey key(cnt),KEY_CODE(cnt)
if key(cnt){
color 64,80,80
boxf cnt * bar_sizeX + 1 , 0 , ( cnt + 1 ) * bar_sizex - 1 , ginfo_sy
color 255,255,255
line cnt * bar_sizeX , perfect_line , ( cnt + 1 ) * bar_sizex , perfect_line
}
color 255 , 255 * key(cnt) , 255
pos KEY_POSX + BAR_SIZEX * ( cnt ) , KEY_POSY
mes strf ( "%c" , KEY_CODE( cnt ) )
loop
foreach mod_v //バー情報のモジュール変数配列分だけ繰り替えす
mod_x = mod_get_Lane( mod_v(cnt) ) //レーン番号をmod_xに代入
mod_y = mod_get_Ypos( mod_v(cnt) ) //初期Y位置をmod_yに代入
mod_y = mod_y + ( movms * etim ) //現在のY位置を算出
color 255,255,255
boxf mod_x * bar_sizex ,mod_y ,( mod_x + 1 ) * bar_sizex ,mod_y + bar_sizey //バーを描写
mod_f = mod_get_flg( mod_v(cnt) ) //判定状態を取得
switch mod_f //判定状態による分岐
//______________
case 0 //未判定
if ( mod_y > ( -3 * PERFECT_RANGE + PERFECT_LINE )) {//バーが判定線に近ければ 判定を開始
if key( mod_x ){ //キー入力がされている
hit_f(mod_x) = 1 //hitエフェクト用数値 設定
use = 3 //評価メッセージの 表示寿命
key( mod_x ) = 0 //キー入力状態を初期化
if abs(PERFECT_LINE -( bar_sizey / 2 + mod_y)) <= PERFECT_RANGE {//差がPERFECT_RANGE以下ならperfect
ms="perfect" //評価メッセージ設定
use_abk(cnt)=1 //ヒットエフェクトの色計算用 設定
mod_set_flg mod_v(cnt),1 //バー情報に判定結果を記録。
}else{//PERFECT_RANGE*2以下ならgoodでそれより大きければmiss
if abs(PERFECT_LINE -( bar_sizey / 2 + mod_y)) <= ( PERFECT_RANGE * 2 ) {
ms="good"
use_bak(cnt)=2
mod_set_flg mod_v(cnt),2
}else{
ms="miss"
use_bak(cnt)=3
mod_set_flg mod_v(cnt),3
}
}
}
}
swbreak
//_____________
case 1 //パーフェクト 判定後のバーの色
if mod_y < perfect_line{ //判定済み&ライン手前で再びキー入力があったら
key(mod_x)=0 //打ち消しておく
}
color 120,120,255
swbreak
//_____________
case 2 //グッド 判定後のバーの色
if mod_y < perfect_line{ //判定済み&ライン手前で再びキー入力があったら
key(mod_x)=0 //打ち消しておく
}
color 200,255,200
swbreak
//_____________
case 3 //バッド 判定後のバーの色
if mod_y < perfect_line{ //判定済み&ライン手前で再びキー入力があったら
key(mod_x)=0 //打ち消しておく
}
color 255,64,64
swbreak
//_____________
swend
boxf mod_x * bar_sizex + 1 ,mod_y + 1 ,( mod_x + 1 ) * bar_sizex - 1 ,mod_y + bar_sizey - 1 //判定後色でバーの内側を塗りつぶし
if mod_y > double( ginfo_sy ){
if mod_f = 0{ //無判定で流れた。
ms = "Bad!"
use = 3
}
delmod mod_v(cnt) //下に流れたバー情報は削除
}
await 0
loop
;//ヒット表示
repeat 5
if hit_f(cnt)<6 and hit_f(cnt)>0{
if hit_f(cnt)<4{ //押してから4カウント
color 255,255,63+hit_f(cnt)*64
boxf (cnt+1)*bar_sizex,hit_y(cnt)-bar_sizey/2+hit_f(cnt)*3,(cnt+2)*bar_sizex,hit_y(cnt)-bar_sizey/2-hit_f(cnt)*3
}
color 255 , 255 - 128 * ( use_bak = 3 ) , 255 - 128 * ( use_bak > 1 )
circle (cnt+1)*bar_sizex - 65 - hit_f(cnt) * 2 , PERFECT_LINE - 15 - hit_f(cnt) * 2 , (cnt+1)*bar_sizex - 35 + hit_f(cnt) * 2 , PERFECT_LINE + 15 + hit_f(cnt) * 2 , 1
circle (cnt+1)*bar_sizex - 80 - hit_f(cnt) * 4 , PERFECT_LINE - 30 - hit_f(cnt) * 4 , (cnt+1)*bar_sizex - 20 + hit_f(cnt) * 4 , PERFECT_LINE + 30 + hit_f(cnt) * 4 , 0
hit_f(cnt)++
}
loop
//++++++++(判定表示)
pos 500,0
color 255,255,255
mes ms
//--------
redraw 1
await 16
loop
stop
end
//++++++++画面初期化
*clr_screen
pos 0,0 :celput 1//背景画面コピー
return
//--------
//++++++++拍数のカウント
*get_beat
if (onebeat*gcnt) <= (d3timer()-start_tim) {//一拍ずつの経過時間を越えた
if (use < 0){ //評価が更新されてからのカウントダウンが切れたら
ms = ""
}else{
use--
}
}
return
//--------
今後の課題
・楽譜の終端まで行っても終わらない。→終端処理を実装する。
・楽譜を一気に読み込んでいるのでメモリを食いすぎる。→拍カウントを利用して、直近のみを準備させる。
・得点の処理?
・もろもろ調整。
参考になれば幸いです。
| |
|
2014/8/22(Fri) 14:50:06|NO.64143
>たんすさん
凄いですね・・・・
わざわざここまでありがとうございます><
とても参考になりました。
あと少しで完成を迎えられそうです。ありがとうございました^^
|
|
2014/8/22(Fri) 15:17:51|NO.64144
ごめんなさい、最後に・・・
ゲームオーバ判定を追加するにはどうしたらいいですか??
repeat strlen( gakuhu ) //楽譜変換
sbuf = strmid( gakuhu , cnt , 1 )
//newmod モジュール型変数配列名(mod_v),モジュール型変数タイプ(bar),レーン番号,拍数(cnt),移動量,テンポ
if sbuf = "1"{ newmod mod_v,bar,0,cnt,movms,tenpo} //単音のみ
if sbuf = "2"{ newmod mod_v,bar,1,cnt,movms,tenpo}
if sbuf = "3"{ newmod mod_v,bar,2,cnt,movms,tenpo}
if sbuf = "4"{ newmod mod_v,bar,3,cnt,movms,tenpo}
if sbuf = "5"{ newmod mod_v,bar,4,cnt,movms,tenpo}
if sbuf = "6"{ newmod mod_v,bar,0,cnt,movms,tenpo : newmod mod_v,bar,1,cnt,movms,tenpo} //同時押し対応
if sbuf = "7"{ newmod mod_v,bar,1,cnt,movms,tenpo : newmod mod_v,bar,2,cnt,movms,tenpo}
if sbuf = "8"{ newmod mod_v,bar,2,cnt,movms,tenpo : newmod mod_v,bar,3,cnt,movms,tenpo}
if sbuf = "9"{ newmod mod_v,bar,3,cnt,movms,tenpo : newmod mod_v,bar,4,cnt,movms,tenpo}
if sbuf = "*"{ gakuhuend=cnt}
loop
の sbuf = strmid( gakuhu , cnt , 1 ) を
sbuf = peek(gakuhu,gcnt)-'0'
if sbuf < 0 {break}
に置き換えればいいのでしょうか?
|
|
2014/8/22(Fri) 18:02:45|NO.64149
楽譜の終了は、
拍数をカウントして終了拍を少し過ぎたころに終了処理を入れることで実装できます。
//++++++++拍数のカウント
*get_beat
if ( onebeat * gcnt ) <= ( d3timer() - start_tim ) {//一拍ずつの経過時間を越えた
if (use < 0){ //評価が更新されてからのカウントダウンが切れたら
ms = ""
}else{
use -= 1
}
if (gakuhuend + 2) < gcnt{ //終了点を少し越えて、終了処理
dialog "終了!"
end
}
gcnt += 1 //現在の拍数をカウントアップ
}
return
//--------
|
|
2014/8/23(Sat) 02:16:07|NO.64167
ありがとうございます。助かります。
|
|