Windows Phone用のゲームを作成します


少し前まで、Windows Phoneプラットフォームが一般に紹介されました。 プラットフォームは、開発の面で非常に興味深いです。 .Net Framework、マルチタスク、およびXNA Frameworkのサポートがあり、XNAとデスクトップバージョンの違いは最小限です。

最初は、軟膏のハエ:Windows Phoneでは、独自のシェーダーに対する本格的なサポートはありませんが、優れた機能を備えたいくつかの事前構成された設定が約束されています。 さて、心配することはありません、すべてに時間があります。
仕事にはWindows Phone開発者ツールが必要です

さらに読む前に、リンクで記事をご覧になることをお勧めします。リンクにはXNAゲームのアーキテクチャに関する基本情報が含まれています。


したがって、新しいソリューションを作成します。



画面にテキストを表示することから始めましょうこれを行うには、プロジェクトに新しいフォントファイルを追加します。



このファイルを開き、セクションにキリル文字のエントリを追加します。
< CharacterRegions >
< CharacterRegion >
< Start > </ Start >
< End > ~ </ End >
</ CharacterRegion >
< CharacterRegion >
< Start > </ Start >
< End > </ End >
</ CharacterRegion >
</ CharacterRegions >

また、フォントサイズを大きくします。

フォントのダウンロードコードと表示テキスト:
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
font = Content.Load<SpriteFont>( "Arial" );
}

protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin();
spriteBatch.DrawString(font, " !" , new Vector2(120, 400), Color.White);
spriteBatch.End();
base .Draw(gameTime);
}




画面回転



しかし、残念なことに、空間内のデバイスの向きを変更しても画面の向きが切り替わらないため、480/800のアスペクト比で画面を再生するのはあまり便利ではありません。 XNAには画面を回転させる手段はありませんが、自分で取得する必要があります。 RenderTarget2Dはこれに役立ちます。 実際、これは指定したサイズのテクスチャであり、そこに描画してから画面に表示することもできます。 Draw関数の変更:スプライトは画面ではなくrenderTargetに描画されます。

protected override void Initialize()
{
base .Initialize();
renderTarget = new RenderTarget2D(GraphicsDevice, 800, 480, false , SurfaceFormat.Color, DepthFormat.Depth24Stencil8);
}

private void DrawSprites(GameTime gameTime) // renderTarget 800x480
{
spriteBatch.Begin();
spriteBatch.DrawString(font, " !" , new Vector2(40, 40), Color.White);
spriteBatch.End();
}

protected override void Draw(GameTime gameTime)
{
GraphicsDevice.SetRenderTarget(renderTarget);
GraphicsDevice.Clear(Color.Black); // renderTarget
DrawSprites(gameTime); //
GraphicsDevice.SetRenderTarget( null ); //
GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin(); // renderTarget
spriteBatch.Draw((Texture2D)renderTarget, Vector2.Zero, null , Color.White, -MathHelper.PiOver2, new Vector2(800, 0), 1, SpriteEffects.FlipHorizontally | SpriteEffects.FlipVertically, 0);
spriteBatch.End();
base .Draw(gameTime);
}


私たちが得たもの:



「ゲーム」には必ずスタートアップ画面が必要です。プロジェクトにtitle.pngを追加します。 ゲームを開始してから4秒後にこの画像を表示します。
Texture2D title;

protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
font = Content.Load<SpriteFont>( "Arial" );
title = Content.Load<Texture2D>( "Title" );
}

private void DrawSprites(GameTime gameTime)
{
spriteBatch.Begin();
if (gameTime.TotalGameTime.TotalSeconds > 4)
spriteBatch.DrawString(font, " !" , new Vector2(40, 40), Color.White);
else
spriteBatch.Draw(title, Vector2.Zero, Color.White);
spriteBatch.End();
}




3Dグラフィックス


マトリックスの操作とユーザー入力の処理を担当するカメラクラスが必要です。gamedev.ruでカメラの作成について読むことができます。 この記事のフレームワークでは、タッチ入力の操作を担当するUpdateTouch関数のみが対象です。 このリンクでは、カメラの完全なソースコードを表示できます。 データを別のDLLに格納するためのロジック、クラスを配置することをお勧めします。 これを行うには、ソリューションに新しいプロジェクト「WindowsPhoneGameDemoObjects」を追加します

