Q&A
前提
Javascriptでトランプゲームを作成していて、イカサマイベントを実装しています。
そこでイカサマClassを作成しイベントを発火させ、カードに触れられないようにクリックイベントを削除したいのですが、うまくいかないです。
トランプゲームは、
・メインのゲームの進行クラスであるmain.js
・イベントリスナーなどの汎用関数をまとめたUtil.js
・イベントハンドラ等があるikasama.js
・カードを選択するプレイヤークラス
カードを選択するメソッドはプレイヤークラスですが、それを実行するのはメインの進行クラスである、main.jsです。
このイベントを削除したいです。
発生している問題
特にエラーメッセージなどは出ていません。
検証ツールでデバックしてみると、removeEventListenerの「handler」にはイベントを登録したmain.jsのメンバメソッドが渡ってきているようでした。
this.clickEvent : ƒ #onClickCard() [[FunctionLocation]] : main.js:110
ソースコード(汎用関数)
util.js
1export default class Util { 2 /** 3 * 指定した時間だけ待つ(未指定の場合は1秒) 4 */ 5 static sleep = (wait = 1000) => { 6 return new Promise((resolve, reject) => { 7 setTimeout(() => resolve(), wait); 8 }); 9 }; 10 11 /** 12 * イベントハンドラの追加 13 */ 14 static addEventListener = (selector, event, handler) => { 15 document 16 .querySelectorAll(selector) 17 .forEach((e) => e.addEventListener(event, handler)); 18 }; 19 /** 20 * イベントハンドラを削除する 21 */ 22 static removeEventListener = (selector, event, handler) => { 23 document 24 .querySelectorAll(selector) 25 .forEach((e) => e.removeEventListener(event, handler)); 26 }; 27}
ソースコード(ゲームクラス)
main.js
1import Util from "./util.js"; 2import Player from "./player.js"; 3import Com from "./com.js"; 4import Card from "./card.js"; 5import Pair from "./pair.js"; 6import Ikasama from "./ikasama.js"; 7/** 8 * Gameクラス 9 */ 10export default class Game { 11 #you; //あなた(You) 12 #com; // コンピュータ 13 #cards; // 山札のカード 14 #isRunning; // ゲームの実行状態 15 /** 16 * コンストラクタ 17 */ 18 constructor() { 19 this.#you = null; 20 this.#com = null; 21 this.#cards = []; 22 this.#isRunning = false; 23 this.#setUpEvent(); 24 } 25 run() { 26 this.#initialize(); 27 } 28 /** 29 * ゲームの状態を初期化する 30 */ 31 #initialize() { 32 // ①プレイヤーを生成する 33 this.#you = new Player(".card.you"); 34 this.#com = new Com(".card.com"); 35 // ランダムイベントの抽選 36 if (Util.randomEvent(8)) { 37 this.#ikasamaActive(); 38 } 39 } 40 41 /** 42 * 手札のクリックイベントハンドラ 43 */ 44 #onClickCard() { 45 if (this.#isRunning) { 46 this.#you.selectCard(event.target); 47 } 48 } 49 /** 50 * イカサマウィンドウの振る舞い 51 */ 52 #ikasamaActive() { 53 // ウィンドウを表示する 54 Ikasama.displayWindow(); 55 // イカサマを実行する 56 Util.addEventListener("#intikiOn", "click", {player: this.#you, clickEvent: this.#onClickCard, handleEvent: Ikasama.destinyCard}); 57 // イカサマするのをやめる 58 Util.addEventListener("#intikiNo", "click", Ikasama.goodBye); 59 } 60 /** 61 * イベントハンドラを登録する 62 */ 63 #setUpEvent() { 64 Util.addEventListener(".card.you", "click", this.#onClickCard.bind(this)); 65 } 66} 67
player.js
1//...一部抜粋 2selectCard(node) { 3 node.classList.toggle("selected"); 4 };
ソースコード(イカサマクラス)
ikasama.js
1import Util from "./util.js"; 2 3export default class Ikasama { 4 /** 5 * イカサマの選択を迫る 6 */ 7 static displayWindow() { 8 document.querySelector('.ikasama').classList.add('active'); 9 } 10 /** 11 * イカサマを発動する 12 */ 13 static async destinyCard() { 14 document.querySelector(".ikasama").classList.remove("active"); 15 await Util.sleep(); 16 if(Util.randomEvent(4)) { 17 this.player.cards.forEach((card, index) => { 18 card.rank = 10 + index; 19 card.suit = 1; 20 card.index = 10 + index; 21 if(index === 4) card.index = 1; 22 }); 23 } else { 24 this.player.cards.forEach((card, index) => { 25 card.rank = 1 + index; 26 if((index + 1) % 2 === 0) card.rank = 5 + index; 27 card.suit = 1 + index; 28 if (index === 4) card.suit = 1; 29 switch (index) { 30 case 0: 31 card.index = 1; 32 break; 33 case 1: 34 card.index = 19; 35 break; 36 case 2: 37 card.index = 29; 38 break; 39 case 3: 40 card.index = 47; 41 break; 42 case 4: 43 card.index = 5; 44 break; 45 } 46 }); 47 } 48 this.player.sortCards(); 49 50 /** 51 * イベントリスナーを解除しようとしてうまく行かず保留。 52 * 試したこと:登録してある関数の参照を取得。mainメソッドで直接指定。 53 */ 54 Util.removeEventListener(".card.you", "click", this.clickEvent); 55 alert("自分のカードをすり替えました!!\n※このまま勝負してください。"); 56 }; 57}
以上です。
どうかよろしくお願いいたします。
回答1件
下記のような回答は推奨されていません。
このような回答には修正を依頼しましょう。