広告
JavaScriptを使ってオリジナルの単語タイピングゲームを作っていきます。
単語タイピングゲーム作りを通してリアルタイム入力、文字列の操作、タイマーによるプログラムの自動実行、簡単なアニメーションなど実践的なプログラミング技術を学んでいきます。
「JavaScriptでプログラミング入門」の応用編になりますので、まだ終えてない方はそちらを先にご覧ください。
今回は単語タイピングゲームを作っていきます。
複数文字の入力、打った文字の確認、問題の切り替えなどなど作っていきます。
まだ動きやら、ゲームオーバー判定やら、背景の切り替えやらはつけません。
このへんからプログラムが長くなるのでプログラムの全体は中間ソースで確認してください。
とりあえずレベルに合わせた問題を適当に用意しましょう。
var lv1_ary = [ "a","b","c","d","e", "f","g","h","i","j" ]; var lv2_ary = [ "act","add","age","bad","bag", "bar","bed","bee","bet","can" ]; var lv3_ary = [ "baby","bank","bear","bird","book", "foot","icon","land","liar","ship" ]; var lv_all_ary = [ lv1_ary, lv2_ary, lv3_ary ];
まだテストプログラムの段階なので少なめで大丈夫です。
レベルごとのそれぞれの配列をさらに配列に保存することにより、2次元配列として扱う事ができます。
上の例だと
lv_all_ary[0][0]・・・「a」
lv_all_ary[0][1]・・・「b」
lv_all_ary[1][2]・・・「age」
lv_all_ary[2][0]・・・「baby」
のようにアクセスできます。
今回使う変数を軽く紹介します。
あとでその都度説明しますので、今はなんとなく頭に入れておいてください。
var init_flag;/*初期化用のフラグ*/ var mistake_flag;/*打ち間違えた時用のフラグ*/ var ary_length;/*配列の要素数を保存*/ var str_length;/*問題の文字数を保存*/ var key_code;/*入力されたキーコードを保存*/ var ransuu;/*乱数を保存*/ var moji_point;/*その時何文字目かを保存*/ var input_mondai;/*入力された単語を保存*/ var lv;/*問題のレベル*/ var i;/*forループ用*/ var mondai_code_ary = [];/*問題の文字コードを保存*/
のようになります。
今回作る単語タイピングゲームは
初期画面
↓
何かキーを押したらスタート
↓
問題の入力
↓
正誤判定で一回停止
↓
何かキーを押したら再びスタート
のような流れでゲームを進行したいので、それを実現するためのプログラムの流れを変えるテクニックをご紹介します。
プログラムの分岐ごとにalert命令を入れておくので
「今プログラムがどこを流れているのか?」
この点に注目しつつプログラムを確認してみてください。
<html> <head> <script> var init_flag; function my_init(){ init_flag = 0; document.onkeydown = my_get_key; alert("最初の初期化"); } function my_init2(){ init_flag = 0; alert("2回目以降の初期化"); } function my_set_mondai(){ alert("問題セット!"); } function my_get_key(){ if(init_flag == 0){ my_set_mondai(); init_flag = 1; } else{ my_init2(); } } </script> <title>プログラムの流れ確認プログラム</title> </head> <body onload="my_init()"> <p>キーを押すたびにプログラムの流れが変わります</p> </body> </html>
キーを押すたびに実行される「alert」が異なるのを確認できるかと思います。
今回のプログラムでは「init_flag」という変数の値でプログラムを分岐させるようにしております。
いわゆるフラグってやつです。
今からプログラムの流れをトレースして(なぞって)いきますので「init_flag」の値に注目しながらプログラムと見比べてみてください。
1・ページを開くと「body onload」により関数「my_init()」が実行される。
「init_flag」の値は「0」へ
↓
2・何かキーを押すと「my_get_key()」内の「init_flag == 0」の流れが実行されるので、そこで「my_set_mondai()」を実行、その中のalertが実行される。
「init_flag」の値は「1」へ
↓
3・何かキーを押すと「my_get_key()」内の「init_flag == 1」の流れが実行されるので、そこで「my_init2()」を実行、その中のalertが実行される。
「init_flag」の値は「0」へ
↓
4・2へ戻る
なんとなく伝わりましたでしょうか?
繰り返しますが
「今プログラムがどこを流れているのか?」
これを想像しながらプログラミングしていく事が大事です。
では中身をひとつひとつ作っていきます。
function my_init(){ init_flag = 0; mistake_flag = 0; lv = 2; ary_length = lv_all_ary[lv - 1].length; key_code = 0; ransuu = 0; moji_point = 0; input_mondai = ""; i = 0; document.onkeydown = my_get_key; }
一番最初に一回だけ実行される変数などの初期化部分です。
主なトコロだけ説明します。
lv = 2;
問題のレベル用の変数です。
今回はレベルを固定するのでここで決めた値で読み込む配列を決定します。
ひとまずレベル「2」にしてありますので、必要に応じて他のレベルも試してみてください。
ary_length = lv_all_ary[lv - 1].length;
「ary_length」には配列の要素数が保存されます。
「文字列.length」で文字数を取得できる事を説明しましたが、それを配列に使う事で配列の要素数(その配列にいくつの要素が入っているのか)を得る事ができます。
例えば
var mondai = ["apple","bag","cat","day","eleven","face"];
こんな配列があったとして
mondai[0].length・・・「5」
これだと最初の要素「apple」の文字数が取得できますが、
mondai.length・・・「6」
このように配列番号を省略すると、その配列の全体の要素数を取得する事ができます。
2次元配列の場合は(ページ冒頭の2次元配列と見比べながら確認してください)
lv_all_ary[1][2].length・・・「3」
のように最後まで指定するとそこに保存されている要素の文字数が取得できて
lv_all_ary[1].length・・・「10」
のように配列番号を一つだけ指定すると、そこに保存されてる配列の要素数が取得できます。
この値をもとに問題用の乱数を得ます。
このことによってレベルごとの問題数が異なった場合でも対応できるようになります。
input_mondai = "";
入力された単語を保存する変数です。
文字列を保存する変数の場合、何も値が決まってなければこのように「""」ダブルクォーテーションで囲って初期化します。
document.onkeydown = my_get_key;
「document.onkeydown」はプログラム中どこかで一度実行されていれば大丈夫なので初期化時に実行しております。
残りは普通に初期化しているだけです。
広告
続きまして問題を出題していきます。
function my_set_mondai(){ ransuu = Math.floor(Math.random() * ary_length); str_length = lv_all_ary[lv - 1][ransuu].length; for(i = 0;i < str_length;i++){ mondai_code_ary[i] = lv_all_ary[lv - 1][ransuu].charCodeAt(i); } }
先ほどの「ary_length」を使って乱数を取得、その時の問題の文字数を取得していきます。
ransuu = Math.floor(Math.random() * ary_length); str_length = lv_all_ary[lv - 1][ransuu].length;
これで「str_length」に問題の文字数が保存されたので「for」ループでその文字数分だけ一文字一文字、文字コードへと変換して配列「mondai_code_ary」に保存していきます。
for(i = 0;i < str_length;i++){ mondai_code_ary[i] = lv_all_ary[lv - 1][ransuu].charCodeAt(i); }
「charCodeAt(何文字目か)」こちらで文字列の何文字目かを指定して文字コードに変換する事ができます。
問題の表示と不必要な部分のクリアなどを行います。
function my_set_stage(){ /*入力された単語をクリア*/ document.getElementById("input_mondai_box").innerHTML = ""; /*問題を表示*/ document.getElementById("mondai_box").innerHTML = lv_all_ary[lv - 1][ransuu]; /*正誤部分をクリア*/ document.getElementById("marubatu_box").innerHTML = "結果:"; }
今回正誤の結果を表示するのに簡単に「marubatu_box」という「div」を設置しました。
あとはコメントの通りですね。
では問題の出題と画面表示ができたので、入力を受け取り判定していきます。
ちょっとプログラムが長いので主な部分だけ説明します。
中間ソースに従って、「my_set_mondai」、「my_set_stage」などを設置したら
if(key_code == mondai_code_ary[moji_point] - 32){ /*合っている場合*/ moji_point++; } else{ /*間違っている場合*/ mistake_flag = 1; }
判定部分です!
複数文字になるので少し複雑になると思いきや、以外にシンプルです。
あらかじめ配列「mondai_code_ary」に一文字ずつ分解した問題が文字コードのカタチで入っているので、「現在何文字目が入力されているのか?」を変数「moji_point」で調整しつつ比べるだけです。
お尻の「-32」は一文字タイピングゲームでもやった文字コードとの差分ですね。
前は「65」だったぞ!と気になっちゃう方は「mondai_code_ary」の中身などを確認してみてください。
続きましてその中身の処理ですね。
input_mondai = input_mondai + String.fromCharCode(key_code + 32);
入力された文字を一文字ずつつなげるカタチで「input_mondai」に保存していきます。
「String.fromCharCode」で文字コードから文字へと変換できます。
あとはそれを表示して、合っている場合は「moji_point++」で入力を続けてもらい、間違っている場合は「mistake_flag = 1」にして不正解へと分岐します。
if(mistake_flag == 1){ /*不正解*/ my_init2(); } else if(moji_point == str_length){ /*正解*/ my_init2(); }
正解・不正解の分岐です。
「mistake_flag == 1」ならその場で不正解、間違えずに「moji_point == str_length」最後の文字まで到達できれば正解ですね。
最後に必要な変数を再初期化して問題出題の流れへと復帰します。
function my_init2(){ init_flag = 0; mistake_flag = 0; key_code = 0; moji_point = 0; input_mondai = ""; }
それぞれのフラグなどを再初期化します。
単語タイピングゲームの完成です!
ここまでの中間ソースになります。
中間ソース2の状態で続けて作っていくと問題が左端に隠れてしまうかもしれないので、「mondai_box」の「left」をお好みで調整してください。
まだゲームオーバーを設置してないので永遠に問題が出続けます。
あきたらページを閉じてあげてください。
次回は動きとゲームオーバーを加えます。
広告
Copyright 2016 K.N/petitetech.com