Japanese (日本語) translation by Hakima Madani (you can also view the original English article)
私の以前のキーボードコンボの検出のチュートリアルから始めて、私たちはあなたのタイピングスキルをテストする完全なゲームを構築する方法を見るでしょう。
最終結果のプレビュー
に向けて取り組んで最終結果を見てをみましょう。
英語の単語を入力するのに、画面上の文字を使用!無効なワード ポイントを失う、従って見なさい。
ステップ 1: 導入
このチュートリアルでは、この非常に便利なCombo Detection classを使用して、非常に素晴らしいタイピングゲームを開発します。 あなたがそのクラスが我々のゲームの間に何をするであろうかを理解するように、あなたがここに続ける前にあなたがそのチュートリアルを読むことを強く勧めます。
私たちのゲームで、画面に多くのブロックの手紙を持って、プレイヤーは、文字のブロックで形成された単語を入力します。 その単語が有効な場合、ブロックが削除され、プレーヤーはポイントを再生するより多くの時間を取得します。時間がゼロになったら、ゲームは終了します。
完全にこのチュートリアル次のようにする場合は、ソース ファイルをつかむ必要があります。
ステップ 2: Flash Professional のイメージを追加します。
前述のチュートリアルで説明したように、ゲーム用のすべての画像をFlash Professionalの.flaファイルに追加してから、.swcファイルを生成します。これをFlashDevelopプロジェクトに追加して使用します。
このチュートリアルでは、背景画像(素晴らしい木製の背景のPetr Kovarに感謝します)、選択されたフレームと現在入力されているキーボックスを含む一般的なブロック画像が必要です。 あなたは私たちのソースファイルで設定されたすべてを見つけることができます。








