sakanaプログラマーの日記

プログラミングや金融関係について書くブログです。

jqueryでタイピングゲームを作成してみた

jqueryを覚えたのでタイピングゲームを作成してみた。

デザインはタイプウェルを参考にさせていただいています。(
http://www.twfan.com/
)

とりあえず動く程度のレベルなので、デザインとか機能とかはもっと改善したいところ。

動作確認したのはChoromeのみ

実装した機能


・タイマー

・ミス数表示

・入力したものは赤くなる

・入力文字表示枠

キーロガー

今後実装したい機能


・ミス時に通知する機能(音とか文字色変更とか)

・リザルト画面(単語ごとのタイムとかミスした箇所とか)

・再チャレンジ用のリセット機能

・あいまい入力対応("し"の場合 si or shi のどちらも可能にする。:これは難しそう)

・対象の単語を外部ファイルから読み込むようにする。

所感


グローバル変数使い過ぎな気もするのでちゃんとリファクタリングしたいなぁ

区切り文字を","にしたのはかなりセンスないorz

javascriptは初心者なので、書き方変だよとかあればコメントください。

使って遊びたい場合は、candidateWordとcreateWordsのforの数をいじれば、自分の好きなように設定できます。

typingGame.html

<!doctype html>
<html>
<head>
<script type="text/javascript" src=".\jquery.js"></script>
<script type="text/javascript" src=".\typingGame.js"></script>

</head>
<body style="width:100%; height:100%;">
<span class="start">    </span>
<input class="ready" type="button" onclick="start();" value="READY">
<span>Time</span>
<span class="time" ></span>
<span >miss:</span>
<span class="miss" >0</span>
<!-- 日本語欄 -->
<div class="textJp"> <span class="endInputJp" style="color:red"></span><span class="yetInputJp"></span></div>

<!-- 英語(ローマ字)欄 -->
<div class="textEn"> <span class="endInputEn" style="color:red"></span><span class="yetInputEn"></span></div>
<!--  入力欄 -->
<div class="inputareaJp" style="font-size:20px;"><span class="endInputareaJp">    </span><span class="nowInputareaJp" style="border:solid 1px;"> </span><span class="yetInputareaJp"></span></div>
<!--  ログ欄 -->
<div class="log"> 入力キー:</div>
</body>
</html>

typingGame.js

var isStart = false; // 準備後
var canKeyUp = false; // 入力可能状態
var isEnd = false; // 完了したかどうか
var Word = function(jp,en){  // 単語のコンストラクタ
	this.jp = jp;
	this.en = en; // ローマ字 日本語1文字につき[,]で区切る(最後も)
}
var words =[]; // タイピングする単語の配列

var candidateWord = [new Word("テスト","te,su,to,"), new Word("単語","tann,go,"), new Word("タイピング","ta,i,pi,nn,gu,")];
	
var dispJp; // 表示用の日本語
var dispEn; // 表示用の英語
var inputEn; // 入力用の英語


$(function(){
	var miss = 0;
	$("html").keyup(function(){
		var key = event.key;
		if(!isStart){
			if(key == " "){
				// スペースで開始する(クリックするとキーボードから手が離れるし)
				$(".ready").click();
			
			}
		}else{
			// カウントダウンが終わるまでは何もしない
			if(canKeyUp){
				// 開始後
				// ログ出力
				$(".log").append(key);
				
				// 正解のローマ字
				var okChar = dispEn.slice(0,1);
				
				if(key == okChar){
					// 正解の場合
					dispEn = dispEn.slice(1); // 先頭文字削除
					inputEn = inputEn.slice(1);
					$(".yetInputEn").text(dispEn);
					$(".endInputEn").append(okChar);
					
					// 日本語を1字入力完了した場合
					if(inputEn.slice(0,1) == ","){
						inputEn = inputEn.slice(1); // ,を削除
						$(".endInputJp").append(dispJp.slice(0,1)); // 先頭文字設定
						$(".endInputareaJp").text($(".endInputareaJp").text().slice(1) + dispJp.slice(0,1));
						
						dispJp = dispJp.slice(1); // 先頭文字削除
						$(".nowInputareaJp").text(dispJp.slice(0,1));
						$(".yetInputareaJp").text(dispJp.slice(1,6));
						$(".yetInputJp").text(dispJp);
						
						
					}
					// 完了時
					if(dispEn.length == 0){
						isEnd = true;
						alert("完了");
					}
				}else{
				 	// 不正解の場合
					miss++;
					$(".miss").text(miss);
				}
				
			}
		}
	});
});

/**
 * 開始処理を行う
 */
function start(){
	if(isStart){
		// 開始後はなにもしない
		return;
	}
	// readyボタンのオンクリック処理をなくす
	$(".ready").prop("disabled", true);
	isStart=true;
	var startCountdown = 3; // スタートするまでの秒数
	var countSpace = "    ";
	
	// 先にtyping対象を表示しちゃう
	createWords();
	dispJp = getDispJp();
	
	inputEn = getDispEn();
	dispEn = inputEn.replace(/,/g,""); // ,を消す

	$(".yetInputJp").text(dispJp);
	$(".yetInputEn").text(dispEn);
	$(".start").text(countSpace + startCountdown);
	$(".nowInputareaJp").text(dispJp.slice(0,1));
	$(".yetInputareaJp").text(dispJp.slice(1,6));// 表示枠は5文字とする
	setInterval(function(){
		if(!canKeyUp){
			startCountdown--;
			if(startCountdown > 0){
			
				
				$(".start").text(countSpace + startCountdown);
			}else{
				$(".start").text("  start");
				canKeyUp = true; // startしたので入力可能
				// タイマーを設定
				var startTime = new Date();
				$(".time").text(0);
				setInterval(function(){
					if(!isEnd){
						// 少数第一位まで表示
						var timems = new Date - startTime;
						$(".time").text(Math.floor((timems/1000)) + "." + Math.floor((timems/100)%10 ));
					}
				},100);
			}
		}
	},1000);
}

/**
 * タイピング対象の単語を作成する
 */
function createWords(){
	// テストなので5単語を出力する
	for(i = 0; i < 5; i++){
		// 入力候補からランダムで決める
		words.push(candidateWord[Math.floor(Math.random() * candidateWord.length)]);
	}
}

/**
 * タイピング対象の日本語をスペース区切りですべて取得する
 */
function getDispJp(){
	var dispStr ="";
	$.each(words, function(index,value){
	
		dispStr += value.jp + " ";
	});
	// 最後のスペースを削除
	dispStr = dispStr.slice(0, -1);
	return dispStr;
}

/**
 * タイピング対象の英語をスペース区切りですべて取得する
 */
function getDispEn(){
	var dispStr ="";
	$.each(words, function(index,value){
		dispStr += value.en + " ,";
	});
	dispStr = dispStr.slice(0, -1);
	return dispStr;
}