Silverlightを使って簡単なミニゲームを作る—Jewellery(Part 2)
7663 ワード
下一篇:Silverlightを使って簡単なミニゲームを作る—Jewellery(Part 1)
Jewelsからコードの作成を開始します.
まずはInitializeメソッド.スタート後、Jewel配列を埋めてCanvasに表示します.ここで注意したいのは、初期化のプロセスは、最終的な表示において、消去可能なJewelが存在しないことを保証することです.Jewelの種類はランダムに生成されるため、最も簡単な方法は、現在位置の行/列において、隣接位置に同じ種類のJewelが存在する場合、ランダムに生成される種類はこの種類ではない.コードは次のとおりです.
各Jewelも初期化する必要があり、各Jewelを表示できるようにするには、JewelBaseにInitializeの虚メソッドを追加し、現在のCanvasに転送する必要があります.したがって、Jewelsを初期化した後、各JewelのInitializeメソッドを呼び出します.具体的な内容は、Jewelを実現する際に、またお話しします.
CreateJewelメソッドでは、JewelのClickイベントごとに、ユーザーのクリックを受信/選択するための統一的な処理方法をバインドします.これは、ユーザーのインタラクションを処理する鍵です.クリック処理があれば、次はSelectとUnselectで、現在選択されているJewelを記録する以外は、インタフェースIJewelSelectorを呼び出せばいいので、先にスキップします.ここでは主にExchangeメソッドと、Exchangeの後にTryToDestroyメソッドを扱うのがゲームの核心でしょう.これを言う前に、MoveでもDestroyでも、このプロセスはアニメーション表示のプロセスに違いないと説明したいと思います.SLでは、アニメーションの表示は一般的にthreadの問題です.アニメーション表示が終了したら、次の処理を行い、良い応答を得ることができます.だから、私たちはまずExchangeをして、2つのJewelのMoveアニメーションが終わるのを待って、TryToDestroyに来ます.Destroyもアニメーションであることを考慮して、ここでは単独でClassをしてEventを登録し、すべてのJewel応答が終わるのを待っています.大まかなコードは次のとおりです.
このようにして、アニメーションがすべて終了したことを確認してから、次の判断を実行することができます.
これがExchangeメソッドの最も主要なことで、2つのJewelのMoveToメソッドを呼び出して、それらが新しい位置に移動できるようにし、移動が終了するのを待ってから、破棄できるJewelが存在するかどうかを判断し、存在しない場合、この2つのJewelの位置を回復します.
TryToDestroyという方法を見てみましょう.実は何も言うことはありません.横になってから、縦に破棄できるJewelを探して、3つ以上あれば破棄できます.ここでお話しするのは、やはりアニメーションの表示についてです.プログラムではまずすべてを巡り、破棄できるJewelを見つけて、重複していないことを確認し、リストに存在していることを確認し、最後にJewelのDestroyメソッドを呼び出します.やはりさっき言ったイベントのクラスを使います.大まかなコードは次のとおりです.
最後の方法は、Destroyの後、Jewelの補充作業をして、ゲームをずっと遊ぶことができます.:)やはり遍歴して、私はこの方法の中で、下から上へ遍歴して、nullの場所に出会って、私はメモして、それから上へ歩いて、Jewelを見つけた後に、このJewelのMoveTo方法を呼び出して、それを消えたJewelの位置に落とすことができます.見つからない場合は、転送された配列のJewelを先端に配置し、再初期化します.このような利点は、Jewelを新規作成する必要がなく、すべてのJewelインスタンスが重複して適用されることです.
Fillを終えたら、TryToDestroyに行くことを忘れないでください.新しい充填のため、消去可能なJewelも存在するかもしれません.続けて消して、これもゲームの中で最も眩しいところでしょう.:)だから、ここは消去可能なJewelがなくなるまで循環します.
はい、これが核心の論理部分で、基本的にSLのものには触れません.次にJewelのアニメーションを処理し始め、本当に表示できるようにして、この論理を発揮させます.
未完待続...
Jewelsからコードの作成を開始します.
まずはInitializeメソッド.スタート後、Jewel配列を埋めてCanvasに表示します.ここで注意したいのは、初期化のプロセスは、最終的な表示において、消去可能なJewelが存在しないことを保証することです.Jewelの種類はランダムに生成されるため、最も簡単な方法は、現在位置の行/列において、隣接位置に同じ種類のJewelが存在する場合、ランダムに生成される種類はこの種類ではない.コードは次のとおりです.
private void Initialize()
{
for (int i = 0; i < this.RowCount; ++i)
for (int j = 0; j < this.ColumnCount; ++j)
{
this.JewelMap[i, j] = this.CreateJewel(i, j);
}
this.FillMap(this.KindCount);
}
private T CreateJewel(int x, int y)
{
T jewel = new T();
jewel.IndexX = x;
jewel.IndexY = y;
jewel.Width = this.JewelWidth;
jewel.Height = this.JewelHeight;
jewel.Click += new EventHandler(jewel_Click);
return jewel;
}
private void FillMap(int kindCount)
{
List<int> unallowed = new List<int>();
for (int i = 0; i < this.RowCount; ++i)
for (int j = 0; j < this.ColumnCount; ++j)
{
T jewel = this.JewelMap[i, j];
if (i > 1 && this.JewelMap[i - 1, j].Kind == this.JewelMap[i - 2, j].Kind)
{
unallowed.Add(this.JewelMap[i - 1, j].Kind);
}
if (j > 1 && this.JewelMap[i, j - 1].Kind == this.JewelMap[i, j - 2].Kind)
{
unallowed.Add(this.JewelMap[i, j - 1].Kind);
}
int kind = rand.Next(kindCount);
while (unallowed.Contains(kind))
kind = rand.Next(kindCount);
jewel.Kind = kind;
unallowed.Clear();
}
}
各Jewelも初期化する必要があり、各Jewelを表示できるようにするには、JewelBaseにInitializeの虚メソッドを追加し、現在のCanvasに転送する必要があります.したがって、Jewelsを初期化した後、各JewelのInitializeメソッドを呼び出します.具体的な内容は、Jewelを実現する際に、またお話しします.
CreateJewelメソッドでは、JewelのClickイベントごとに、ユーザーのクリックを受信/選択するための統一的な処理方法をバインドします.これは、ユーザーのインタラクションを処理する鍵です.クリック処理があれば、次はSelectとUnselectで、現在選択されているJewelを記録する以外は、インタフェースIJewelSelectorを呼び出せばいいので、先にスキップします.ここでは主にExchangeメソッドと、Exchangeの後にTryToDestroyメソッドを扱うのがゲームの核心でしょう.これを言う前に、MoveでもDestroyでも、このプロセスはアニメーション表示のプロセスに違いないと説明したいと思います.SLでは、アニメーションの表示は一般的にthreadの問題です.アニメーション表示が終了したら、次の処理を行い、良い応答を得ることができます.だから、私たちはまずExchangeをして、2つのJewelのMoveアニメーションが終わるのを待って、TryToDestroyに来ます.Destroyもアニメーションであることを考慮して、ここでは単独でClassをしてEventを登録し、すべてのJewel応答が終わるのを待っています.大まかなコードは次のとおりです.
public delegate bool EventCondition(string eventName);
public static class JewelEvent
{
// launch this method when a jewel finish its animation
public static void Add(string name, JewelBase source)
{
}
// get all jewels which has finished
public static JewelBase[] GetSources(string name)
{
}
public static T[] GetSources<T>(string name) where T : JewelBase
{
}
public static void RegisterAndBegin(string name, int count, Action action)
{
RegisterAndBegin(name, (e) => GetSources(name).Length == count, action);
}
public static void RegisterAndBegin(string name, EventCondition condition, Action action)
{
RegisterAndBegin(name, condition, (Delegate)action);
}
// register a event, auto launch action depend on condition
public static void RegisterAndBegin(string name, EventCondition condition, Delegate action, params object[] parameters)
{
}
public static void Unregister(string name)
{
}
public static bool HasRegistered(string name)
{
}
public static void Begin(string name)
{
}
public static void End(string name)
{
}
public static void Reset(string name)
{
}
}
このようにして、アニメーションがすべて終了したことを確認してから、次の判断を実行することができます.
private void Exchange(T source, T target)
{
JewelEvent.RegisterAndBegin("Move", 2, this.ExchangeFinished);
// launch JewelBase.MoveTo method
}
private void ExchangeFinished()
{
if (!this.TryToDestroy())
{
// restore
T[] jewels = JewelEvent.GetSources<T>(“Move”);
this.Exchange(jewels[0], jewels[1]);
}
}
これがExchangeメソッドの最も主要なことで、2つのJewelのMoveToメソッドを呼び出して、それらが新しい位置に移動できるようにし、移動が終了するのを待ってから、破棄できるJewelが存在するかどうかを判断し、存在しない場合、この2つのJewelの位置を回復します.
TryToDestroyという方法を見てみましょう.実は何も言うことはありません.横になってから、縦に破棄できるJewelを探して、3つ以上あれば破棄できます.ここでお話しするのは、やはりアニメーションの表示についてです.プログラムではまずすべてを巡り、破棄できるJewelを見つけて、重複していないことを確認し、リストに存在していることを確認し、最後にJewelのDestroyメソッドを呼び出します.やはりさっき言ったイベントのクラスを使います.大まかなコードは次のとおりです.
private bool TryToDestroy()
{
List<T> jewels = new List<T>();
// check row
for (int y = 0; y < this.ColumnCount; ++y)
{
// ...
}
// check column
for (int x = 0; x < this.RowCount; ++x)
{
// ...
}
if (jewels.Count == 0)
{
return false;
}
// destroy
JewelEvent.RegisterAndBegin("Destroy", jewels.Count, this.DestroyFinished);
jewels.ForEach((e) =>
{
e.Destroy();
this.JewelMap[e.IndexX, e.IndexY] = null;
});
return true;
}
private void DestroyFinished()
{
T[] jewels = JewelEvent.GetSources<T>(JewelEventNames.Destroy);
this.Fill(jewels); // fill empty location
}
最後の方法は、Destroyの後、Jewelの補充作業をして、ゲームをずっと遊ぶことができます.:)やはり遍歴して、私はこの方法の中で、下から上へ遍歴して、nullの場所に出会って、私はメモして、それから上へ歩いて、Jewelを見つけた後に、このJewelのMoveTo方法を呼び出して、それを消えたJewelの位置に落とすことができます.見つからない場合は、転送された配列のJewelを先端に配置し、再初期化します.このような利点は、Jewelを新規作成する必要がなく、すべてのJewelインスタンスが重複して適用されることです.
private void FillEmpty(T[] jewels)
{
List<T> sources = new List<T>();
List<int> targetXs = new List<int>(); // save new location x
List<int> targetYs = new List<int>(); // save new location y
for (int x = 0; x < this.RowCount; ++x)
{
// ...
}
if (sources.Count == 0)
return;
JewelEvent.RegisterAndBegin("Move", sources.Count, this.FillFinished);
for (int i = 0; i < sources.Count; ++i)
{
this.MoveTo(sources[i], targetXs[i], targetYs[i]);
}
sources.Clear();
}
private void FillFinished()
{
this.TryToDestroy(); // try to destroy again
}
Fillを終えたら、TryToDestroyに行くことを忘れないでください.新しい充填のため、消去可能なJewelも存在するかもしれません.続けて消して、これもゲームの中で最も眩しいところでしょう.:)だから、ここは消去可能なJewelがなくなるまで循環します.
はい、これが核心の論理部分で、基本的にSLのものには触れません.次にJewelのアニメーションを処理し始め、本当に表示できるようにして、この論理を発揮させます.
未完待続...