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

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

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

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

Q&A

解決済

2回答

813閲覧

サイコロのアニメーションとメッセージウインドウに表示される目(数字)が一回ずつずれてしまうのはなぜか?

jdshngy

総合スコア4

JavaScript

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

0グッド

2クリップ

投稿2022/06/12 06:14

編集2022/06/12 06:17

【困っていること】
テキストベースのすごろくゲームを作成しています。
しかしただテキスト表示されるだけだと物足りないので
サイコロのアニメーションを追加していますが、
画面に表示されるサイコロの目とテキストに表示されるサイコロの目が1回分ずつズレてしまい、
ゲーム自体は遊べるのですが、ヘンテコなゲーム画面になってしまいます。
テキストと画面に表示されるサイコロの目を一致させる方法をご教示いただけないでしょうか?

【試したこと】
関数を分けているので良くないかと思い1つにまとめてみて試しましたが、こちらもうまくいきませんでした。
初歩的なことが原因かと思うのですが、混乱してきてしまったため、恐縮ではございますが、良い解決方法があればご教示をお願いします。

javascript

1コード 2 3'use strict' 4 5 6var img,cm,messegegamen,ctx,gamegamen ; 7 8var Nokorimasu = 0; //ゴールまでの残りマス 9var Susumimasu = 0; //進んだ合計マス 10var player = ""; 11 12var DiceNumber=0; 13 14var DiceNumberR=0; 15 16var dicekaisu = 0; 17 18 19function gamekaishi(){ 20 21 22dicekaisu = 30; 23 24SaiNokori(); 25 26//canvas準備(msg) 27var msgwindow = document.getElementById('msg'); 28var cm = msgwindow.getContext('2d'); 29cm.font="18pt serif"; 30cm.fillStyle='white'; 31 32var gamegamen = document.getElementById('game'); 33var cg = gamegamen.getContext('2d'); 34 35Nokorimasu = 100; 36Susumimasu = 0; 37 38 39 40 41 player = document.getElementById('playername').value; 42if(player===""){ 43 alert("プレイヤー名が入力されていません!"); 44} 45 46else{cg.clearRect(0,0,800,800); 47 cm.clearRect(0,0,800,800); 48 cm.fillText("Game Start!",20,50); 49 cm.fillText("サイコロをふり、ゴールを目指そう!",20,80); 50 51 cg.font="20pt Georgia"; 52 cg.fillStyle='black'; 53 cg.fillText("残りマス:"+Nokorimasu,30,25); 54 cg.fillText("今のマス:"+Susumimasu,200,25); 55 56 57} 58 59 60} 61 62 63 64 65 66 67function hajime(){ 68 69 //canvas(game)準備 70var gamegamen = document.getElementById('game'); 71var cg = gamegamen.getContext('2d'); 72cg.font="35pt Georgia"; 73cg.fillStyle='#FFFFFF'; 74cg.fillText("ランダムすごろく",80,250); 75 76//canvas(msg)準備 77var msgwindow = document.getElementById('msg'); 78var cm = msgwindow.getContext('2d'); 79cm.font="18pt serif"; 80cm.fillStyle='white'; 81 82var textarr = ["プレイヤー名を入力し、","スタートボタンを押してください。"] 83cm.fillText(textarr[0],20,50); 84cm.fillText(textarr[1],20,70); 85 86 87 88} 89 90 91 92//ランダム値の計算 93function randnum(){ 94 var bunkinum = 1+Math.floor( Math.random() * 10); 95return bunkinum; 96 97} 98 99//画像表示処理※検証中 GazouHyouji(usagiimg)などが使えるかどうか 100function GazouHyouji() 101{ 102var gamegamen = document.getElementById('game'); 103var cg = gamegamen.getContext('2d') 104 105var sai1 = new Image(); 106 sai1.src="img/sai1.PNG"; 107 108var sai2 = new Image(); 109 sai2.src="img/sai2.PNG"; 110 111var sai3 = new Image(); 112 sai3.src="img/sai3.PNG"; 113 114var sai4 = new Image(); 115 sai4.src="img/sai4.PNG"; 116 117var sai5 = new Image(); 118 sai5.src="img/sai5.PNG"; 119 120var sai6 = new Image(); 121 sai6.src="img/sai6.PNG"; 122 123} 124 125 126function SaiNokori(){ 127 128 129var nokorisai=document.getElementById("nokorisai"); 130var ns = nokorisai.getContext('2d'); 131ns.clearRect(0,0,800,800); 132 133ns.font="20pt serif"; 134ns.fillStyle='black'; 135 136ns.fillText("のこり:"+ dicekaisu+"回",5,30); 137 138dicekaisu = dicekaisu-1; 139console.log(dicekaisu+"dicekaisu"); 140} 141 142 143 144 145 146//サイコロをふる1 147function DiceRollR(){ 148 149var fn = function() { 150 151var gamegamen = document.getElementById('game'); 152var cg = gamegamen.getContext('2d'); 153 154var msgwindow = document.getElementById('msg'); 155var cm = msgwindow.getContext('2d'); 156cm.font="18pt serif"; 157cm.fillStyle='white'; 158 159 160 161var sai0 = 0; 162var sai1 = new Image(); 163 sai1.src="img/sai1.PNG"; 164 165var sai2 = new Image(); 166 sai2.src="img/sai2.PNG"; 167 168var sai3 = new Image(); 169 sai3.src="img/sai3.PNG"; 170 171var sai4 = new Image(); 172 sai4.src="img/sai4.PNG"; 173 174var sai5 = new Image(); 175 sai5.src="img/sai5.PNG"; 176 177var sai6 = new Image(); 178 sai6.src="img/sai6.PNG"; 179 180var sailist = [sai0,sai1,sai2,sai3,sai4,sai5,sai6]; 181 182DiceNumberR = 1+Math.floor( Math.random() * 6); 183  var saiN = sailist[DiceNumberR]; 184 185cg.drawImage(saiN,150,150,100,100); 186 187console.log(DiceNumberR+"random") 188 189 if(i > 10) clearInterval(id); 190 i++; 191 192// 193} 194var tm = 50; 195var i = 0; 196var id = setInterval(fn,tm); 197// 198 199// 200} 201 202function DiceRoll1(){ 203 204DiceRollR(); 205 206//canvas(msg)準備 207var msgwindow = document.getElementById('msg'); 208var cm = msgwindow.getContext('2d'); 209cm.font="18pt serif"; 210cm.fillStyle='white'; 211 212 213var gamegamen = document.getElementById('game'); 214var cg = gamegamen.getContext('2d'); 215 216var sai0 = ""; 217var sai1 = new Image(); 218 sai1.src="img/sai1.PNG"; 219 220var sai2 = new Image(); 221 sai2.src="img/sai2.PNG"; 222 223var sai3 = new Image(); 224 sai3.src="img/sai3.PNG"; 225 226var sai4 = new Image(); 227 sai4.src="img/sai4.PNG"; 228 229var sai5 = new Image(); 230 sai5.src="img/sai5.PNG"; 231 232var sai6 = new Image(); 233 sai6.src="img/sai6.PNG"; 234 235var sailist = [sai0,sai1,sai2,sai3,sai4,sai5,sai6]; 236 237DiceNumber = DiceNumberR; //test ここが原因 238 239// 240 241 242 243//DiceNumber = 1+Math.floor( Math.random() * 6); 244  var saiN = sailist[DiceNumber]; 245 246// 247 248 249Nokorimasu = Nokorimasu-DiceNumber; 250Susumimasu = Susumimasu+DiceNumber; 251console.log(Susumimasu+"+"+DiceNumber) 252 253cm.clearRect(0,0,800,800); 254 255 cg.clearRect(0,0,800,800); 256 cg.fillText("残りマス:"+Nokorimasu,30,25); 257 cg.fillText("今のマス:"+Susumimasu,200,25); 258 259cm.fillText("サイコロの数字は "+DiceNumberR+"!",20,50); 260 cm.fillText(player+"は"+DiceNumberR+"つ進んだ。",20,70); 261 262 263 264 265} 266 267 268//サイコロをふる2 269 270 271 function DiceRoll2(){ 272 273 if(Nokorimasu===""){ 274 275 276 277}else if(Nokorimasu<0){ 278 279 280alert(player+"は目的地に着いた!") 281return; 282 283}else if(dicekaisu<1){ 284alert("残念!ゲームオーバーです。スタートボタンを押すと新しくゲームをはじめることができます。") 285}else{ 286 287 288 289 DiceRoll1(); 290 291 292 SaiNokori(); 293 294 295 296var msgwindow = document.getElementById('msg'); 297cm = msgwindow.getContext('2d'); 298cm.font="17pt serif"; 299cm.fillStyle='white'; 300 301var gamegamen = document.getElementById('game'); 302var cg = gamegamen.getContext('2d'); 303 304 305 306 307 308 309 var bunkinum = randnum(); 310 311 312 console.log(bunkinum+"here"); 313 314 switch(bunkinum){ 315 316 case 1: 317 cm.fillText("ふつうの道だ。変わったところはない。",20,90); 318 console.log(1+"here"); 319 break; 320 321 case 2: 322 323cm.fillText("近道を見つけた!",20,90); 324DiceNumber = DiceNumber+DiceNumber; 325 326cm.fillText(player+"はさらに"+DiceNumber+"つ進んだ!",20,110); 327 328 329 break; 330 case 3: 331 cm.fillText(player+"は、おいしそうな果物を見つけた!",20,90); 332 333dicekaisu = dicekaisu+3; 334 335cm.fillText("元気になり、サイコロ残り回数が3つ増えた!",20,110); 336 337 console.log(3+"here"); 338 break; 339 340 case 4: 341cm.fillText(player+"は道に迷った!",20,90); 342 343Nokorimasu = Nokorimasu+3; 344Susumimasu = Susumimasu-3; 345 346cm.fillText("3マス戻ってしまった!",20,110); 347 348 349 break; 350 351 case 5: 352cm.fillText(player+"は、盗賊に襲われた!",20,90); 353dicekaisu=dicekaisu-2 354 355 356cm.fillText(player+"のサイコロ残り回数が2減った!",20,110); 357 358 359 360 break; 361 362 case 6: 363cm.fillText(player+"は、猛獣に襲われ、逃げた!",20,90); 364 365Nokorimasu = Nokorimasu+4; 366Susumimasu = Susumimasu-4; 367 368cm.fillText(player+"は、4マス戻った!",20,110); 369 370 371 break; 372 373 case 7: 374cm.fillText("ふつうの道だ。変わったところはない。",20,90); 375 376 break; 377cm.fillText("ふつうの道だ。変わったところはない。",20,90); 378 379 case 8: 380cm.fillText("ふつうの道だ。変わったところはない。",20,90); 381 382 break; 383 384 case 9: 385cm.fillText("ふつうの道だ。変わったところはない。",20,90); 386 387 388 break; 389 390 case 10: 391 392cm.fillText(player+"は、おいしそうな果物を見つけた!",20,90); 393 394dicekaisu = dicekaisu+3; 395 396cm.fillText("元気になり、サイコロ残り回数が3つ増えた!",20,110); 397 398 break; 399 400 default:alert("開発者へ連絡してください"); 401 break; 402 403 } 404 405 406 407 } 408 409} 410

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

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

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

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

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

