Clicky

Welcome to MSDN Blogs Sign in | Join | Help

develop .net

デベロッパー エバンジェリストの 大野です。

News

  • This blog is in Japanse only. コミュニティにおけるマイクロソフト社員による発言やコメントは、マイクロソフトの正式な見解またはコメントではありません。
Silverlight 1.0 でゲームを作る

Silverlight で作られているゲームが、いろいろ登場しています。たとえば、"Zero Gravity"(※Silverlight 1.1 Alpha が必要です)は、デザインもゲームプログラムとしても、なかなか凝って作られていて楽しめます。実のところ、こうしたゲームには Silverlight 1.1 Alpha 版を使って作成されているものも多いのですが、その理由は「.NET によるパフォーマンス」よりも「.NET 言語を使えることによる手軽さ」にあるのではないかと思います。というのも、Silverlight 1.0 も 1.1 も「描画性能」に違いはなく、キャラクタが動き回る程度の(思考ルーチンなどを持たない)ゲームであれば、JavaScript のパフォーマンスでも十分な場合もあるからです。

そこで、Silverlight 1.0 で「ものすごく単純」なゲームを作ってみました。題材にしたのはテレビゲームの元祖とも言える「テニス」です(もちろん、昨今のコントローラを振り回して遊ぶものとはまったく違います。30年くらい前は、こんなものでも立派に「テレビゲーム」と呼んでいたのです^_^;)。

Silverlight Tennis

※グレーの領域をマウスクリックすると、その場所からボールが移動します。左ラケットの移動は [A][Z] キー、右ラケットの移動は [K][M] キーです。

このゲームに必要な処理は、ボールの移動や衝突の処理、キー入力にともなうラケット(板)の移動処理などです。このアプリケーションで使っている XAML は以下の通りです。

<Canvas
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="640" Height="480" Background="Darkgray" x:Name="Page">

    <Canvas.Resources>
        <Storyboard x:Name="NextFrame">
            <DoubleAnimation x:Name="animBallX" BeginTime="00:00:00" Duration="0:0:0.05" From="320" To="330" Storyboard.TargetName="Ball" Storyboard.TargetProperty="(Canvas.Left)" />
            <DoubleAnimation x:Name="animBallY" BeginTime="00:00:00" Duration="0:0:0.05" From="240" To="250" Storyboard.TargetName="Ball" Storyboard.TargetProperty="(Canvas.Top)" />
        </Storyboard>
    </Canvas.Resources>

    <Rectangle Width="10" Height="80" Fill="Black" Stroke="#FF000000" Canvas.Left="50" Canvas.Top="100" x:Name="Player1"/>
    <Rectangle Width="10" Height="80" Fill="Black" Stroke="#FF000000" Canvas.Left="580" Canvas.Top="280" x:Name="Player2"/>
    <Rectangle Width="10" Height="10" Fill="Black" Stroke="#FF000000" Canvas.Left="310" Canvas.Top="240" x:Name="Ball"/>
</Canvas>

まず、「処理を繰り返す」ために、ここでは非常に短い間隔のアニメーション(Storyboard)を使っています。ここでは「Duration="0:0:0.05"」(0.05秒)と指定していますので、アニメーションを開始した0.05秒後に終了イベント(Completed)を発生させることができます。これを繰り返すことで、ボールを随時移動させているわけです。ラケットの移動もここで処理していますが、ボールの移動が From/To を使ったアニメーションであるのに対し、ラケットは座標値を直接書き換えているだけなので、ボールに比べて“カクカク“動きます。キーを押しているかどうかについては、KeyDown と KeyUp というイベントを使い、すべてのキーの状態(押している=true)を保持する isPressed という配列を使っています。ボール処理のたびに、この配列を確認して、ラケットの上下移動を処理します。あとは、ボールと壁、ラケットの関係に基づいて跳ね返らせたり、ゲームオーバーにするだけです。

// Canvas の KeyDown に割り当てるイベントハンドラ
handleKeyDown: function(sender, args)
{
    isPressed[args.Key] = true;
},

// Canvas の KeyUp に割り当てるイベントハンドラ
handleKeyUp: function(sender, args)
{
    isPressed[args.Key] = false;
},

// Storyboard の Completed に割り当てるイベントハンドラ
handleFrameFinished: function(sender, args)
{
    this.NextFrame.Stop();

    this.animBallY.From = PY;
    if (((PY + DY) < 0) || (this.rootElement.Height <= (PY + DY)))
        DY = -DY;
    PY += DY;
    this.animBallY.To = PY;

    this.animBallX.From = PX;
    if (DX < 0) {
        if ((this.Player1["Canvas.Left"] <= (PX + DX)) && ((PX + DX) < (this.Player1["Canvas.Left"] + this.Player1.Width))
            && (this.Player1["Canvas.Top"] <= PY) && (PY <= (this.Player1["Canvas.Top"] + this.Player1.Height)))
        DX = -DX;
    } else {
        if ((this.Player2["Canvas.Left"] < (PX + DX + STEP)) && ((PX + DX + STEP) <= (this.Player2["Canvas.Left"] + this.Player2.Width))
            && (this.Player2["Canvas.Top"] <= PY) && (PY <= (this.Player2["Canvas.Top"] + this.Player2.Height)))
        DX = -DX;
    }
    PX += DX;
    if (((PX + STEP) < 0) || (this.rootElement.Width < PX))  // game over
        return;
    this.animBallX.To = PX;

    var LeftRacket = this.Player1["Canvas.Top"];
    if (isPressed[30]) LeftRacket -= STEP * 2;
    if (isPressed[55]) LeftRacket += STEP * 2;
    if ((0 <= LeftRacket) && ((LeftRacket + this.Player1.Height) <= this.rootElement.Height))
        this.Player1["Canvas.Top"] = LeftRacket;

    var RightRacket = this.Player2["Canvas.Top"];
    if (isPressed[40]) RightRacket -= STEP * 2;
    if (isPressed[42]) RightRacket += STEP * 2;
    if ((0 <= RightRacket) && ((RightRacket + this.Player2.Height) <= this.rootElement.Height))
        this.Player2["Canvas.Top"] = RightRacket;

    this.NextFrame.Begin();
}

JavaScript ソースコード → http://develop.net/samples/tennis/Page.xaml.js
Silverlight Tennis → http://develop.net/samples/tennis/

さて、少し早いのですが、本年はこれが最後のエントリになる予定です。すでに MSDN サブスクリプションで公開がはじまった Visual Studio 2008 をはじめ、来年第1四半期に登場する Silverlight 2.0 Beta、さらに Windows Server 2008、SQL Server 2008 など、エキサイティングなテクノロジが目白押しです。来年もどうぞよろしくお願いします。

皆様も、よいお年を。

Posted: Friday, December 21, 2007 7:19 PM by mohno
Filed under:

Comments

No Comments

Anonymous comments are disabled
Page view tracker