はじめに
こんにちは、@hiro128_777です。
今回は JXUGC #23 でお見せした関東地方の地図がぐりぐり動くサンプルアプリを作成できるようにハンズオン用のテキストを作成しました。
オフラインでハンズオンも実施しますが、参加できない方でも、こちらを参考にすればサンプルアプリを作成できますので、ご興味がある方はぜひ試してみてください。
完成版のソースコードはこちら
github.com
今回のゴール
Xamarin.Forms 上で Cocos Sharp のアニメーションが動かせるようになる!
ハンズオンを始める前に
Cocos Sharp の基本的な使い方
まずは Cocos Sharp の基本的な使い方をご説明します。
Prism Template Pack のインストール、Prism for Xamarin.Forms 適用済みのソリューションの作成
まずはソリューションを作成します。
手順はこちらをご覧ください。
hiro128.hatenablog.jp
Visual studio for Mac では Prism Template Pack がインストールできないので
以下の作成済みのソリューションをご利用下さい。
github.com
ViewModelの作成 : MainPageViewModel.cs
ViewModels/MainPageViewModel.cs
を下記のように書き換えてください。
Cocos Sharp のキャンバスGameScene
のプロパティを作成し、各県ごとのコマンドにダミーのデリゲートを設定しておきます。
using Prism.Commands;
using Prism.Mvvm;
using Prism.Navigation;
namespace CocosHandsOn01.ViewModels
{
public class MainPageViewModel : BindableBase
{
public GameScene GameScene { get; set; }
public DelegateCommand TokyoCommand => new DelegateCommand(() => { });
public DelegateCommand KanagawaCommand => new DelegateCommand(() => { });
public DelegateCommand SaitamaCommand => new DelegateCommand(() => { });
public DelegateCommand ChibaCommand => new DelegateCommand(() => { });
public DelegateCommand GunmaCommand => new DelegateCommand(() => { });
public DelegateCommand TochigiCommand => new DelegateCommand(() => { });
public DelegateCommand IbarakiCommand => new DelegateCommand(() => { });
private INavigationService navigationService;
public MainPageViewModel(INavigationService navigationService)
{
this.navigationService = navigationService;
}
}
}
画面に地図を表示する
XAMLの作成 : MainPage.xaml
Views/MainPage.xaml
を下記のように書き換えてください。
xml version="1.0" encoding="utf-8"
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlnsx="http://schemas.microsoft.com/winfx/2009/xaml"
xmlnsprism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prismViewModelLocatorAutowireViewModel="True"
Title="関東地方"
xClass="CocosHandsOn01.Views.MainPage">
<Grid xName="MainGrid" RowSpacing="0">
<GridRowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</GridRowDefinitions>
<StackLayout GridColumn="0" GridRow="1" Padding="10,7,10,0" Margin="0,0,0,0" VerticalOptions="FillAndExpand" Orientation="Vertical">
<StackLayoutSpacing>
<OnPlatform xTypeArguments="x:Double">
<OnPlatformiOS>7</OnPlatformiOS>
<OnPlatformAndroid>0</OnPlatformAndroid>
</OnPlatform>
</StackLayoutSpacing>
<Button HeightRequest="35" BackgroundColor="Gray" TextColor="White" Text="群馬県" FontSize="Micro" Command="{Binding GunmaCommand}" />
<Button HeightRequest="35" BackgroundColor="Gray" TextColor="White" Text="栃木県" FontSize="Micro" Command="{Binding TochigiCommand}" />
<Button HeightRequest="35" BackgroundColor="Gray" TextColor="White" Text="茨城県" FontSize="Micro" Command="{Binding IbarakiCommand}" />
<Button HeightRequest="35" BackgroundColor="Gray" TextColor="White" Text="千葉県" FontSize="Micro" Command="{Binding ChibaCommand}" />
<Button HeightRequest="35" BackgroundColor="Gray" TextColor="White" Text="埼玉県" FontSize="Micro" Command="{Binding SaitamaCommand}" />
<Button HeightRequest="35" BackgroundColor="Gray" TextColor="White" Text="神奈川県" FontSize="Micro" Command="{Binding KanagawaCommand}" />
<Button HeightRequest="35" BackgroundColor="Gray" TextColor="White" Text="東京都" FontSize="Micro" Command="{Binding TokyoCommand}" />
</StackLayout>
</Grid>
</ContentPage>
XAMLは通常の Xamarin.Forms の場合と何も変わりません。上下2段のGridが配置してあり、下のセルにボタンが配置されています。
CocosSharp のコントロールは XAML 上には配置されていません。CocosSharp のコントロールは XAML 上で追加すると落ちるため、後ほどコードビハインドで追加します。
コードビハインド : MainPage.xaml
usingを以下のように書き換えます。
using System;
using System.Collections.Generic;
using Xamarin.Forms;
using CocosSharp;
using CocosHandsOn01.ViewModels;
コンストラクタを以下のように書き換えます。
InitializeComponent
の後にCocosSharpView
のコントロールを作成し配置します。。
public MainPage()
{
InitializeComponent();
var grid = this.FindByName<Grid>("MainGrid");
var gameView = new CocosSharpView()
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
ViewCreated = CocosSharpView_ViewCreated
};
grid.Children.Add(gameView, 0, 0);
}
下記のイベントハンドラを追加します。
CocosSharpView
の生成時にゲーム画面CCGameView
の初期設定を行います。
private void CocosSharpView_ViewCreated(object sender, EventArgs e)
{
var gameView = sender as CCGameView;
if (gameView != null)
{
gameView.DesignResolution = new CCSizeI(350, 300);
gameView.ResolutionPolicy = CCViewResolutionPolicy.ShowAll;
gameView.ContentManager.SearchPaths = new List<string> { "Images" };
var gameScene = new GameScene(gameView);
gameView.RunWithScene(gameScene);
var viewModel = BindingContext as MainPageViewModel;
viewModel.GameScene = gameScene;
}
}
参考
ゲーム画面の初期化の内容を具体的に見ていきましょう。
gameView.DesignResolution = new CCSizeI(350, 300);
ゲーム内の仮想解像度を横350ユニット、縦300ユニットに設定します。
gameView.ResolutionPolicy = CCViewResolutionPolicy.ExactFit;
アスペクト比を保ったまま最大の大きさで表示します。
gameView.ContentManager.SearchPaths = new List<string> { "Images" };
アセットを探しに行くパスを設定します。
var viewModel = BindingContext as MainPageViewModel;
viewModel.GameScene = gameScene;
また、ViewModel側からゲーム操作できるように参照を渡しています。この部分本当は疎結合にしたいのですが、現状では厳しそうな感じです。
アセットの配置
Imageファイルをプラットフォームごとのプロジェクトに配置します。
Imageファイルは以下をご利用ください。
tokyo.png
kanagawa.png
saitama.png
chiba.png
gunma.png
tochigi.png
ibaraki.png
iOSの場合
Content/Images
の中にpngファイルを配置してください。
pngファイルのビルドアクションはBundleResource
に設定してください。
Androidの場合
Assets/Content/Images
の中にpngファイルを配置してください。
pngファイルのビルドアクションはAndroidAsset
に設定してください。
レイヤーの作成 : GameLayer
CocosSharp では、キャンパスであるCCScene
の中に、グラフィックレイヤーであるCCLayer
を配置し、その中に動くオブジェクトCCSprite
を配置します。
最初にCCLayer
上にそれぞれの県のCCSprite
を配置します。
using System;
using System.Diagnostics;
using CocosSharp;
namespace CocosHandsOn01
{
public class GameLayer : CCLayerColor
{
private CCTexture2D tokyoTexture;
private CCTexture2D kanagawaTexture;
private CCTexture2D saitamaTexture;
private CCTexture2D chibaTexture;
private CCTexture2D gunmaTexture;
private CCTexture2D tochigiTexture;
private CCTexture2D ibarakiTexture;
private CCSprite tokyoSprite;
private CCSprite kanagawaSprite;
private CCSprite saitamaSprite;
private CCSprite chibaSprite;
private CCSprite gunmaSprite;
private CCSprite tochigiSprite;
private CCSprite ibarakiSprite;
public GameLayer(CCColor4B? color = default(CCColor4B?)) : base(color)
{
tokyoTexture = new CCSprite("tokyo.png", null).Texture;
kanagawaTexture = new CCSprite("kanagawa.png", null).Texture;
saitamaTexture = new CCSprite("saitama.png", null).Texture;
chibaTexture = new CCSprite("chiba.png", null).Texture;
gunmaTexture = new CCSprite("gunma.png", null).Texture;
tochigiTexture = new CCSprite("tochigi.png", null).Texture;
ibarakiTexture = new CCSprite("ibaraki.png", null).Texture;
var offsetX = 50f;
tokyoSprite = new CCSprite(tokyoTexture)
{
PositionX = 96.25f + offsetX,
PositionY = 126.25f,
Scale = 0.3f,
Tag = (int)Prefecture.Tokyo,
};
AddChild(tokyoSprite);
kanagawaSprite = new CCSprite(kanagawaTexture)
{
PositionX = 90f + offsetX,
PositionY = 93f,
Scale = 0.3f,
Tag = (int)Prefecture.Kanagawa,
};
AddChild(kanagawaSprite);
saitamaSprite = new CCSprite(saitamaTexture)
{
PositionX = 84.5f + offsetX,
PositionY = 163f,
Scale = 0.3f,
Tag = (int)Prefecture.Saitama,
};
AddChild(saitamaSprite);
chibaSprite = new CCSprite(chibaTexture)
{
PositionX = 177.5f + offsetX,
PositionY = 104f,
Scale = 0.3f,
Tag = (int)Prefecture.Chiba,
};
AddChild(chibaSprite);
gunmaSprite = new CCSprite(gunmaTexture)
{
PositionX = 60f + offsetX,
PositionY = 220f,
Scale = 0.3f,
Tag = (int)Prefecture.Gunma,
};
AddChild(gunmaSprite);
tochigiSprite = new CCSprite(tochigiTexture)
{
PositionX = 131f + offsetX,
PositionY = 238f,
Scale = 0.3f,
Tag = (int)Prefecture.Tochigi,
};
AddChild(tochigiSprite);
ibarakiSprite = new CCSprite(ibarakiTexture)
{
PositionX = 174.5f + offsetX,
PositionY = 200f,
Scale = 0.3f,
Tag = (int)Prefecture.Ibaraki,
};
AddChild(ibarakiSprite);
}
}
public enum Prefecture
{
Tokyo,
Kanagawa,
Saitama,
Chiba,
Gunma,
Tochigi,
Ibaraki
}
}
シーンの作成
CCScene
上に今作成したCCLayer
を配置します。
using System;
using CocosSharp;
namespace CocosHandsOn01
{
public class GameScene : CCScene
{
GameLayer layer;
public GameScene(CCGameView gameView) : base(gameView)
{
layer = new GameLayer(CCColor4B.Black);
AddLayer(layer);
}
}
}
確認
ここまでをデバッグ実行すると画面上に地図が表示されるはずです。確認してみましょう。