同様に、プリローダーと画面にゲームなどの他の画像が追加されますが、これらになりますチュートリアルの間そうより理にかなってので。
ステップ 3: LetterBlock
我々 は我々 のコードで作業を開始することができます、私たち FlashDevelop プロジェクトを設定しましょう。この 1 つは、プリローダーと AS3 プロジェクトである、だから FlashDevelop でそのオプションを選択する予定です! combos tutorialを読んだことを前提として、FlashDevelopのライブラリに.swcファイルを追加する方法を知っているでしょう。 そうしない場合、ちょうどそれを右クリックし、「ライブラリに追加」を選択します。ソースから .swc ファイルを取得し、それを追加します。それです。処置の時間!
私たちの手紙のブロックは、それとステップ 2 に示したブロック画像のテキスト フィールドを持つ単純なオブジェクトになります。コーディングは簡単です。LetterBlock
クラスを作成します。
package { import ArtAssets.LetterBlockImage; import flash.display.MovieClip; import flash.display.Sprite; import flash.text.TextField; import flash.text.TextFormat; import flash.text.TextFormatAlign; public class LetterBlock extends Sprite { private var _image:MovieClip; private var _letterText:TextField; public function LetterBlock() { _image = new LetterBlockImage(); _image.stop(); _letterText = new TextField(); _letterText.defaultTextFormat = new TextFormat("Verdana", 40, 0xFFFFFF, true, null, null, null, null, TextFormatAlign.CENTER); _letterText.width = 60; _letterText.x = -30; _letterText.y = -26.3; _letterText.selectable = false; _letterText.multiline = false; addChild(_image); addChild(_letterText); } public function setLetter(letter:String):void { _letterText.text = letter; } } }
行 21 28 画面上の位置し同様、我々 の文字のテキストを保持するテキスト フィールドを作成し、フォント、フォントの色、サイズ、それを与えます。ボックスの文字を設定する setLetter
関数を使用のみ。
ステップ 4: 単語を読み込み
すべてのタイピング ゲームでは、単語で動作する必要があります。この手順では、[Embed]
タグを外部ファイルをロードし、ファイルのデータを使用します。明らかに、このファイルには、私たちのゲームで使用される言葉が含まれています。 ソース ファイルで利用可能です。また、この手順ではまず、ComboHandler
クラスを使用するので同様に FlashDevelop プロジェクトで追加!
いくつかのコードを見てみましょう。
Main.as: で
private function init(e:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, init); ComboHandler.initialize(stage); DictionaryWords.loadWords(); }
5 上記の行は、必要に応じて、ComboHandler
を初期化します、7 行目は DictionaryWords
クラスの loadWords()
メソッドを呼び出します。このクラスは、作成者し、そのコードです。
package { public class DictionaryWords { [Embed(source = "../src/Words.txt", mimeType = "application/octet-stream")] private static var _Words:Class; public static function loadWords():void { var words:String = new _Words(); var wordsArray:Array = words.split("\n"); var i:int; var length:int = wordsArray.length; for (i = 0; i < length; i++) { ComboHandler.registerCombo(wordsArray[i], turnIntoLetters(wordsArray[i])); } } private static function turnIntoLetters(word:String):Array { var letters:Array = word.split(""); if (letters[0] == "") { letters.shift(); } if (letters[letters.length - 1] == "") { letters.pop(); } var i:int; for (i = 0; i < letters.length; i++) { letters[i] = String(letters[i]).charCodeAt(0); } return letters; } } }
5行目は、コンパイル時に外部ファイルをロードしてゲームに入れる行です。 [Embed]
タグがあるため、これはすべて可能です。 あなたがそれについてもっと情報が欲しいならば、私はAdobe Livedocsのこの素晴らしい記事を推薦します。
働いているものを見ることができますので、Words.txt のセクションがあります。
ABBREVIATOR ABC ABCOULOMB ABCS ABDIAS ABDICABLE ABDICATE ABDICATION ABDICATOR ABDOMEN ABDOMINAL ABDOMINOCENTESIS ABDOMINOPLASTY
12行目(DictionaryWords.asの)は非常に重要な行です。 基本的には、String
に格納されていたWords.txtのすべての単語をArrayの要素に変換します。 各単語は改行文字で区切られているので、あとはString
クラスのsplit()
メソッドを呼び出すだけで済みます。
turnIntoLetters
関数は、単語を各文字のキーコードを含む Array
に変換するだけです。 そのようにして、私たちのComboHandler
クラスはそれを扱うことができます。
手順 5: 文字のブロックを画面に追加します。
ゲームの準備ができて私たちの言葉があるので、画面に文字を置く作業を開始する時間です。これは非常に簡単です。まず第一に、我々 はゲーム画面を必要があります。GameScreen
クラス私たちのゲームのすべてのロジックが含まれます。
package { import ArtAssets.BackgroundImage; import flash.display.Sprite; import adobe.utils.CustomActions; public class GameScreen extends Sprite { private var _background:BackgroundImage; private var _blocksOnScreen:Vector.<LetterBlock>; public function GameScreen() { _background = new BackgroundImage(); _background.x = 275; _background.y = 200; addChild(_background); _blocksOnScreen = new Vector.<LetterBlock>(); populateBlocks(); } private function populateBlocks():void { var i:int; var tempBlock:LetterBlock; for (i = 0; i < 8; i++) { tempBlock = new LetterBlock(); tempBlock.x = 130 + ((i % 4) * 95); tempBlock.y = 80 + int(i / 4) * 80; tempBlock.setLetter(randomLetter()); addChild(tempBlock); _blocksOnScreen.push(tempBlock); tempBlock = null; } } private function randomLetter():String { return String.fromCharCode((int(Math.random() * 26) + 65)); } } }
_BlocksOnScreen
ベクトルはこのコードの主要な要素: 作業中にいつでも私たちをことができ、画面上のすべてのブロックが含まれます。行 14 に追加、BackgroundImage
.swc ファイルからグラフィックは、画面上に注意してください。
PopulateBlocks()
関数の内部で我々 の行うことは特定の位置に新しい LetterBlock
を追加し、(これは randomLetter()
関数によって生成されます) ランダムな文字を付けて画面に追加。
それでは、Main
の子にゲーム画面を追加する必要があります。 Main.asの内側:
private var _gameScreen:GameScreen; private function init(e:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, init); ComboHandler.initialize(stage); DictionaryWords.loadWords(); _gameScreen = new GameScreen(); addChild(_gameScreen); }
プロジェクトをコンパイルし、画面上のブロックを参照してくださいすることができます!
ステップ 6: キーを押した後、ブロックを選択します。
私たちのゲームでは、その対応するキーが押されたとき、その「選択」イメージに行きブロックをします。これは非常に簡単です。LetterBlock.as ファイルに移動し、このコードを追加します。
private var _selected:Boolean; public function select():void { _selected = !_selected; _image.gotoAndStop(_selected == true ? "Selected" : "Unselected"); } public function get letter():String { return _letterText.text; } public function get selected():Boolean { return _selected; }
_Selected
変数は、ブロックを選択するかどうかをチェックするゲームのロジックで使用されます。同じはletter
で発生します。
残っているすべては今「選択」と「未選択」切り替えるブロックをすることです。内側の GameScreen.as:
import flash.events.Event; import flash.events.KeyboardEvent; // ** snip ** public function GameScreen() { _background = new BackgroundImage(); _background.x = 275; _background.y = 200; addChild(_background); _blocksOnScreen = new Vector.<LetterBlock>(); populateBlocks(); addEventListener(Event.ADDED_TO_STAGE, onStage); } private function onStage(e:Event):void { removeEventListener(Event.ADDED_TO_STAGE, onStage); stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); } private function onKeyDown(e:KeyboardEvent):void { var i:int; for (i = 0; i < _blocksOnScreen.length; i++) { if (_blocksOnScreen[i].letter == String.fromCharCode(e.keyCode) && !_blocksOnScreen[i].selected) { _blocksOnScreen[i].select(); break; } } }
KeyboardEvent
リスナーをステージに追加する必要があることを考えて、GameScreen
のコンストラクターで、Event.ADDED_TO_STAGE
のリスナーを追加します。これにより、onStage()
関数に進みます。 この関数はリスナーをステージに追加します。 OnKeyDown()
関数は、私たちのすべてのブロック画面に行くと押された文字で任意のブロックがあるかを確認します。もしそうなら、我々 は行 36 で行われている、それを選択必要があります。
プロジェクトをコンパイルする、これは何を得るです。
(キーボードのキーを押します!)
ステップ 7: ComboHandler クラスに変更
たい私たちのゲームに方法を働かせるためには、前のチュートリアルから ComboHandler
クラスにいくつかの変更を行う必要があります。 最初の変更は、入力ユーザーが停止したときのみコンボを確認できるようにすることです。これは、MAX_INTERVAL
定数し、update()
関数を通じて検出されます。 また、ユーザーが""それを完了するために厳密な単語を入力して以来、どのように我々 はコンボ pressedKeys
配列内のキーに一致する場合を確認して変更します。 最終更新はも単語が入力されたときに、イベントを送信するが間違っています。私たちのゲームにプレイヤーの間違いを検出し、そのために彼を処罰できるようになります。
以下すべてのコードは、説明したものを行います。
内側の ComboHandler.as:
private static const MAX_INTERVAL:int = 500; // Milliseconds private static var checkComboAfterClearing:Boolean; public static function initialize(stageReference:Stage, checkComboAfterClearing:Boolean = false):void { combos = new Dictionary(); interval = 0; dispatcher = new EventDispatcher(); ComboHandler.checkComboAfterClearing = checkComboAfterClearing; pressedKeys = []; stageReference.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); } private static function onKeyDown(e:KeyboardEvent):void { if (getTimer() - interval > MAX_INTERVAL) { pressedKeys = []; } interval = getTimer(); pressedKeys.push(e.keyCode); if (!checkComboAfterClearing) { checkForCombo(); } } public static function update():void { if (getTimer() - interval > MAX_INTERVAL) { checkForCombo(); pressedKeys = []; } } private static function checkForCombo():void { if (pressedKeys.length == 0) { return; } var i:int; var comboFound:String = ""; for (var comboName:String in combos) { if ((combos[comboName] as Array).length == 0) { continue; } if (pressedKeys.join(" ") == (combos[comboName] as Array).join(" ")) { comboFound = comboName; break; } } // Combo Found //if (comboFound != "") //{ //pressedKeys = []; dispatcher.dispatchEvent(new ComboEvent(ComboEvent.COMBO_FINISHED, {comboName: comboFound} )); //} }
我々 は、ユーザーが入力を停止した後にのみ私たちのコンボのためのチェックをできるようにする、ComboHandler のコンス トラクター宣言を変更しました。 これは、MAX_INTERVAL
定数を使用して、update()
関数で検証します。また、チェックより適切なコンボを使用する checkForCombo()
関数を変更されています。
今、また GameScreen
クラス ComboHandler
クラスの更新は変更する必要があります。
public function GameScreen() { _background = new BackgroundImage(); _background.x = 275; _background.y = 200; addChild(_background); _blocksOnScreen = new Vector.<LetterBlock>(); populateBlocks(); addEventListener(Event.ADDED_TO_STAGE, onStage); addEventListener(Event.ENTER_FRAME, gameLoop); } private function gameLoop(e:Event):void { ComboHandler.update(); }
この更新プログラムは、シンプルで良いアプローチだから Event.ENTER_FRAME
イベント リスナーを介して行われています。
最後の変更は、Main
クラス内でComboHandler
クラスを初期化する方法を変更することです。
private function init(e:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, init); ComboHandler.initialize(stage, true); DictionaryWords.loadWords(); _gameScreen = new GameScreen(); addChild(_gameScreen); }
ゲームをコンパイルすると、これは何を得るです。
ステップ 8: Word ボックスの追加
プレイヤーに依存する他の何かを与えるために時間です。今、プレーヤーできません既に入力された文字のシーケンスを参照してください、それではゲームの [単語] ボックスを追加します。 このボックスは、順序、主催、現在型指定された文字を含む、コンボ イベントを受信したときに消去されます。WordBox
クラスを作成し、このコードを追加します。
package { import ArtAssets.TypedLettersBoxImage; import flash.display.Sprite; import flash.text.TextField; import flash.text.TextFormat; import flash.text.TextFormatAlign; public class WordBox extends Sprite { private var _image:Sprite; private var _textField:TextField; public function WordBox() { _image = new TypedLettersBoxImage(); _textField = new TextField(); _textField.defaultTextFormat = new TextFormat("Verdana", 30, 0xFFFFFF, true, null, null, null, null, TextFormatAlign.CENTER); _textField.width = 500; _textField.x = -250; _textField.y = -25; _textField.selectable = false; _textField.multiline = false; _textField.text = ""; addChild(_image); addChild(_textField); } public function addLetter(letter:String):void { _textField.appendText(letter); } public function clear():void { _textField.text = ""; } } }
このクラスはLetterBlock
クラスとほとんど同じです。したがって、詳しい説明は必要ありません。 注目に値する唯一のものは35行目です。ここにはString
クラスからappendText()
メソッドへの呼び出しが含まれています。 この関数は、単語] ボックスの現在のテキストの末尾に型指定された文字を常に表示させる、現在のテキストの末尾にテキストを追加します。
今、ゲームで、[単語] ボックスを追加する時間です。GameScreen.as に移動し、このコードを追加します。
private var _wordBox:WordBox; public function GameScreen() { _background = new BackgroundImage(); _background.x = 275; _background.y = 200; addChild(_background); _blocksOnScreen = new Vector.<LetterBlock>(); populateBlocks(); _wordBox = new WordBox(); _wordBox.x = 275; _wordBox.y = 350; addChild(_wordBox); addEventListener(Event.ADDED_TO_STAGE, onStage); addEventListener(Event.ENTER_FRAME, gameLoop); } private function onKeyDown(e:KeyboardEvent):void { var i:int; for (i = 0; i < _blocksOnScreen.length; i++) { if (_blocksOnScreen[i].letter == String.fromCharCode(e.keyCode) && !_blocksOnScreen[i].selected) { _blocksOnScreen[i].select(); _wordBox.addLetter(_blocksOnScreen[i].letter); break; } } }
1、15-17、19 号線は、word ボックスを作成し、画面上に置きます。行 36 は、ボックスに文字を追加するには、addLetter()
関数を呼び出しています。
この手順の結果は、以下です。次の手順で word ボックスをオフにするコードを追加します。
私たちの ComboHandler と私たち GameScreen 統合手順 9。
右ここで、ComboHandler
で行われている変更のみのみ変更とコンボをチェックする方法。これはどこが面白い部分です: 我々 は、ゲームで私たちの ComboHandler
を統合します。 これは、私たちの ComboHandler
は、実行するために GameScreen
に依存を意味します。レッツのコードにジャンプし、それの後の説明を参照してください!
内側の GameScreen.as:
public function GameScreen() { _background = new BackgroundImage(); _background.x = 275; _background.y = 200; addChild(_background); _blocksOnScreen = new Vector.<LetterBlock>(8); populateBlocks(); _wordBox = new WordBox(); _wordBox.x = 275; _wordBox.y = 350; addChild(_wordBox); addEventListener(Event.ADDED_TO_STAGE, onStage); addEventListener(Event.ENTER_FRAME, gameLoop); ComboHandler.dispatcher.addEventListener(ComboEvent.COMBO_FINISHED, onWordFinished); ComboHandler.setGameInstance(this); } private function onWordFinished(e:ComboEvent):void { _wordBox.clear(); } public function isKeyAvailable(key:String):Boolean { var i:int; for (i = 0; i < _blocksOnScreen.length; i++) { if (_blocksOnScreen[i].letter == key && !_blocksOnScreen[i].selected) { return true; } } return false; } private function populateBlocks():void { var i:int; var tempBlock:LetterBlock; for (i = 0; i < 8; i++) { tempBlock = new LetterBlock(); tempBlock.x = 130 + ((i % 4) * 95); tempBlock.y = 80 + int(i / 4) * 80; tempBlock.setLetter(randomLetter()); addChild(tempBlock); _blocksOnScreen[i] = tempBlock; tempBlock = null; } }
GameScreen
のコンス トラクターの内部は、ComboHandler
の dispatcher オブジェクトにイベントリスナーを追加し、そのクラスの下に追加されます) の setGameInstance()
関数を呼び出した。これは、ComboHandler
クラスにゲーム画面の現在のインスタンスを与え、word ボックスをオフにします。
また、作成した isKeyAvailable
関数です。これは押されたキーのリストにキーを追加することができるかどうかを確認するコンボ ハンドラー内で呼び出されます。
63 行目はコンス トラクターで _blocksInScreen
で行う変更を修正するだけです。
ComboHandler.as 中に追加するコードを見てみましょう。
private static var gameInstance:GameScreen; public static function setGameInstance(gameInstance:GameScreen):void { ComboHandler.gameInstance = gameInstance; } private static function onKeyDown(e:KeyboardEvent):void { if (getTimer() - interval > MAX_INTERVAL) { pressedKeys = []; } if (gameInstance.isKeyAvailable(String.fromCharCode(e.keyCode))) { interval = getTimer(); pressedKeys.push(e.keyCode); } if (!checkComboAfterClearing) { checkForCombo(); } }
強調表示された行には、ゲーム画面のインスタンスの ComboHandler
クラスに格納されている isKeyAvailable()
への呼び出しを追加します。これはゲームとコンボ ハンドラー間の統合の終わりです。
コンパイルすると、間隔が経過した後ゲームが今、[単語] ボックスをクリアに気づくでしょう。
ステップ 10: 法と単語が入力されて
この手順で行いますゲーム取るいくつかのアクション単語が検出されたとき。まず第一に、我々 は知っている単語が検出されたときに必要があります。どのようにを見つけてこと。
内側の GameScreen.as:
public function GameScreen() { _background = new BackgroundImage(); _background.x = 275; _background.y = 200; addChild(_background); _blocksOnScreen = new Vector.<LetterBlock>(8); populateBlocks(); _wordBox = new WordBox(); _wordBox.x = 275; _wordBox.y = 350; addChild(_wordBox); addEventListener(Event.ADDED_TO_STAGE, onStage); addEventListener(Event.ENTER_FRAME, gameLoop); ComboHandler.dispatcher.addEventListener(ComboEvent.COMBO_FINISHED, onWordFinished); ComboHandler.setGameInstance(this); } private function onWordFinished(e:ComboEvent):void { if (e.params.comboName != "") { removeSelectedLetters(); populateBlocks(); _wordBox.clear(); } } private function removeSelectedLetters():void { var i:int; for (i = 0; i < 8; i++) { if (_blocksOnScreen[i].selected) { removeChild(_blocksOnScreen[i]); _blocksOnScreen[i] = null; } } } private function populateBlocks():void { var i:int; var tempBlock:LetterBlock; for (i = 0; i < 8; i++) { if (_blocksOnScreen[i] == null) { tempBlock = new LetterBlock(); tempBlock.x = 130 + ((i % 4) * 95); tempBlock.y = 80 + int(i / 4) * 80; tempBlock.setLetter(randomLetter()); addChild(tempBlock); _blocksOnScreen[i] = tempBlock; } tempBlock = null; } }
23 ComboEvent.COMBO_FINISHED
のイベント リスナーがあります。単語が形成されているたびに、またはプレーヤーが欠場しているときに発生します。 あなたは ComboHandler.as に戻るときプレーヤーはミス、コンボ火力のイベント内での名前が、null になります気づくまたは""。 そのため私たちはライン 28-34 のチェックを行います。RemoveSelectedLetters()
関数が呼び出されたとき、プレーヤーは単語を形成してから選択したすべての文字が削除されます。 我々 はまただけどこにブロックがない - これに合うブロックを削除する関数の内部で何をやっている場所で新しいブロックを配置する populateBlocks()
関数を変更しました。
ゲームをコンパイルし、これは結果です。
ステップ 11: 何かプレイヤーが間違った単語を入力したとき
ときにプレーヤーが単語をミスしなければ何の任意のアイデアを持っていますか? 私は入力ミスの単語から選択した文字を変更する 30% のチャンスを与えることと同様、(後の手順で実行されます) プレーヤーから時間と得点を奪うに考えていた。以下のコードはまさに後者。GameScreen.as に移動します。
private function onWordFinished(e:ComboEvent):void { if (e.params.comboName != "") { removeSelectedLetters(false); } else { removeSelectedLetters(true); } populateBlocks(); _wordBox.clear(); } private function removeSelectedLetters(wasFromFailure:Boolean):void { var i:int; for (i = 0; i < 8; i++) { if (_blocksOnScreen[i].selected) { if ((wasFromFailure && Math.random() < 0.3) || !wasFromFailure) { removeChild(_blocksOnScreen[i]); _blocksOnScreen[i] = null; } else { _blocksOnScreen[i].select(); } } } }
5行目と9行目を見る前に、25行目にジャンプしましょう。この行で、wasFromFailure
は、ゲームが(Math.random()
によって)30%の確率で "計算"するかブロックを置き換えるかを定義する変数です。 そしてこの値がどのように渡されるか。5行目と 9 を見て: 単語の名前が nothing する場合または""、つまり、プレーヤーは、true
は removeSelectedLetters()
に忠実に渡す必要がありますを意味する言葉を欠場しています。
プロジェクトをコンパイルし、間違った単語を入力してみてください!
ステップ 12: スコアを追加します。
今、ゲームでスコアを追加する時間だ!最初に、イメージの作成、画面の上に置きます。次のステップでは、プレイヤーにスコアをさせていただきます。スコア、我々 はスコア クラスを作成する必要があります、これはそれのためのコード。
package { import flash.display.Sprite; import flash.text.TextField; import flash.text.TextFormat; import flash.text.TextFormatAlign; public class Score extends Sprite { private var _text:TextField; private var _score:int; public function Score() { _text = new TextField(); _text.defaultTextFormat = new TextFormat("Verdana", 40, 0xFFFFFF, true, null, null, null, null, TextFormatAlign.CENTER); _text.width = 500; _text.selectable = false; _text.multiline = false; addChild(_text); _score = 0; _text.text = "Score: " + _score.toString(); } public function addToScore(value:int):void { _score += value; _text.text = "Score: " + _score.toString(); } } }
それについて言っても過言ではない - 我々 はすでに前にこの 2 回のようなテキストを行っていると思います。今画面にこのスコアを追加する必要があります。内側の GameScreen.as:
private var _score:Score; public function GameScreen() { _background = new BackgroundImage(); _background.x = 275; _background.y = 200; addChild(_background); _blocksOnScreen = new Vector.<LetterBlock>(8); populateBlocks(); _wordBox = new WordBox(); _wordBox.x = 275; _wordBox.y = 350; addChild(_wordBox); _score = new Score(); _score.x = 25; _score.y = 210; addChild(_score); addEventListener(Event.ADDED_TO_STAGE, onStage); addEventListener(Event.ENTER_FRAME, gameLoop); ComboHandler.dispatcher.addEventListener(ComboEvent.COMBO_FINISHED, onWordFinished); ComboHandler.setGameInstance(this); }
さあ行こう。プロジェクトをコンパイルし、スコアを見ることができるようになりました!
ステップ 13: を付けて、得点を取る
今ではスコアを既に画面に追加すると、すべての我々 は彼は単語を完了すると、プレイヤーにスコアを与えるし、彼はそれを逃すときにスコアを奪います。GameScreen.as のコード:
private function removeSelectedLetters(wasFromFailure:Boolean):void { var i:int; var count:int = 0; for (i = 0; i < 8; i++) { if (_blocksOnScreen[i].selected) { count++; if ((wasFromFailure && Math.random() < 0.3) || !wasFromFailure) { removeChild(_blocksOnScreen[i]); _blocksOnScreen[i] = null; } else { _blocksOnScreen[i].select(); } } } if (wasFromFailure) { _score.addToScore( -(count * 10)); } else { _score.addToScore(count * 30); } }
それは非常に簡単で、あなたが見ることができる: プレーヤー、単語の文字数の 30 倍を与える行い入力ミスの単語の文字の数の 10 倍を奪います。コンパイル済みのゲームはテストの下です。
手順 14: タイマーを追加します。
タイマーを追加するスコアとほぼ同じものになります。1 つだけ違いがあります: タイマーは常に更新する必要があります、タイマーは別のテキストを持っています。Timer.as 以下のコードを見てみましょう。
package { import flash.display.Sprite; import flash.text.TextField; import flash.text.TextFormat; import flash.text.TextFormatAlign; public class Timer extends Sprite { private var _text:TextField; private var _value:int; public function Timer() { _text = new TextField(); _text.defaultTextFormat = new TextFormat("Verdana", 20, 0xFF0000, true, null, null, null, null, TextFormatAlign.LEFT); _text.width = 200; _text.selectable = false; _text.multiline = false; addChild(_text); _value = 30; _text.text = "Time: " + timeString(); } private function timeString():String { var minutes:int = _value / 60; var seconds:int = _value % 60; return minutes.toString() + ":" + seconds.toString(); } public function addToTime(value:int):void { _value += value; _text.text = "Time: " + timeString(); } } }
あなたは、33、35、37 線に気づいているかもしれませんが、タイマーのテキストの違いをつくっています。それは、分および秒で構成されます。 そのため作業に、_value
は秒で、ゲームの残り時間になります。今すぐ GameScreen.as で、タイマーを追加するコード:
private var _timer:Timer; public function GameScreen() { _background = new BackgroundImage(); _background.x = 275; _background.y = 200; addChild(_background); _blocksOnScreen = new Vector.<LetterBlock>(8); populateBlocks(); _wordBox = new WordBox(); _wordBox.x = 275; _wordBox.y = 350; addChild(_wordBox); _score = new Score(); _score.x = 25; _score.y = 210; addChild(_score); _timer = new Timer(); addChild(_timer); addEventListener(Event.ADDED_TO_STAGE, onStage); ComboHandler.dispatcher.addEventListener(ComboEvent.COMBO_FINISHED, onWordFinished); ComboHandler.setGameInstance(this); }
コードで必要な説明がない、だからコンパイル ボタンを押すし、タイマーを見てみましょう!
しかし、それではないカウント ダウンですか?それをしましょう!
ステップ 15: 減少して残り時間が増加
前の手順で説明したように、タイマーを絶えず更新する必要があります。それが、秒ずつ絶えず減らしているためにです。 また、プレーヤーを秒以上単語が正常に完了と単語を誤入力した場合いくつかの時間を奪う賞私たちする必要があります。内側の GameScreen.as:
private var _updateTimer:Number; public function GameScreen() { _background = new BackgroundImage(); _background.x = 275; _background.y = 200; addChild(_background); _blocksOnScreen = new Vector.<LetterBlock>(8); populateBlocks(); _wordBox = new WordBox(); _wordBox.x = 275; _wordBox.y = 350; addChild(_wordBox); _score = new Score(); _score.x = 25; _score.y = 210; addChild(_score); _timer = new Timer(); addChild(_timer); addEventListener(Event.ADDED_TO_STAGE, onStage); addEventListener(Event.ENTER_FRAME, gameLoop); ComboHandler.dispatcher.addEventListener(ComboEvent.COMBO_FINISHED, onWordFinished); ComboHandler.setGameInstance(this); _updateTimer = 0; } private function gameLoop(e:Event):void { ComboHandler.update(); _updateTimer += 1 / 30; if (_updateTimer >= 1) { _updateTimer -= 1; _timer.addToTime(-1); } } private function removeSelectedLetters(wasFromFailure:Boolean):void { var i:int; var count:int = 0; for (i = 0; i < 8; i++) { if (_blocksOnScreen[i].selected) { count++; if ((wasFromFailure && Math.random() < 0.3) || !wasFromFailure) { removeChild(_blocksOnScreen[i]); _blocksOnScreen[i] = null; } else { _blocksOnScreen[i].select(); } } } if (wasFromFailure) { _score.addToScore( -(count * 10)); _timer.addToTime( -count); } else { _score.addToScore(count * 30); _timer.addToTime(count * 2); } }
ライン 1、27、29、33 は、タイマーを作成、画面上に置くし、Event.ENTER_FRAME
のイベント リスナーを追加します。このリスナー (であれば、ここで 30 fps でゲームが実行されていること各フレームに _updateTimer
に 1/30 秒が追加されますです。 それを 24 fps で実行している場合たとえば、それする必要があります追加 1/24 秒の)。とき _updateTimer
に達する 1 つまたは 1 秒以上 1 はタイマーの値から減少しました。 84、89 線では、減少し、プレーヤーが「許容」の単語を形成されるかに基づいて、それぞれ時間を長きます。
また、ユーザーが単語を誤って入力したとき、ゲーム タイマーから秒の文字数と等しい量が減少します。単語が正しい場合は、ゲームはプレーヤーのための秒として文字数の 2 倍を賞します。
これは、あなたの結果は。
ステップ 16: ランダムな文字の作成プロセスの改善します。
現在のゲーム時々 あまりにもほとんどの母音は画面に表示されません。それは単語を作成する非常に困難になります。この手順では、変更します。解決策は非常に簡単です: 重量に基づいて配列を使用します。
この配列には、アルファベットのすべての文字が含まれているし、配列の範囲内でランダムなインデックスへのアクセスによって手紙を差し上げます。ただし、各文字の「重量」は異なるでしょう。 「重さ」は、配列内の文字数では単にので、"r"に重量がある場合例えば、ある 2 つの"R"s 配列内。 手紙のより多くの数がある場合、確率論的視点から見て高いアクセスすることのあなたのチャンス。
コードは確かにそれを説明する役立ちます。このコードは、GameScreen.as 内に配置する必要があります。
private var _letters:Array = ["A", "A", "A", "B", "C", "D", "E", "E", "E", "F", "G", "H", "I", "I", "I", "J", "K", "L", "M", "N", "O", "O", "O", "P", "Q", "R", "R", "S", "T", "U", "U", "U", "V", "W", "X", "Y", "Z"]; private function randomLetter():String { return _letters[int(Math.random() * _letters.length)]; }
1 の行では、文字の配列を見ることができます。各母音は常にそれらの 3 があることを意味、重量 3 を有し、"r"は重量 2 を。しかし、そのアイデアより多く行うことができます多くの非常に簡略化された配列です。
ここでは、相対的な重み明確になりますそれを置く別の方法です。
private var _letters:Array = [ "A", "A", "A", "B", "C", "D", "E", "E", "E", "F", "G", "H", "I", "I", "I", "J", "K", "L", "M", "N", "O", "O", "O", "P", "Q", "R", "R", "S", "T", "U", "U", "U", "V", "W", "X", "Y", "Z" ]; private function randomLetter():String { return _letters[int(Math.random() * _letters.length)]; }
本当に「見えない」、コンパイル済みプロジェクトの下はチェックできます。
ステップ 17: プリローダーを作成、グラフィックス
右、私たちのゲームの基本は完了です。次の手順で画面上プリローダーとゲームを今すぐ追加します。 まず第一に、我々 はプリローダーのグラフィックを作成する必要があります。角丸の正方形は単なる「読み込み」の中に書かれております。それを得るためのソース ファイルをつかむことができます。