guest

回答2

0

ベストアンサー

DiceRoll1の中でDiceRollRが呼ばれていますが、
DiceRollRの中にある

var id = setInterval(fn,tm);

のsetInterval は非同期であるため、fn の実行を予約した後すぐDiceRoll1に戻ってしまっています。
このため期待する動作(fnの動作が全部完了した後にDiceRoll1に戻る)となっていません。

したがって、下記のように、fnの中で、指定回数繰り返したら clearInterval を実行して得られたランダム数をDiceRoll1に渡す、というように直す必要があります。

※おそらく、現状は「サイコロを振る」ボタンを押したら DiceRoll1() を呼び出すようになっていると思いますが、下記のコードの場合は、「サイコロを振る」ボタンを押したら DiceRollR() を実行するように修正してください。

js

1//サイコロをふる1 2function DiceRollR() { 3 console.log("DiceRollR start") 4 5 var fn = function () { 6 var gamegamen = document.getElementById("game"); 7 var cg = gamegamen.getContext("2d"); 8 9 var msgwindow = document.getElementById("msg"); 10 var cm = msgwindow.getContext("2d"); 11 cm.font = "18pt serif"; 12 cm.fillStyle = "white"; 13 14 cg.clearRect(0, 0, 800, 800); 15 var sai0 = 0; 16 var sai1 = new Image(); 17 sai1.src = "img/sai1.PNG"; 18 19 var sai2 = new Image(); 20 sai2.src = "img/sai2.PNG"; 21 22 var sai3 = new Image(); 23 sai3.src = "img/sai3.PNG"; 24 25 var sai4 = new Image(); 26 sai4.src = "img/sai4.PNG"; 27 28 var sai5 = new Image(); 29 sai5.src = "img/sai5.PNG"; 30 31 var sai6 = new Image(); 32 sai6.src = "img/sai6.PNG"; 33 34 var sailist = [sai0, sai1, sai2, sai3, sai4, sai5, sai6]; 35 36 DiceNumberR = 1 + Math.floor(Math.random() * 6); 37 var saiN = sailist[DiceNumberR]; 38 39 cg.drawImage(saiN, 150, 150, 100, 100); 40 41 console.log(DiceNumberR + "random"); 42 43 if (i > 10) { 44 clearInterval(id); 45 DiceRoll1(DiceNumberR) 46 } 47 i++; 48 49 }; 50 var tm = 50; 51 var i = 0; 52 var id = setInterval(fn, tm); 53 54} 55 56function DiceRoll1(DiceNumber) { 57 //canvas(msg)準備 58 var msgwindow = document.getElementById("msg"); 59 var cm = msgwindow.getContext("2d"); 60 cm.font = "18pt serif"; 61 cm.fillStyle = "white"; 62 63 var gamegamen = document.getElementById("game"); 64 var cg = gamegamen.getContext("2d"); 65 66 Nokorimasu = Nokorimasu - DiceNumber; 67 Susumimasu = Susumimasu + DiceNumber; 68 console.log(Susumimasu + "+" + DiceNumber); 69 70 cm.clearRect(0, 0, 800, 800); 71 72 cg.fillText("残りマス:" + Nokorimasu, 30, 25); 73 cg.fillText("今のマス:" + Susumimasu, 200, 25); 74 75 cm.fillText("サイコロの数字は " + DiceNumberR + "!", 20, 50); 76 cm.fillText(player + "は" + DiceNumberR + "つ進んだ。", 20, 70); 77} 78

