質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

3回答

412閲覧

JavaScriptでFNF音ゲー制作

falcon_function

総合スコア6

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

0クリップ

投稿2023/06/26 14:17

実現したいこと

  • 音楽の再生時間に応じて、キーボードが押された時点の判定枠を実装したい
  • 音声ファイルが読み込まれた時点で再生したいが、ユーザーアクションがないと再生できない問題を解決したい
  • 画像読み込み時、requestAnimationFrameを使ってノーツを実際に動かしたい

前提

発生している問題・エラーメッセージ

・今はEnterキーを押したら音楽が再生されるようにしていますが、再びEnterキーを押すと二重三重にも再生されてしまうため その対策をしたい。 ・試しにクラスノーツで、描画と移動をrequestAnimationFrameで動かそうとしたが、描画されはするが微動だにしない。 コンソールログでposyを確認してみたが、posy = 2で変化がない。

該当のソースコード

JavaScript

1let canvas = document.querySelector(".fnfcanvas"); 2let ctx = canvas.getContext("2d"); 3let width = canvas.width = 1080; 4let height = canvas.height = 640; 5//ノーツそのものの制御(座標・加速度・画像の大きさ・各秒数) 6class Notes{ 7 constructor(x,y,VelX,VelY,width,height,time){ 8 this.x = x; 9 this.y = y; 10 this.VelX = VelX; 11 this.VelY = VelY; 12 this.width = width; 13 this.height = height; 14 this.time = time; 15 } 16 notesmoving(){ 17 //ここにVelYの挙動およびVelXなどの挙動を書く。 18 if((this.y + this.height) >= height ){ 19 this.VelY = -(this.VelY); 20 } 21 if((this.y - this.height) <= 0){ 22 this.VelY = -(this.velY); 23 } 24 this.y += this.VelY; 25 26 } 27 notesdrawing(){ 28 //ここに描画処理を書く。 29 ctx.fillRect(0,0,width,height); 30 ctx.translate(width/2,height/2); 31 const note_sprite = new Image(); 32 note_sprite.src = "arrow_down_empty.png"; 33 34 let sprite = 0; 35 let posy = 0; 36 37 note_sprite.addEventListener("load",(event)=>{ 38 ctx.drawImage(note_sprite,(sprite * 158),0,158,157,0,0+posy,74,73.5); 39 }); 40 ctx.fillRect(-(width/2), -(height/2), width, height); 41 if (posy > height/2) { 42 let newStartPos = -((height/2) + 157); 43 posX = Math.ceil(newStartPos); 44 console.log(posy); 45 } else { 46 posy += 2; 47 } 48 } 49} 50const notes_LEGENDALY = []; 51const notes_LASO = []; 52const notes_SLASO = []; 53 54 55function loop(){ 56 const test = new Notes(0,0,1,1,158,157,34.5); 57 test.notesdrawing(); 58 test.notesmoving(); 59} 60 61window.requestAnimationFrame(loop); 62 63 64 65//判定枠 66class notes_lane extends Notes{ 67 constructor(x,y,VelX,VelY,width,height,time){ 68 super(x,y,VelX,VelY,width,height,time); 69 } 70 laneupdate(){ 71 72 } 73 74 lanedisplay(){ 75 76 } 77 lanedraw(){ 78 laneupdate(); 79 lanedisplay(); 80 } 81} 82//ノーツの種類(上から通常・半透明・ダメージノーツ・即死ノーツ) 83class Notes_Elements{ 84 constructor(){ 85 this.normal = 'normal'; 86 this.invisible = 'invisible'; 87 this.reverse = 'damage'; 88 this.death = 'death'; 89 } 90} 91 92 93 94 95 96//グローバル定数を作れるらしいので、やってみる。 97function define(name,value){ 98 Object.defineProperty(window,name,{ 99 get: function(){return value;}, 100 set: function(){throw(name+ "は既に定義済みです!");}, 101 }); 102} 103define("PERFECT",32); 104define("GOOD",70); 105define("BAD",110); 106define("MISS",150); 107 108 109class Pushing{ 110 constructor(up_push,down_push,left_push,right_push){ 111 this.up_push = false; 112 this,down_push = false; 113 this.left_push = false; 114 this.right_push = false; 115 } 116} 117class Pushing_continue extends Pushing{ 118 constructor(up_pushing,down_pushing,left_pushing,right_pushing){ 119 super(up_pushing,down_pushing,left_pushing,right_pushing); 120 } 121 122} 123//押した経過時間の計算 124class passed_time{ 125 constructor(s_time,e_time){ 126 this.s_time = s_time; 127 this.e_time = e_time; 128 } 129 progress(){ 130 if(this.e_time < this.s_time){ 131 return (this.s_time - this.e_time); 132 } else { 133 return (this.e_time - this.s_time); 134 } 135 } 136} 137let totaltime = new passed_time(); 138 139//判定枠 140const move=(key_send)=>{ 141 if(key_send.up_push){ 142 const judgetime = totaltime.progress(); 143 144 145 if((judgetime <= PERFECT) && (judgetime >= 0)){ 146 console.log(`Perfect: ${judgetime}ms`); 147 } 148 149 if(judgetime <= GOOD && judgetime > PERFECT){ 150 console.log(`GOOD: ${judgetime}ms`); 151 } 152 153 if(judgetime <= BAD && judgetime > GOOD){ 154 console.log(`BAD: ${judgetime}ms`); 155 } 156 157 } 158 159 if(key_send.down_push){ 160 const judgetime = totaltime.progress(); 161 162 163 if((judgetime <= PERFECT) && (judgetime >= 0)){ 164 console.log(`Perfect: ${judgetime}ms`); 165 } 166 167 if(judgetime <= GOOD && judgetime > PERFECT){ 168 console.log(`GOOD: ${judgetime}ms`); 169 } 170 171 if(judgetime <= BAD && judgetime > GOOD){ 172 console.log(`BAD: ${judgetime}ms`); 173 } 174 } 175 176 if(key_send.left_push){ 177 const judgetime = totaltime.progress(); 178 179 180 if((judgetime <= PERFECT) && (judgetime >= 0)){ 181 console.log(`Perfect: ${judgetime}ms`); 182 } 183 184 if(judgetime <= GOOD && judgetime > PERFECT){ 185 console.log(`GOOD: ${judgetime}ms`); 186 } 187 188 if(judgetime <= BAD && judgetime > GOOD){ 189 console.log(`BAD: ${judgetime}ms`); 190 } 191 } 192 193 if(key_send.right_push){ 194 const judgetime = totaltime.progress(); 195 196 197 if((judgetime <= PERFECT) && (judgetime >= 0)){ 198 console.log(`Perfect: ${judgetime}ms`); 199 } 200 201 if(judgetime <= GOOD && judgetime > PERFECT){ 202 console.log(`GOOD: ${judgetime}ms`); 203 } 204 205 if(judgetime <= BAD && judgetime > GOOD){ 206 console.log(`BAD: ${judgetime}ms`); 207 } 208 } 209}; 210 211document.addEventListener('keydown',(event)=>{ 212 const check = new Pushing(); 213 switch (event.key){ 214 case 'ArrowUp': 215 totaltime.s_time = performance.now(); 216 check.up_push = true; 217 break; 218 case 'ArrowDown': 219 totaltime.s_time = performance.now(); 220 check.down_push = true; 221 break; 222 case 'ArrowLeft': 223 totaltime.s_time = performance.now(); 224 check.left_push = true; 225 break; 226 case 'ArrowRight': 227 totaltime.s_time = performance.now(); 228 check.right_push = true; 229 break; 230 } 231 console.log(`keydown: ${totaltime.s_time}ms`); 232 move(check); 233}); 234 235 236document.addEventListener('keyup', (event) => { 237 const check = new Pushing(); 238 switch (event.key){ 239 case 'ArrowUp': 240 totaltime.e_time = performance.now(); 241 check.up_push = false; 242 break; 243 case 'ArrowDown': 244 totaltime.e_time = performance.now(); 245 check.down_push = false; 246 break; 247 case 'ArrowLeft': 248 totaltime.e_time = performance.now(); 249 check.left_push = false; 250 break; 251 case 'ArrowRight': 252 totaltime.e_time = performance.now(); 253 check.right_push = false; 254 break; 255 } 256 console.log(`keyup: ${totaltime.s_time}ms`); 257}); 258

