|
 |
|
2016/7/11(Mon) 19:31:26|NO.76151
こんばんは。
ビート●ニアIIDX風のゲームを夏の自由課題プロジェクトとして
製作しているのですが、2つの問題に頭を抱えています。
その問題が何かというと
1、譜面のタイミングが合わない (これが最重要)
2、譜面再生中、キーボードのキーを押すとFPSが変動する
あと、「キーを押した直後のみ判定を行う」の実装がわからない
【スクリプト】
#include "d3m.hsp"
title "Beatrush 譜面テスター"
screen 0,800,600
max=2000
bpm=0
dim timing,max
dim key,max
dim ny,max
dim tuuka,max
dim dr,max
dim tk,8
dim cir,8
dim xmore,8
dim ymore,8
dim feed,8
dim tim,8
sdim filename
sdim musicname
sdim log
sdim notes
sdim keys
sdim bpms
repeat max-1
timing(cnt)=double(timing(cnt))
ny(cnt)=double(ny(cnt))
loop
time = double(time)
movms = double(movms)
onebeat = double(onebeat)
*filenameinput
mes "譜面ファイル"
mesbox filename,300,60,5
mes ""
mes "音楽ファイル"
mesbox musicname,300,60,5
mes ""
button goto "",*check
stop
*check
cls
mes "Checking Notes Timing Data..."
exist filename : if strsize =-1 {
mes "譜面ファイルが存在しません"
wait 100
cls 1
goto *filenameinput
}else{
notesel log
noteload filename
exist musicname : if strsize =-1 {
mes "音楽ファイルが存在しません"
wait 100
cls 1
goto *filenameinput
}else{
mmload musicname,0,1
mes "タイミング情報を読み込んでいます"
repeat
noteget notes,count
if notes="" {
mes "done."
break
}else{
timing(cnt) = double(notes)
count + 1
noteget keys,count
if keys = "" {
mes "Error in Keycode Read Line(" + count + ")"
stop
}else{
if keys="A" : key(cnt)=1
if keys="I" : key(cnt)=2
if keys="S" : key(cnt)=3
if keys="O" : key(cnt)=4
if keys="D" : key(cnt)=5
if keys="P" : key(cnt)=6
if keys="F" : key(cnt)=7
if keys="B" : key(cnt)=8
count + 1
}
}
loop
noteget bpms,count+1
if bpms = "" {
mes "Error in BPM read line"
stop
}else{
bpm = int(bpms)
}
}
}
onebeat = 60000/bpm //一拍の時間
movms = 500.0/onebeat //Y座標が0から500までの1pxあたりの移動量
dim ny,max
mmplay 0
repeat
redraw 0
color 0,0,0 : boxf
color 255,255,255
line 30,0,30,600
line 50,0,50,600
line 70,0,70,600
line 90,0,90,600
line 110,0,110,600
line 130,0,130,600
line 150,0,150,600
line 170,0,170,600
line 0,500,170,500
pos 200,0
mes "First Notes : " + timing(0)
mes "Time :" + time
mes "FPS :" + d3getfps()
mes "BPM :" + bpm
mes "movms:" + movms
mes "one.b:" + onebeat
mes "All.n:" + count/2
mes "ライン通過:" + tuuka
gosub *draw
gosub *move
time + movms
redraw 1
await 16
loop
*draw
repeat count/2
if timing(cnt)<=time :if dr(cnt)=1{
if key(cnt) = 1 : color 255,255,255 : boxf 31,ny(cnt),50,ny(cnt)+5
if key(cnt) = 2 : color 0,0,255 : boxf 51,ny(cnt),70,ny(cnt)+5
if key(cnt) = 3 : color 255,255,255 : boxf 71,ny(cnt),90,ny(cnt)+5
if key(cnt) = 4 : color 0,0,255 : boxf 91,ny(cnt),110,ny(cnt)+5
if key(cnt) = 5 : color 255,255,255 : boxf 111,ny(cnt),130,ny(cnt)+5
if key(cnt) = 6 : color 0,0,255 : boxf 131,ny(cnt),150,ny(cnt)+5
if key(cnt) = 7 : color 255,255,255 : boxf 151,ny(cnt),170,ny(cnt)+5
if key(cnt) = 8 : color 255,0,0 : boxf 0,ny(cnt),30,ny(cnt)+5
}
loop
return
*move
repeat count/2
if dr(cnt)=0 : if timing(cnt)<=time : dr(cnt)=1
if dr(cnt)=1 : ny(cnt)+movms
if dr(cnt)=1 : if ny(cnt)>=500 : dr(cnt)=2 : tuuka+1 {
if key(cnt)=1 : tk(0)=1 //ここから
if key(cnt)=2 : tk(1)=1
if key(cnt)=3 : tk(2)=1
if key(cnt)=4 : tk(3)=1
if key(cnt)=5 : tk(4)=1
if key(cnt)=6 : tk(5)=1
if key(cnt)=7 : tk(6)=1
if key(cnt)=8 : tk(7)=1 //ここまでのスプリクトは関係ありません
}
loop
return
※譜面再生用スクリプトなのでタイミング判定はありません。
(自分がタイミング判定のスクリプトを上手く組めないという理由もある)
【譜面データ】
1000.000000 タイミング(これを基本としてタイミングを合わせます)
A キー (どこのノーツなのかを表します)
2行がまとまり、1つのノーツタイミングデータとなります
【問題②について】※keycode変数はあらかじめ、文字コードを代入しています。
repeat
redraw 0
color 0,0,0 : boxf
color 255,255,255
(中略)
repeat 9,1
getkey a,keycode(cnt) : if a {
(判定処理)
}
loop
redraw 1
await 16
loop
…一体なにがいけないんでしょうか?
だれか、助けてください!!

