HTML+CSS+JavascriptでSDVX譜面画像を生成&表示

概要

タイトルの通り、譜面画像を手軽に作れるようにしました。

作成例

[譜面画像]
いつもの
[譜面画像]
あの雲を追いかけたいつまみ
[譜面画像]
こういうものも可能

仕組み

canvas要素にchartImageクラスとdata-chart属性を与えておくと、JavascriptがchartImageクラスを探し出し、data-chart属性を読んで譜面画像を生成してくれるという構造です。

本体はただのcanvas要素なので、こんな風に 適当な配置の説明 [譜面画像] に譜面画像を対応させるようなこともできます。

data-chart属性はこうなっています。

CHIP,
BC,2/16,
AD,4/16,
C,6/16,
B,7/16,
A,8/16,
B,10/16,
C,11/16,
D,12/16,
C,14/16,
B,15/16,
A,16/16,
B,18/16,
C,19/16,
D,20/16,
BC,22/16,
D,24/16,
C,25/16,
B,26/16,
A,27/16,
RSE,28/16,
;
LONG,
L,3/8,4/8,
R,5/8,6/8,
L,7/8,8/8,
R,9/8,10/8,
L,12/8,14/8,
;
VOL,
L,0/1,-0.5,
VERTICAL,0/1,-0.25,
STRAIGHT,2/1,-0.25,
VERTICAL,2/1,0,
;
VOL,
R,0/1,-0.5,
VERTICAL,0/1,-0.25,
STRAIGHT,2/1,-0.25,
VERTICAL,2/1,0,
;
[譜面画像]
実際に表示されるもの

基本的には「;」がノーツ1つ1つ、「,」がノーツ1つを表現するためのデータ1つ1つを区切っています。

[ノーツ1のデータ],……[ノーツ1のデータ];
[ノーツ2のデータ],……[ノーツ2のデータ];
……

区切りに伴う改行やスペースは無視されるので、好きなように見やすく改行できます。区切り文字の隣に区切り文字を無駄に打ってもある程度大丈夫です。

[ノーツ1のデータ],……[ノーツ1のデータ],
;
[ノーツ2のデータ],……[ノーツ2のデータ],
;
……

BTとFXは

  • 「ノーツ名(同時押しをまとめて表記可能)」
  • 「タイミング(1小節の何倍かを表す分数で表現)」

の2つのデータで表現されます。

ノーツ名はA,B,C,D,L,R,LSE,RSEの8種類です。「ABRSE」のように書けます。

CHIP,[ノーツ名],[タイミング];

ロングは

  • 「終点タイミング」

を3つ目に指定します。

LONG,[ノーツ名],[始点タイミング],[終点タイミング];

「;」区切りが1ノーツではありますが、チップ同士、ロング同士であれば、1つの「;」区切りの中に複数書いても機能します。ノーツ同士は順不同です。

CHIP,[ノーツ名],[タイミング],[ノーツ名],[タイミング],……[ノーツ名],[タイミング];

つまみは「;」区切りが1つの繋がったレーザーを表しており、「,」区切りのデータ3つごとに

  • 「レーザー形状(直線、直角、曲線)」
  • 「終点タイミング(分数)」
  • 「終点レーン位置(レーン全体が0~1の小数で、はみ出しは-0.5~1.5で表現)」

を示します。

始点は1個前のデータに依存し、一番最初にだけ

  • 「レーザー名」
  • 「始点タイミング」
  • 「始点レーン位置」

を表すデータが入ります。

VOL,[レーザー名],[始点タイミング],[始点レーン位置],
[レーザー形状],[終点タイミング],[終点レーン位置],
……
[レーザー形状],[終点タイミング],[終点レーン位置];

レーザー形状は

  • STRAIGHT
  • VERTICAL
  • CURVE
    • IN
    • OUT
    • INOUT

という種類に分かれています。CURVEの種類は「CURVE」と「IN」などの文字列が「,」の間に両方入っていることで判定されます。「CURVE_IN」などの書き方がおすすめ。

[譜面画像]
STRAIGHT
[譜面画像]
VERTICAL
[譜面画像]
CURVE IN
[譜面画像]
CURVE OUT
[譜面画像]
CURVE INOUT

実はBPMを表示する機能があります。小節数っぽく見えることもあってアレですが一応使えます。

BPM,
165,0/4,
156,1/4,
148,2/4,
139,3/4,
130,4/4,
121,5/4,
113,6/4,
104,7/4,
107,32/16,
121,33/16,
136,34/16,
151,35/16,
166,36/16,
181,37/16,
195,38/16,
210,39/16,
218,40/16,
;
CHIP,
A,-5/24,
L,-4/24,
B,-3/24,
C,-2/24,
R,-1/24,
D,0/4,
B,32/16,
B,35/16,
B,38/16,
B,39/16,
A,40/16,
;
LONG,
D,10/4,11/4,
;
VOL,
L,11/4,0,
VERTICAL,11/4,1,
;
VOL,
R,32/16,0.4,
STRAIGHT,35/16,0.4,
;
VOL,
L,35/16,0.6,
STRAIGHT,38/16,0.6,
;
VOL,
R,38/16,0.4,
STRAIGHT,39/16,0.4,
;
VOL,
L,39/16,0.6,
STRAIGHT,40/16,0.6,
;
[譜面画像]
合格発表地帯

課題

  • コードが凄まじく汚いので整理したいです。
  • 処理を軽くできているかわかりません。不必要に重い可能性あり。
  • 小節線に関して、仕様を決めかねておりまだ4/4しか表現できません。
  • 今のところ愚直に譜面が終わるまで表示してしまうので、表示範囲や譜面の改行を任意で指定できるようにしたいです。こちらも仕様を決めかねています。
  • 縮小されたときに一部の線が見えなくなるのを改善したいです。
  • 直角と同時に始まる曲線つまみが特殊な仕様をしており、canvasの機能だけでは再現が非常に困難*1なため、現状そういった形を描画すると表示が荒れます。
[譜面画像] [譜面画像] [譜面画像]
どこに限界が生じているかがわかりやすい形のつまみ

公開?

今のところ実用に堪えるかわからないので、とりあえずご紹介だけ。

この記事では必要な要素をすべてHTMLに直書きしているので、ソースを開くと一応全部見ることができます*2

追記

"https://70165tk.github.io/sdvx-chart-display-javascript/sdvx-chart-display.js"をscriptタグのsrcに設定することで単体で使えるようにしました。

*1:3次ベジェ曲線と直線の交点座標および、分割された3次ベジェ曲線を表す式が必要

*2:<div class="entry-content"></div>に入っています