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

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

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

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

JavaScript

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

enchant.js

enchant.jsとは、アプリやゲームを簡単に開発できるオープンソースのHTML5+JavaScriptベースのフレームワークです。プログラミング学習にも用いられ、多くの素材やプラグインが用意されています。

Q&A

解決済

2回答

2149閲覧

enchant.jsのサウンドを使用する際にXampp環境だとエラーが出てしまう

web11

総合スコア52

canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

JavaScript

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

enchant.js

enchant.jsとは、アプリやゲームを簡単に開発できるオープンソースのHTML5+JavaScriptベースのフレームワークです。プログラミング学習にも用いられ、多くの素材やプラグインが用意されています。

0グッド

0クリップ

投稿2020/06/01 07:44

Chromeのセキュリティ上の問題でローカルだとサウンドがエラーになって動かないと思ったので、似たような症状で解決した事例を探しました。
こちらで問題なくローカル上だと音が出るようになったのですが、Xampp環境では、以前と変わらずエラーを吐いたままの状態です。
解決策を教えて下さい。よろしくおねがいします。

参考にしたurl
https://teratail.com/questions/252196

javascript

1// enchant.js本体やクラスをエクスポートする 2enchant(); 3 4// ページが読み込まれたときに実行される関数 5window.onload = function() { 6 7 // コアオブジェクトを作成する 8 core = new Core(320, 320); 9 10 // 1秒あたりの画面の描画回数を設定する(省略時は「30」) 11 core.fps = 16; 12 13 // ゲームで使用する画像ファイル、サウンドファイルを読み込む 14 // mp3形式のサウンドファイルはプリロードする(FireFox,Safari対応) 15 core.preload('betty.png', 'flowers.png', 'one_0.mp3'); 16 17 // BGM用のサウンドファイルを読み込む 18 core.bgm = Sound.load('one_0.mp3'); 19 // SE用のサウンドファイルを読み込む 20 core.se = Sound.load('Ready.wav'); 21 22 23 // ファイルのプリロードが完了したときに実行される関数 24 core.onload = function() { 25 26 // BGMのボリュームを設定する(0~1) 27 core.bgm.volume = 0.5; 28 // BGMを再生する 29 core.bgm.play(); 30 // SEを再生する 31 core.se.play(); 32 33 // サーフィスを作成する 34 var image = new Surface(320, 320); 35 // 「flowers.png」の(0, 96)の位置から幅「126」ピクセル、高さ「64」ピクセルの領域を 36 // サーフィスの(64, 64)の位置に幅「126」ピクセル、高さ「64」ピクセルで描画する 37 image.draw(core.assets['flowers.png'], 0, 96, 126, 64, 64, 64, 126, 64); 38 39 // サーフィスを表示するためのスプライトを作成する 40 var bg = new Sprite(320, 320); 41 // スプライトにサーフィスを設定する 42 bg.image = image; 43 44 core.rootScene.addChild(bg); 45 46 // スプライトを作成する 47 var player = new Sprite(48, 48); 48 // スプライトで表示する画像を設定する 49 player.image = core.assets['betty.png']; 50 // 表示するフレームの番号を設定する 51 player.frame = 3; 52 // 表示位置のx座標を設定する 53 player.x = 120; 54 // 表示位置のy座標を設定する 55 player.y = 50; 56 57 // フレーム数をカウントするプロパティを追加する 58 player.tick = 0; 59 60 // rootSceneにスプライトを追加する 61 core.rootScene.addChild(player); 62 63 // 「enterframe」イベントが発生したときに実行するリスナを登録する 64 player.addEventListener('enterframe', function(e) { 65 66 // 左ボタンが押されたら、スプライトをx方向に「-4」ピクセル移動する 67 if (core.input.left) { 68 this.x -= 4; 69 // スプライトのフレーム番号を切り替えてアニメーション表示する 70 this.frame = this.tick % 4 * 4 + 1; 71 // フレーム数をインクリメントする 72 this.tick ++; 73 } 74 75 // 右ボタンが押されたら、スプライトをx方向に「4」ピクセル移動する 76 if (core.input.right) { 77 this.x += 4; 78 this.frame = this.tick % 4 * 4 + 3; 79 this.tick ++; 80 } 81 82 // 上ボタンが押されたら、スプライトをy方向に「-4」ピクセル移動する 83 if (core.input.up) { 84 this.y -= 4; 85 this.frame = this.tick % 4 * 4 + 2; 86 this.tick ++; 87 } 88 89 // 下ボタンが押されたら、スプライトをy方向に「4」ピクセル移動する 90 if (core.input.down) { 91 this.y += 4; 92 this.frame = this.tick % 4 * 4; 93 this.tick ++; 94 } 95 96 }); 97 98 // 「touchmove」イベントが発生したときに実行するリスナを登録する 99 player.addEventListener('touchmove', function(e) { 100 // スプライトをタッチして移動した場所、またはドラッグした場所に移動する 101 this.x = e.x - this.width / 2; 102 this.y = e.y - this.height / 2; 103 }); 104 105 // ラベルを作成する 106 var infoLabel = new Label('enchant.js サンプル'); 107 // 表示位置のx座標を設定する 108 infoLabel.x = 16; 109 // 表示位置のy座標を設定する 110 infoLabel.y = 0; 111 // 文字色を設定する 112 infoLabel.color = '#0000FF'; 113 // フォントサイズとフォントの種類を指定する 114 infoLabel.font ='14px sens-serif'; 115 116 // rootSceneにラベルを追加する 117 core.rootScene.addChild(infoLabel); 118 119 120 }; 121 // ゲームスタート 122 core.start(); 123} 124