| |
|
2016/7/11(Mon) 20:32:15|NO.76152
直ぐにわかる範囲だと
boxfで全画面塗りつぶさなくてもいいのでは?
gcopyで別の画面に描写したものを写す(boxfも必要なくなる)が基本
|
|
2016/7/11(Mon) 20:48:09|NO.76153
過去に 似たような質問があったよ
ttp://hsp.tv/play/pforum.php?mode=pastwch&num=21566
|
|
2016/7/11(Mon) 21:43:06|NO.76155
似たような質問がありましたか…
申し訳ありません。調べ不足です…。
あと、説明が雑ですいません。
ご迷惑をおかけしました…。
|
|
2016/7/11(Mon) 21:46:07|NO.76156
色々とおかしい・・・
>movms = 500.0/onebeat //Y座標が0から500までの1pxあたりの移動量
これは500ドットを1ビートの時間内に進む時の1msの移動量になってるので
使用時にはミリ秒の経過時間を掛ける必要がある
> if dr(cnt)=1 : ny(cnt)+movms
これを
if dr(cnt)=1 : ny(cnt)=movms*ノートの経過ミリ秒
の様にする
後
>time + movms
を
time=スタートからの経過ミリ秒
にする
それから
> if dr(cnt)=0 : if timing(cnt)<=time : dr(cnt)=1
これだと出現タイミングになってしまうので
判定位置のタイミングにはならない
手っ取り早い解決策としては
上のmovms、timeの修正をしてる仮定で
>movms = 500.0/onebeat //Y座標が0から500までの1pxあたりの移動量
の下あたりに
repeat count/2
timing(cnt)-=500.0/movms
loop
を追加すると
500ドット分タイミングがずれるので
判定位置で経過時間と元の指定タイミングが同じになる
|
|
2016/7/12(Tue) 22:15:46|NO.76165
…すいません。ご返信が遅れました。
ご指摘ありがとうございます。
・・・まだ、試行錯誤中です。
|
|
2016/7/13(Wed) 20:00:55|NO.76180
暇人さん
#include "d3m.hsp"
title "Beatrush 譜面テスター"
screen 0,800,600
max=2000
bpm=0
dim timing,max //タイミング情報用
dim key,max //出現位置
dim ny,max //ノートのYポジション
dim tuuka,max //通過フラグ
dim dr,max //描画フラグ
dim tk,8
dim cir,8
dim xmore,8
dim ymore,8
dim feed,8
dim tim,8
dim keika,max //ノートごとの通過フラグ
dim keikastart,max //ノートごとの出現時の時間代入用
dim lk,max
sdim filename
sdim musicname
sdim log
sdim notes
sdim keys
sdim bpms
repeat max-1
timing(cnt)=double(timing(cnt))
ny(cnt)=double(ny(cnt))
loop
time = double(time)
movms = double(movms)
onebeat = double(onebeat)
filename = "max300.brn"
musicname = "max 300.mp3"
*filenameinput
mes "譜面ファイル"
mesbox filename,300,60,5
mes ""
mes "音楽ファイル"
mesbox musicname,300,60,5
mes ""
button goto "",*check
stop
//ここから
*check
cls
mes "Checking Notes Timing Data..."
exist filename : if strsize =-1 {
mes "譜面ファイルが存在しません"
wait 100
cls 1
goto *filenameinput
}else{
notesel log
noteload filename
exist musicname : if strsize =-1 {
mes "音楽ファイルが存在しません"
wait 100
cls 1
goto *filenameinput
}else{
mmload musicname,0,1
mes "タイミング情報を読み込んでいます"
repeat
noteget notes,count
if notes="" {
mes "done."
break
}else{
timing(cnt) = double(notes)// - 8.174
count + 1
noteget keys,count
if keys = "" {
mes "Error in Keycode Read Line(" + count + ")"
stop
}else{
if keys="A" : key(cnt)=1
if keys="I" : key(cnt)=2
if keys="S" : key(cnt)=3
if keys="O" : key(cnt)=4
if keys="D" : key(cnt)=5
if keys="P" : key(cnt)=6
if keys="F" : key(cnt)=7
if keys="B" : key(cnt)=8
count + 1
}
}
loop
noteget bpms,count+1
if bpms = "" {
mes "Error in BPM read line"
stop
}else{
bpm = int(bpms)
}
}
}
//ここまでタイミング・ノート位置のデータ読み込み部分
onebeat = 60000/bpm //1拍の時間を求める
movms = 500.0/onebeat //1msあたりの移動量を求める
repeat count/2
timing(cnt) - 500.0/movms //500ドット分ずらす
loop
mmplay 0
start_tim = d3timer() //再生開始時間をstart_timに代入
repeat
redraw 0
color 0,0,0 : boxf
color 255,255,255
line 30,0,30,600
line 50,0,50,600
line 70,0,70,600
line 90,0,90,600
line 110,0,110,600
line 130,0,130,600
line 150,0,150,600
line 170,0,170,600
line 0,500,170,500
pos 200,0
mes "First Notes : " + timing(0) //こ↑こ↓から
mes "Time :" + time
mes "FPS :" + d3getfps()
mes "BPM :" + bpm
mes "movms:" + movms
mes "one.b:" + onebeat
mes "All.n:" + count/2
mes "ライン通過:" + tuuka
mes "経過時間" + keika(0) //こ↑こ↓までデバッグ用のモニターみたいなやつ
gosub *draw
gosub *move
gosub *tims
time = d3timer() - start_tim
redraw 1
await 16
loop
*draw
repeat count/2
if timing(cnt)<=time :if dr(cnt)=1{
if key(cnt) = 1 : color 255,255,255 : boxf 31,ny(cnt),50,ny(cnt)+5 :if lk(cnt)=0 : keikastart(cnt)=d3timer() : lk(cnt)=1 //フラグが0でノート出現のタイミングが来たら
if key(cnt) = 2 : color 0,0,255 : boxf 51,ny(cnt),70,ny(cnt)+5:if lk(cnt)=0 : keikastart(cnt)=d3timer() : lk(cnt)=1 //ノートの出現時に現在の時間を記録し、フラグを1にする
if key(cnt) = 3 : color 255,255,255 : boxf 71,ny(cnt),90,ny(cnt)+5:if lk(cnt)=0 : keikastart(cnt)=d3timer() : lk(cnt)=1
if key(cnt) = 4 : color 0,0,255 : boxf 91,ny(cnt),110,ny(cnt)+5:if lk(cnt)=0 : keikastart(cnt)=d3timer() : lk(cnt)=1
if key(cnt) = 5 : color 255,255,255 : boxf 111,ny(cnt),130,ny(cnt)+5:if lk(cnt)=0 : keikastart(cnt)=d3timer() : lk(cnt)=1
if key(cnt) = 6 : color 0,0,255 : boxf 131,ny(cnt),150,ny(cnt)+5:if lk(cnt)=0 : keikastart(cnt)=d3timer() : lk(cnt)=1
if key(cnt) = 7 : color 255,255,255 : boxf 151,ny(cnt),170,ny(cnt)+5:if lk(cnt)=0 : keikastart(cnt)=d3timer() : lk(cnt)=1
if key(cnt) = 8 : color 255,0,0 : boxf 0,ny(cnt),30,ny(cnt)+5:if lk(cnt)=0 : keikastart(cnt)=d3timer() : lk(cnt)=1
}
loop
return
*move
repeat count/2
if dr(cnt)=0 : if timing(cnt)<=time : dr(cnt)=1
if dr(cnt)=1 :ny(cnt)=movms*keika(cnt) //移動量*ノート経過時間
if dr(cnt)=1 : if ny(cnt)>=500 : dr(cnt)=2 : tuuka+1 {
}
loop
return
*tims
repeat count/2
if dr(cnt)= 1 : keika(cnt) = abs( keikastart(cnt) - d3timer()) //ノート経過時間を計算
loop
return
このスクリプトで実行すると
データで指定した時間にきちんとタイミングを合わせてくれたものの
一瞬しかノートが見えなくなってしまいました。
原因を探しましたがわからずのままです…
申し訳ありませんが、お教えいただけませんか?