ステップ 18: プリローダー コードを記述します。
あなたがFlashDevelopに慣れているならば、これは難しくありません。 グラフィックをそこに入れるようにPreloader
クラスを変更します。 コードにジャンプする:
import ArtAssets.LoadingImage; import flash.display.Sprite; // *** snip *** private var _loadingImage:LoadingImage; private var _loadingMask:Sprite; public function Preloader() { if (stage) { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; } addEventListener(Event.ENTER_FRAME, checkFrame); loaderInfo.addEventListener(ProgressEvent.PROGRESS, progress); loaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioError); _loadingImage = new LoadingImage(); _loadingImage.x = 275; _loadingImage.y = 200; addChild(_loadingImage); _loadingMask = new Sprite(); _loadingMask.x = 75; _loadingMask.y = 175; _loadingImage.mask = _loadingMask; } private function progress(e:ProgressEvent):void { _loadingMask.graphics.clear(); _loadingMask.graphics.beginFill(0x000000); _loadingMask.graphics.drawRect(0, 0, _loadingImage.width * (e.bytesLoaded / e.bytesTotal), 50); _loadingMask.graphics.endFill(); } private function loadingFinished():void { removeEventListener(Event.ENTER_FRAME, checkFrame); loaderInfo.removeEventListener(ProgressEvent.PROGRESS, progress); loaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, ioError); removeChild(_loadingImage); _loadingImage.mask = null; _loadingImage = null; _loadingMask = null; startup(); }
Preloader
コンストラクターで、.swcファイル内にロードイメージのインスタンスを作成し、それをマスクとして使用します。 このマスクは、「ロード」プロセスの視覚的表現を作成します。
Progress()
関数は、キーの関数をここで: それの幅 e.bytesLoaded/e.bytesTotal
の四角形を作成することにより、マスクを更新 回の読み込みの幅バーのイメージ。 ProgressEvent
クラスの bytesLoaded
と bytesTotal
プロパティを見せてゲームからどのように多くのバイトが読み込まれ、合計バイト数とは何ですか。その方法は、ダイビングで我々 はゲームをロードされたの割合を得るそれら。
LoadingFinished()
関数でローディング イメージとそのマスクに対するすべての参照をクリアする必要が我々。そのようにガベージ コレクトされるし、もはやゲームのために予約されたメモリを使用できます。
プリローダーの作業を見てみましょう!
ステップ 19: ゲームは画面上のグラフィックを作成します。
今我々 は画面上のゲームで動作する必要があります。ゲームが終了したときに画面を追加する方法を表示するためだけに、非常に簡単であることと思いました。 グラフィックは非常に簡単: 同じゲーム「ゲーム オーバー」テキストとフェード アニメーション背景。以下のアニメーションの中間を見ることができます。