エラーコードになります
enchant.js:5481 Uncaught TypeError: Cannot read property 'gain' of undefined
at Constructor.set [as volume] (enchant.js:5886)
at Constructor.core.onload (game.js:27)
at Constructor.dispatchEvent (enchant.js:916)
at Constructor.<anonymous> (enchant.js:5085)
at Constructor.dispatchEvent (enchant.js:922)
at Constructor._succ (enchant.js:1465)
at Constructor.call (enchant.js:5458)
at Constructor._succ (enchant.js:5555)
at Constructor.call (enchant.js:5458)
at Constructor._callback (enchant.js:1384)

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

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

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

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

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

guest

回答2

0

ベストアンサー

ローカル上だと音が出るようになったのですが、Xampp環境では、以前と変わらずエラーを吐いたまま

以前とは異なるエラーではないでしょうか?

enchant.js-builds-master/build/enchant.js の 5949行 に条件 (三項) 演算子 が記述されています。

enchant.Sound = window.AudioContext && enchant.ENV.USE_WEBAUDIO ? enchant.WebAudioSound : enchant.DOMSound;

(window.AudioContext は、5763行に示される通り enchant.js 独自のクロスブラウザ対策です)

USE_WEBAUDIO をエディタで検索すると 473 行で定義されています。

javascript