試したこと

・performance.now()を使い、keydownとkeyupで、キーが押されたタイミングで変数に保存し、その差を計算した。
・ノーツクラスにnotesdrawingとnotesmovingメソッドを追加して、requestAnimationFrameで描画しながら移動するように試みた。

補足情報(FW/ツールのバージョンなど)

ブラウザ:Chrome 114.0.5735.134
PCのスペック: CPU: i7-12700 2.10 GHz
メモリ: 32GB
Windows11 Home 22H2

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

・今はEnterキーを押したら音楽が再生されるようにしていますが、再びEnterキーを押すと二重三重にも再生されてしまうためその対策をしたい。

これは1つ前の質問で回答しているので省略。

・試しにクラスノーツで、描画と移動をrequestAnimationFrameで動かそうとしたが、描画されはするが微動だにしない。コンソールログでposyを確認してみたが、posy = 2で変化がない。

js

1function loop(){ 2 const test = new Notes(0,0,1,1,158,157,34.5); 3 test.notesdrawing(); 4 test.notesmoving(); 5} 6 7window.requestAnimationFrame(loop);

loop() が一度しか呼ばれていません。requestAnimationFrame() は繰り返し呼ぶ必要があります。

js

1const test = new Notes(0,0,1,1,158,157,34.5); 2function loop(){ 3 test.notesdrawing(); 4 test.notesmoving(); 5 window.requestAnimationFrame(loop); 6} 7 8window.requestAnimationFrame(loop);

