2016年9月13日 | ブログ記事

MonoGameを使ってAndroidのゲームを作ろう その2

Namazu

どうも、Namazuです。

前回の記事はこちら。まさか続くとは。
ということで、今回扱う内容は以下の通りです。

これだけ?と思うかもしれませんが、意外と構造が面倒くさいのです。
具体的な実装の話の前に、関連するクラスの説明から。

(MSDN公式サイトより引用)

よく分からないので、少しずつ整理していきます。

まず、私たちが欲しい情報は

などですね。
そこである一ヶ所のタッチについての情報をまとめているのがTouchLocationです。
しかし複数タッチに対応するためには複数のTouchLocationが必要です。
そこで、複数のTouchLocationをまとめたものがTouchCollectionです。
そして、タッチ情報は毎フレーム更新しなくては意味がありません。
画面からタッチ情報を受け取り、TouchCollectionを更新するために用いるのがTouchPanelです。

それではそれぞれのクラスの主要なメンバやメソッドを具体的な実装方法を交えてご紹介します。


//TouchPanelクラス
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
Exit();

touchCollection = TouchPanel.GetState();
//Update関数の中で記述する。
//TouchPanelは、Input.Touchクラスをインポート(using Microsoft.Xna.Framework.Input.Touch;)としておけば定義しなくてよい。

base.Update(gameTime);
}

//TouchCollectionクラス、TouchLocationクラス
protected override void Draw(GameTime gameTime)
{
for(var i=0;i<touchCollection.Count;i++){
TouchLocation touchLocation = touchCollection[i]; //これでタッチID昇順のi番目のTouchLocationが取得できる。
Point point = new Point((int)touchLocation.Position.X,(int)touchLocation.Position.Y); //Pointの中身はint型、Vector2の中身はfloat型
if(ayayaRect.Contains(point)) {}//ayayaRectはRectangleクラスのオブジェクト。Contains(point)でその領域にpointが含まれているか判定できる。
}

base.Update(gameTime);
}

タッチ入力を検出する流れは分かっていただけたでしょうか?
それでは、タッチしたら画面の背景色が変わるゲーム(?)を作ってみましょう。

Activity1.csは変更せずに、Game1.csを以下のように変更します。
Game1.cs


using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using System;

namespace TouchOnly
{
/// <summary>
/// This is the main type for your game.
/// </summary>
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;

Texture2D ayaya, yoko, alice, karen;
Vector2 touchPosition;
TouchCollection touchCollection;
Rectangle ayayarect = new Rectangle(300, 200, 200, 200);
Rectangle alicerect = new Rectangle(700, 200, 200, 200);
Rectangle yokorect = new Rectangle(300, 500, 200, 200);
Rectangle karenrect = new Rectangle(700, 500, 200, 200);

Color backGroundColor = Color.CornflowerBlue;
string[] text;

public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";

graphics.IsFullScreen = true;
graphics.PreferredBackBufferWidth = 800;
graphics.PreferredBackBufferHeight = 480;
graphics.SupportedOrientations = DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight;
}

/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here

base.Initialize();
}

/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
ayaya = Content.Load<Texture2D>("ayaya2");
alice = Content.Load<Texture2D>("alice");
karen = Content.Load<Texture2D>("karen");
yoko = Content.Load<Texture2D>("yoko");

// TODO: use this.Content to load your game content here
}

/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// game-specific content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}

/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
Exit();

// TODO: Add your update logic here

touchCollection = TouchPanel.GetState();

base.Update(gameTime);
}

/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
text = new string[touchCollection.Count];
for (var i = 0; i < touchCollection.Count; i++)
{

TouchLocation touchLocation = touchCollection[i];
touchPosition = touchLocation.Position;
Point point = new Point((int)touchPosition.X, (int)touchPosition.Y);
if (ayayarect.Contains(point))
{
backGroundColor = Color.RoyalBlue;
}
else if (alicerect.Contains(point))
{
backGroundColor = Color.Gold;
}
else if (yokorect.Contains(point))
{
backGroundColor = Color.Orange;
}
else if (karenrect.Contains(point))
{
backGroundColor = Color.Yellow;
}
else
{
backGroundColor = Color.CornflowerBlue;
}
text[i] = string.Format("id={0} X={1} Y={2} state={3} touch count={4}", touchLocation.Id, touchLocation.Position.X, touchLocation.Position.Y, touchLocation.State, touchCollection.Count);
Console.WriteLine(text[i]);
}

GraphicsDevice.Clear(backGroundColor);

spriteBatch.Begin();
spriteBatch.Draw(ayaya, ayayarect, Color.White);
spriteBatch.Draw(alice, alicerect, Color.White);
spriteBatch.Draw(yoko, yokorect, Color.White);
spriteBatch.Draw(karen, karenrect, Color.White);
spriteBatch.End();

base.Draw(gameTime);
}
}
}

簡単に説明します。

何か説明に不備または分かりにくい点等ありましたらコメントにてご指摘ください。

さて、ここからが重要ですがきんいろモザイクの映画「きんいろモザイク PrettyDays」が2016年11月12日に公開されますね。
今回の記事であややを始めとするきんいろモザイクのキャラの可愛さが伝わったと思うので是非見に行きましょう。
私はもう前売り券をゲットしました。特典ブロマイドはあややでした。完全に勝利です。

この記事を書いた人
Namazu

Namazuです。 今まで制作に携わったゲームはTypingWar、EccentricEscape、進捗どうですか?、NinjaFlicker等です。 MonoGameにまつわる記事も書いています。

この記事をシェア

このエントリーをはてなブックマークに追加

関連する記事

2016年9月14日
MonoGameを使ってAndroidのゲームを作ろう その3
Namazu
2016年8月7日
Monogameを使ってAndroidのゲームを作ろう その1
Namazu
2016年4月23日
ゲームプログラミング講習会を行いました
nari
2018年9月19日
ゲームの敵の動きを実装した話
mds_boy
2018年6月12日
ハッカソン2018参加記 – チームFeSt「かえるます」 –
eiya
2018年4月26日
ゲームを作ろう
gotoh

活動の紹介

カテゴリ

タグ