private void UpdateTouch(GameTime gameTime)
{
TouchCollection tc = TouchPanel.GetState(); //
if (tc.Count > 0)
{
TouchLocation current = tc[0]; //
TouchLocation prev;
if (current.TryGetPreviousLocation( out prev)) //
{
//
Angle.X -= MathHelper.ToRadians((current.Position.X - prev.Position.X) * turnSpeed); // pitch
Angle.Y += MathHelper.ToRadians((current.Position.Y - prev.Position.Y) * turnSpeed); // yaw

while (Angle.Y > MathHelper.Pi * 2)
Angle.Y -= MathHelper.Pi * 2;
while (Angle.Y < -MathHelper.Pi * 2)
Angle.Y += MathHelper.Pi * 2;

if (Angle.X > maxPitch)
Angle.X = maxPitch;

if (Angle.X < -maxPitch)
Angle.X = -maxPitch;

float time = ( float )gameTime.ElapsedGameTime.TotalSeconds;
Vector3 forward = -Vector3.Normalize( new Vector3(( float ) Math .Sin(-Angle.Y),
( float ) Math .Sin(Angle.X),
( float ) Math .Cos(-Angle.Y)));
if (DenyVerticalMovement)
{
forward = new Vector3(forward.X, 0, forward.Z);
forward.Normalize();
}
Position += forward * movementSpeed * time;
}
else
touchStartTime = gameTime;
}
}


カメラはDrawableGameComponentから継承されていることに注意してください-つまり ゲームのコンポーネントのリストにカメラを追加すると(this.Components.Add(camera);)、Updateメソッドが自動的に呼び出されます。 オブジェクトとシーンのクラスを記述し、レンダリングするプロジェクトにモデルを追加します。

public class Entity
{
public Matrix World //
{
get
{
return Matrix.CreateScale(Scale)
* Matrix.CreateRotationY(Rotation.Y)
* Matrix.CreateRotationX(Rotation.X)
* Matrix.CreateRotationZ(Rotation.Z)
* Matrix.CreateTranslation(Position)
;
}
}
public Model Model; //
public Vector3 Scale = Vector3.One; // :)
public Vector3 Rotation;
public Vector3 Position;

public void Draw(Camera camera)
{
Matrix[] transforms = new Matrix[Model.Bones.Count]; //
Model.CopyAbsoluteBoneTransformsTo(transforms);

foreach (ModelMesh mesh in Model.Meshes) //
{
foreach (BasicEffect be in mesh.Effects)
{
be.EnableDefaultLighting();
be.PreferPerPixelLighting = true ;
be.Projection = camera.Projection;
be.View = camera.View;
be.World = World * mesh.ParentBone.Transform;
}
mesh.Draw();
}
}
}

public class Scene
{
public List <Entity> Entities = new List <Entity>();
public void Load(ContentManager content)
{
Entities.Add( new Entity() { Model = content.Load<Model>( "Scene\\Scene" ) });
}

public void Draw(Camera camera)
{
foreach (Entity e in Entities)
e.Draw(camera);
}
}


ほとんどすべての準備が整いましたが、1つの不快な問題を解決するだけです。 実際、SpriteBatchオブジェクトは培養されていない状態で動作します。レンダリング設定が変更され、レンダリング後に元の設定が返されません。 この問題を解決するために、興味のある設定を保存し、SpriteBatchの完了後にそれらをインストールし直します。



かっこいい はい。ただし、すべてのプレイヤーがエーテルのような影のように感じたいわけではありません。十分な衝突がありません。 そして、衝突を処理するには何が必要ですか? そうです、ジオメトリ。 これらのモデルから外出するだけではあまり便利ではないので、ContentProcessorを作成しましょう。 これは、プロジェクトの組み立て中にゲームリソースを特別に処理するものです。
このContentProcessorでは、モデルからジオメトリデータを分離し、それらを個別に保存します。 ソリューションに新しいプロジェクト「コンテンツパイプライン拡張ライブラリ」を追加し、3Dモデルの処理を担当するModelCollisionProcessorクラスを記述します。このコードは msdnの例から取られたもので、すべての作業はモデルにポリゴンのリストを追加します。 モデルポリゴンのリストは、Tagプロパティに保存されます。 このプロパティには、任意のデータを保存できます。
作成したContentProcessorを使用するには、ゲームのリソースプロジェクトのCollisionContentProcessorへのリンクを追加し、プロジェクトの各3DモデルのプロパティタブでContentProcessor値をModelCollisionProcessorに設定する必要があります。



ジオメトリデータを取得したので、それらを使用して何かを行う必要があります。 衝突処理クラスを書きましょう。 gamedev.ruのこの記事を参考にしてこのクラスを作成しました。
新しいGroundCameraクラスを作成し、Cameraから継承します。動作の原理は次のとおりです。衝突を処理するボールが地面を転がり、そこから一定の距離でカメラが上にアタッチされます。
Game1.csのCameraをGroundCameraに置き換えます。Updateメソッドで、衝突処理関数を呼び出します。 明確にするために、シーンに別のオブジェクト、遊び場を追加します。 最後に、簡単なスカイボックスを作成しましょう。
結果として得られたもの:



記事のソースをダウンロードしてください。

この記事の範囲外であるもの:

このトピックがhabrasocietyにとって興味深いものである場合、Windows PhoneでXNAに関する記事をさらに2つ書くことをお約束します。
読むべきもの:
http://creators.xna.com
http://blogs.msdn.com/shawnhar/default.aspx
http://gamedev.ru

記事はコンテストに参加します
こちらの記事に投票してください

Source: https://habr.com/ru/post/J90768/


All Articles