投稿2022/06/12 09:06

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

jdshngy

2022/06/12 21:33

ご回答いただきありがとうございます! まだ試せておりませんが、いただいたコードを確認させていただき、またご返事させていただきます。 今しばらくお待ちください。
guest

0

画面に表示されるサイコロの目とテキストに表示されるサイコロの目が1回分ずつズレてしまい、
ゲーム自体は遊べるのですが、ヘンテコなゲーム画面になってしまいます。

その原因はサイコロを振る関数が非同期実行だからです。
以下のコードは問題を端的に再現するコードです。

javascript

1var DiceNumberR = 0; 2 3function main() { 4 DiceRollR(); // ① 5 console.log("結果は" + DiceNumberR + "です"); // ② 6} 7 8function DiceRollR() { 9 var fn = function() { // ③ 10 // (省略) 11 12 DiceNumberR = 1+Math.floor( Math.random() * 6); 13 14 console.log(DiceNumberR+"random") 15 16 if(i > 10) clearInterval(id); 17 i++; 18 } 19 var tm = 50; 20 var i = 0; 21 var id = setInterval(fn,tm); // ④ 22} 23 24main();

これを実行すると「結果は《数値》です」が表示された後に、DiceRollR実行中に表示されるメッセージが出力されることがわかると思います。
その理由は処理が以下のように実行されているからです。


DiceRollR()の実行開始 ※上記コードコメント「①」の行

setIntervalによって50ミリ秒後にfnの実行が予約される ※上記コードコメント「④」の行

DiceNumberRがメッセージ表示される ※上記コードコメント「②」の行

50ミリ秒が経過する

fnが実行されて、DiceNumberRが設定される ※上記コードコメント「③」の行


対策として一番簡単なのは、DiceRollR()で最終結果が得られたタイミングで処理を実行できるようにすることです。
以下がこの問題を解決したコードです。
実行すると、DiceRollR実行中に表示されるメッセージが出力された後に「結果は《数値》です」が表示されます。
これを参考にあなたのソースコードを修正を行いましょう。

javascript

1var DiceNumberR = 0; 2 3function main() { 4 var showDiceResultFunction = function () { 5 console.log("結果は" + DiceNumberR + "です"); 6 }; 7 DiceRollR(showDiceResultFunction); 8} 9 10function DiceRollR(showDiceResultFunction) { 11 var fn = function() { 12 // (省略) 13 14 DiceNumberR = 1+Math.floor( Math.random() * 6); 15 16 console.log(DiceNumberR+"random") 17 18 if(i > 10) { clearInterval(id); showDiceResultFunction() } 19 i++; 20 } 21 var tm = 50; 22 var i = 0; 23 var id = setInterval(fn,tm); 24} 25 26main();

投稿2022/06/12 08:19

ku__ra__ge

総合スコア4524

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

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

ku__ra__ge

2022/06/12 08:24

この問題に対するベストな解決方法は async/await を使うというものです。 しかしそれを使うには多くの前提知識が必要なので、ベストではないけれど単純な解決策を提示しました。
jdshngy

2022/06/12 21:30

ご回答いただきありがとうございます! 端的にご説明いただきありがとうございます。 async/awaitを使う解決方法というのも あるのですね! まだ試せていませんが、ご教示いただいたコードを元に修正を試みたいと思います。
jdshngy

2022/06/14 11:15

ベストアンサーとはならず申し訳ございませんでしたが、お二人の回答を元に修正を行ったところ、無事求めていた結果を出力することができました!ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問