それから、posynotesdrawing() で毎回初期化されているので移動しません。this.y などを参照したいのではないでしょうか。

note_sprite はグローバル変数にして、その load イベントが発行されてからゲーム開始にしないと最初の描画でもたつくと思います。

投稿2023/06/26 22:21

int32_t

総合スコア20914

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

自己解決

描画については自己解決しましたのでご報告いたします。
しかし、次は当たり判定と音楽の再生時間の取得方法についてがまだわかっていないので、そちらのほうを優先したいと思います

JavaScript

1let canvas = document.querySelector(".fnfcanvas") 2let ctx = canvas.getContext("2d"); 3let g_width = canvas.width = 1080; 4let g_height = canvas.height = 680; 5let posy = 0; 6let sprite = 0; 7let note_sprite = new Image(); 8 9 10//ノーツそのものの制御(座標・加速度・画像の大きさ・各秒数) 11class Notes{ 12 constructor(x,y,VelX,VelY,width,height,time){ 13 this.x = x; 14 this.y = y; 15 this.VelX = VelX; 16 this.VelY = VelY; 17 this.width = width; 18 this.height = height; 19 this.time = time; 20 } 21 22 async notesdrawing(x,y,VelX,VelY,width,height,time){ 23 //ここに描画処理を書く。 24 ctx.clearRect(0,0,width,height); 25 ctx.translate(width/2,height/2); 26 note_sprite.src = "arrow_down_empty.png"; 27 ctx.fillRect(-(width/2), -(height/2), width, height); 28 note_sprite.addEventListener("load",(event)=>{ 29 ctx.clearRect(0,0,g_width,g_height); 30 ctx.drawImage(note_sprite,(sprite * 220),0,158,157,110,0+posy,158,157); 31 }); 32 33 if (posy > g_height) { 34 const newStartPos = -((g_height/2) + 120); 35 posy = Math.ceil(newStartPos); 36 } else { 37 posy += 4; //ここの部分は 38 } 39 } 40 41 async notesmoving(x,y,VelX,VelY,width,height,time){ 42 //ここにVelYの挙動およびVelXなどの挙動を書く。 43 if(this.y + this.height >= g_height ){ 44 this.VelY = -(this.VelY); 45 } 46 if((this.y - this.height) <= 0){ 47 this.VelY = -(this.velY); 48 } 49 this.y += this.VelY; 50 51 } 52} 53 54//const notes_LEGENDALY = []; 55//const notes_LASO = []; 56//const notes_SLASO = []; 57const test = new Notes(110,-100,1,4,110,110,34.5); 58async function loop(){ 59 test.notesdrawing(); 60 test.notesmoving(); 61 window.requestAnimationFrame(loop); 62} 63window.requestAnimationFrame(loop);

投稿2023/06/27 11:19

falcon_function

総合スコア6

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

この回答はGPT-4による自動生成回答です

check.up_push = true; move(check); break; case 'ArrowDown': totaltime.s_time = performance.now(); check.down_push = true; move(check); break; case 'ArrowLeft': totaltime.s_time = performance.now(); check.left_push = true; move(check); break; case 'ArrowRight': totaltime.s_time = performance.now(); check.right_push = true; move(check); break; case 'Enter': const audio = new Audio('sample_music.mp3'); audio.play(); break; default: break; }

});

document.addEventListener('keyup',(event)=>{
const check = new Pushing();
switch (event.key){
case 'ArrowUp':
totaltime.e_time = performance.now();
check.up_push = false;
move(check);
break;
case 'ArrowDown':
totaltime.e_time = performance.now();
check.down_push = false;
move(check);
break;
case 'ArrowLeft':
totaltime.e_time = performance.now();
check.left_push = false;
move(check);
break;
case 'ArrowRight':
totaltime.e_time = performance.now();
check.right_push = false;
move(check);
break;
default:
break;
}
});

投稿2023/06/26 14:17

teratail-ai

Powered by GPT-4

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問