1enchant.ENV = { // L330 2 3 USE_WEBAUDIO: (function() { // L473 4 return location.protocol !== 'file:'; 5 }()), 6 7}; // L487

enchant.ENV.USE_WEBAUDIO の実装から、音声は以下の実装で再生されます。

  • ローカル (file:)で動かすと、enchant.DOMSound (L5576-5761)
  • XAMPP (http:)では enchant.WebAudioSound (L5768-5947)

共に200行程度のenchant.DOMSoundenchant.WebAudioSoundを、MDNの解説を参考に紐解いてゆくのが、音声再生の仕組みの学び方と言えます。


rururu3 さんの回答(3つ目のコード)が enchant.js L5797 に該当し、play() が実行される(L5877-5811)まで this._gain がオブジェクトを持たないため、エラーで止まる状況です。

述べられている感想

playしないとボリューム設定できないのもおかしい

には同感でした。

解決策

おそらく Issue といっても良い状況ですので、enchant.js L5776 以下の「enchant.WebAudioSound の初期化時、_gain プロパティに相応のオブジェクトを持たせておく」方法を思いつきます。

javascript

1 2 initialize: function() { // enchant.js L5776 3 if (!window.AudioContext) { 4 throw new Error("This browser does not support WebAudio API."); 5 } 6 enchant.EventTarget.call(this); 7 if (!enchant.WebAudioSound.audioContext) { 8 enchant.WebAudioSound.audioContext = new window.AudioContext(); 9 enchant.WebAudioSound.destination = enchant.WebAudioSound.audioContext.destination; 10 } 11 this.context = enchant.WebAudioSound.audioContext; 12+ if (this.context.createGain != null) { 13+ this._gain = this.context.createGain(); 14+ } else { 15+ this._gain = this.context.createGainNode(); 16+ } 17 18 this.src = this.context.createBufferSource(); 19 this.buffer = null; 20 this._volume = 1; 21 this._currentTime = 0; 22 this._state = 0; 23 this.connectTarget = enchant.WebAudioSound.destination; 24 },

メンテナンスされてないなら、自分でメンテするという発想です。
(私はソースを読んだだけで試していませんが、駄目なら戻せばいいので、試してみては?)。


enchant.js は腰を据えて読んだことがなかったのですが、上記のようなコードの読み方/直し方をいろいろ試してみると、ゲームエンジンの特徴をより深く学べると思います。

投稿2020/06/02 21:53

編集2020/06/02 22:08
AkitoshiManabe

総合スコア5432

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

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

web11

2020/06/03 05:10

回答ありがとうございます。そちらのコードで_gainのエラーは解除されたのですが今度はdurationがnillで動かないと出てしまいました。 BGMを再生するcore.bgm.play();が動かないようです
AkitoshiManabe

2020/06/03 07:34

this.buffer が null で duration を読めないのは、enchant.WebAudioSound オブジェクトが初期値のまま、音声ファイルを読めていないのが原因かもしれません(本来、L5937 でbuffer は適用されます)。 XAMPP で実行したブラウザの開発者コンソール(Network タブ)でBGM用の音声ファイルが正しく読めているか確認してみましょう。「戻せばいい」ので、console.log() を書き込んで処理を追いかけるのも仕組みの理解につながりますよ。
web11

2020/06/03 11:43 編集

ありがとうございます。 Network タブで確認した所そもそも、読み込まれていませんでした。 なので根本的な解決では無いかもしれませんが、Sound.loadとしていた所は削除してassetsで直接読み込みにすると動くようになりました。 ```javascript core.assets['one_0.mp3'].volume = 0.4; core.assets['one_0.mp3'].play(); core.assets['Ready.wav'].play(); //音声ファイルは全てプリロード ``` もしくは、enchant.jsはWebAudioSoundがなければDOMSoundが動くようになっているのでようなので対応していないieでは動く事を確認しました。 なのでSound.lodとしている所、DOMSound指定にすると一応は動くようになるようです。 (違いはまだ、良くわかってませんが...) ```javascript core.bgm = DOMSound.load('one_0.mp3'); core.se = DOMSound.load('Ready.wav'); ```
web11

2020/06/03 11:51 編集

assetsで直接読み込んだ場合はDOMSoundが使用されているのかどうかがちょっとよくわかりません。 こちら分かりますでしょうか? (多分、assetsで直接読み込んだ場合だとthis._gainの所を直さないとvolumeがエラーが出てしまうのでWebAudioSoundが使われているのかなと思うのですが)
AkitoshiManabe

2020/06/06 07:23

> assetsで直接読み込んだ場合 お察しの通り、WebAudioSoundですね(assetsでエディタ検索:core.preload()>Sound.load() のような順になり、回答通り、プロトコルで切り分け)。enchant.js のコードは「読めている」印象です。
web11

2020/06/06 15:53

ありがとうございます。丁寧な解説で大変助かりました。 ベストアンサーに選ばせていただきます。
guest

0

JS

1 // BGMのボリュームを設定する(0~1) 2 core.bgm.volume = 0.5;

ここの代入時にエラー出てるようで、ソース追っかけると

JS

1 volume = Math.max(0, Math.min(1, volume)); 2 this._volume = volume; 3 if (this.src) { 4 this._gain.gain.value = volume; 5 }

ここのthis._gainundefinedなのが原因で(this.srcに値がある)
作られるのが

JS

1 play: function(dup) { 2 if (this._state === 1 && !dup) { 3 this.src.disconnect(); 4 } 5 if (this._state !== 2) { 6 this._currentTime = 0; 7 } 8 var offset = this._currentTime; 9 var actx = this.context; 10 this.src = actx.createBufferSource(); 11 if (actx.createGain != null) { 12 this._gain = actx.createGain(); 13 } else { 14 this._gain = actx.createGainNode(); 15 } 16

play関数時なのでplayやってから設定するといいのかな。

もしくはcore.bgm._volumeに代入するか(まああまりやってはいけないんだろうけど、playしないとボリューム設定できないのもおかしいし、直接代入してもいい気がする)

投稿2020/06/02 09:49

rururu3

総合スコア5545

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問