| |
|
2016/7/13(Wed) 21:30:08|NO.76183
ざっと見ただけだけど
keikastartは描画時じゃ無く出現時に入れないと
>if dr(cnt)= 1 : keika(cnt) = abs( keikastart(cnt) - d3timer()) //ノート経過時間を計算
がgosub *drawからgosub *timsまでの時間しかkeika(cnt)に入らない
て、言うか発生タイミングはtimingに入ってるんだから座標決定時に
再生開始からの経過時間を引けば良い
こんな感じ
#include "d3m.hsp"
title "Beatrush 譜面テスター"
screen 0,800,600
dim tk,8
dim cir,8
dim xmore,8
dim ymore,8
dim feed,8
dim tim,8
sdim filename
sdim musicname
sdim log
sdim notes
sdim keys
sdim bpms
//各キーのノート表示x座標(0は無しで1~8を使用するので要素数9)
notx=0, 31,51, 71,91, 111,131, 151, 0
//各キーのノート幅
notsx=0, 20,20, 20,20, 20, 20, 20, 30
//各キーのノート色
notr=0, 255,0, 255,0, 255,0, 255, 255
notg=0, 255,0, 255,0, 255,0, 255, 0
notb=0, 255,255, 255,255, 255,255, 255, 0
//テスト用にデータ設定
musicname=dir_exe+"\\hsptv\\bgm1.mid"
//bgm1.mid用のノートデータを作る
ob = 60000.0/144.0 //bgm1.midの一拍の時間
tempstr=""
repeat 200 //基本的なドラムをセット
if (cnt\2)=0 {
if (cnt\4)=2 {tempstr+=""+(ob*cnt-ob/2.0)+"\nB\n"}
tempstr+=""+(ob*cnt)+"\nB\n"
}else{
tempstr+=""+(ob*cnt)+"\nA\n"
}
loop
tempstr+="\n144.0"
memfile tempstr //作ったデータをnoteloadで読み込めるようにメモリストリームに設定
filename="MEM:file.mid" //メモリストリームを読み込むためのファイル名を代入
//ここまで
*filenameinput
mes "譜面ファイル"
mesbox filename,300,60,5
mes ""
mes "音楽ファイル"
mesbox musicname,300,60,5
mes ""
button goto "",*check
stop
*check
cls
mes "Checking Notes Timing Data..."
exist filename : if strsize =-1 {
mes "譜面ファイルが存在しません"
wait 100
cls 1
goto *filenameinput
}else{
notesel log
noteload filename
ddim timing,notemax/2
dim key,notemax/2
ddim ny,notemax/2
dim dr,notemax/2
exist musicname : if strsize =-1 {
mes "音楽ファイルが存在しません"
wait 100
cls 1
goto *filenameinput
}else{
//mmload musicname,0,1
//midiの場合デフォルトのデバイスだと時間関係の精度が使い物にならないのでmpegvideoを使用(mp3,wav等も使用できる)
//これはmmplayで再生する場合にも言えるのでmidiの場合mmplayは使わない方が良い(精度が必要な場合)
mci "open \""+musicname+"\" type mpegvideo alias bgm" //以降 bgm がこのファイルを示す文字列になる
if stat = -1 {mci "open \""+musicname+"\" type mpegvideo2 alias bgm"} //mpegvideoが使えなかったらmpegvideo2を使用
mci "setaudio bgm volume to 100" //midiの場合ボリュームが最大になってる事があるので調整
onexit *exit
mes "タイミング情報を読み込んでいます"
repeat
noteget notes,count
if notes="" {
mes "done."
break
}else{
timing(cnt) = double(notes)
count + 1
noteget keys,count
if keys = "" {
mes "Error in Keycode Read Line(" + count + ")"
stop
}else{
if keys="A" : key(cnt)=1
if keys="I" : key(cnt)=2
if keys="S" : key(cnt)=3
if keys="O" : key(cnt)=4
if keys="D" : key(cnt)=5
if keys="P" : key(cnt)=6
if keys="F" : key(cnt)=7
if keys="B" : key(cnt)=8
count + 1
}
}
loop
noteget bpms,count+1
mes bpms
if bpms = "" {
mes "Error in BPM read line"
stop
}else{
bpm = double(bpms)//整数とは限らないので
}
}
}
max=count/2 //ノート総数
onebeat = 60000.0/bpm //一拍(四分音符)の時間(bpmが実数だったり誤差を少なくしたいので実数で計算)
ViewerTime=onebeat*4 //ノートが画面から消えるまでの時間(onebeat*4で1小節分)
movms =500.0/ViewerTime //Y座標が0から500までの1msあたりの移動量
//判定位置までの必要時間を算出
StartAdjust=500.0/movms-onebeat/4 //midiだからかonebeat/4(16部音符分)遅らせるとタイミングが合う
//mmplay 0
mci "play bgm"
start_tim=d3timer()-StartAdjust //再生開始時間代入(タイミングを判定位置到着タイミングにするために上で出した時間を引く)
repeat
redraw 0
color 0,0,0 : boxf
color 255,255,255
line 30,0,30,600
line 50,0,50,600
line 70,0,70,600
line 90,0,90,600
line 110,0,110,600
line 130,0,130,600
line 150,0,150,600
line 170,0,170,600
line 0,500,170,500
pos 200,0
mes "First Notes : " + timing(0)
mes "Time :" + time
mes "FPS :" + d3getfps()
mes "BPM :" + bpm
mes "movms:" + movms
mes "one.b:" + onebeat
mes "All.n:" + count/2
mes "ライン通過:" + tuuka
time=double(d3timer())-start_tim //経過時間
stick k
if k&128 {goto *exit} //Escキーで終了
gosub *move
//確認用に最後に押されたボタンのタイミングで判定内に有ったノートを表示
color 255,255,0
gradf notx(hit_key),hit_ny,notsx(hit_key),5
gosub *draw
redraw 1
await 16
loop
*move
repeat max
if dr(cnt)=0 : if timing(cnt)<=time : dr(cnt)=1
if dr(cnt)=1 {
ny(cnt)=movms*(time-timing(cnt)) //経過時間から出現タイミングを引いてノートの経過時間を出して移動量を掛けてY座標にする
if ny(cnt)>=480 {
if ny(cnt)<=520 {//480~520の間なら判定する
if k {//キーが押された
hit_ny=ny(cnt)
hit_key=key(cnt)
dr(cnt)=2
tuuka+1
}
}else{//判定範囲を超えたので消す
dr(cnt)=2
tuuka+1
}
}
}
loop
return
*draw
repeat max
if timing(cnt)<=time :if dr(cnt)=1{
kid=key(cnt)
color notr(kid),notg(kid),notb(kid)
gradf notx(kid),ny(cnt),notsx(kid),5
}
loop
return
*exit
mci "close all" //念のため終了時にmciを閉じる
end
スペース等で簡易的にタイミング検証できるようにした
await 16なので最大 movms*16 ドット押したタイミングよりずれる
今回の場合movmsが0.3なので最大5ドットぐらいずれる

| |
|
2016/7/13(Wed) 22:05:52|NO.76185
暇人さん
ありがとうございます!!
タイミングもバッチシ合いました!
ノートが一瞬だけ表示されるという事もなくなり
無事にビート●ニア風のゲームが開発できそうです!
あと、わざわざスクリプトを書いてくださり
お手数をおかけしました。
本当にありがとうございます。
|
|