それを使用するソース ファイルをつかむ!
ステップ 20: ゲームは画面上のコードを記述します。
ゲームの画面上にゲームを追加する時間が今です。その前に、タイマーが 0 (これはゲーム オーバーを意味) に達するときを知る方法を持っている必要があります。そのために Timer.as の getter 関数を作成する必要があります。
public function get value():int { return _value; }
我々 は今 GameOverScreen
クラスを作成できます。
package { import ArtAssets.GameOverScreenImage; import flash.display.Sprite; import flash.events.Event; public class GameOverScreen extends Sprite { private var _image:GameOverScreenImage; public function GameOverScreen() { _image = new GameOverScreenImage(); _image.x = 275; _image.y = 200; addChild(_image); addEventListener(Event.ENTER_FRAME, update); } public function update(e:Event):void { if (_image.currentFrame == _image.totalFrames) { _image.stop(); } } } }
Update()
内のコードは、アニメーションを 1 回だけ再生できるように作成されました。つまり、フェード効果でループは行われません。
Main.as しようとして、このコードを追加します。
private var _gameOverScreen:GameOverScreen; public function gameOver():void { removeChild(_gameScreen); _gameOverScreen = new GameOverScreen(); addChild(_gameOverScreen); }
ゲームが失われたことを検出したとき、GameScreen
によってこのコードが呼び出されます。今のところ、GameScreen.as の内部:
private function gameLoop(e:Event):void { ComboHandler.update(); _updateTimer += 1 / 30; if (_updateTimer >= 1) { _updateTimer -= 1; _timer.addToTime(-1); } if (_timer.value < 0 && parent) { Main(parent).gameOver(); } }
強調表示されている行がこの機能に対する唯一の変更点です。 彼らはタイマーが0未満に達した時とそれがまだ親を持っているかどうかを検出します(これはまだMain
によって削除されていないことを意味します)。 この時点で、それはMain
のgameOver()
関数を呼び出します。
プロジェクトをコンパイル、タイマー 0 に到達し、何を得るを参照してください。
結論
素晴らしい仕事を - 基本的なまだ完全にタイピング ゲームを作成した!次は何?私はあなたより良いタイマー、ブロック文字遷移を追加して、複数のエフェクトを追加するを作ってみるお勧め。