どうも、Namazuです。
今、Ninja's Revenge2の開発でMonogameを使っているのですが、Monogameの特にAndroid版での解説が少なかったのでここに書いておきます。
※この記事は2016年8月に書かれたものです。最新の情報とは限りませんのであしからず。
今回の内容
- 開発環境の準備
- 新しいプロジェクトの作成
- 画像の表示
1.インストールするもの
MonogameVisual Studio CommunityXamarin
上記三点をインストールしてください。(クリックするとダウンロードサイトに飛びます)
ここは頑張ってほしい。
2.新しいプロジェクトの作成
まず、新しいプロジェクトを作ります。
左上のツールバー、File→New→Project...を選択してください。
すると以下の画面が出てきますので、Monogame Android Projectを選択してください。
名前は任意です。今回はTutorialとしました。
ここまえ進むとプロジェクトの作成が始まります。
すると、以下の警告が出てきます。
内容は、「ファイルの変更を検出したときどうしますか」ということなので、「すべて再読み込みする(Reload ALL)」を選んでおきましょう。
(おそらくReloadでも問題ありませんが、保険のためです)
さて、プロジェクトの作成が完了すると以下のような画面が開きます。
Solution Explorerは右側のバーに表示されています。もし展開されていなければ展開しておきましょう。
さて、Android Studio等でAndroidアプリを作成したことのある方は分かるかもしれませんが、既にcsファイルが二つに分割されています。
Android講習会で扱ったLectureAppのMainActivity.javaにあたる役割を果たすのがActivity1.cs、LectureView.javaにあたる役割を果たすのがGame1.csです。
基本的に、コードを書かなくてはいけないのはGame1.csです。
さて、それではこのまま実行してみましょうか。
実機またはエミュレータを準備して実行してください。
※実機をおすすめします。実機ならばUSB接続するとすぐ実行できる状態になるので。(一応開発者モードである必要はあるか…?)
※エミュレータは設定が面倒なうえひたすら重いです。やめましょう。
すると、ただひたすら青っぽい背景が表示されるアプリになっています。
ちなみに、青っぽいのはGame1.csの
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Microsoft.Xna.Framework.Color.CornflowerBlue);
// TODO: Add your drawing code here
base.Draw(gameTime);
}
の部分でColor.CornflowerBlueと指定されているのが原因です。
Color.の後を変更すると色が変わりますよ(´▽`)b
3.画像の表示
さて、画像を表示しましょう。
Solution ExplorerのContentフォルダを展開するとContent.mgcbというファイルが見つかるかと思います。
それを右クリックし、Open with...でMonogame Pipeline Toolで開きましょう。デフォルトに設定しておくと楽です。
まず、何故か画面レイアウトがおかしいので直します。
その後、Contentを選択し Add Existing Itemから追加したいファイルを選択します。
すると、以下のようなポップアップが出ます。
Copy the file to the directoryを選びましょう。
念のため、Use the same action for all selected filesのチェックは入れません。
すると、以下のようにファイルが追加されます。
上は、ビルドを行った後の画面です。
ファイルが追加できたら、ビルドしてください。
右のように表示され、0 failedと表示されていれば成功です。
Solution Explorerを見てもファイルは追加されていませんが、心配はありません。
さて、おまたせしました。コードを書いていきます。
デフォルトで生成されるコードに少し書き足すだけですが、変更点は色付けしています。
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace Tutorial
{
///
<summary>
/// This is the main type for your game.
/// </summary>
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D texture; //追加
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);
texture = Content.Load<Texture2D>("alice"); //追加
// 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
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)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
//追加ここから
spriteBatch.Begin();
spriteBatch.Draw(texture, new Rectangle(0, 0, 500, 500), Color.White);
spriteBatch.End();
//追加ここまで
// TODO: Add your drawing code here
base.Draw(gameTime);
}
}
}
上記のコードを実行すると、以下のように画面左端を基準とする500×500pixelの領域に画像が表示されます。
アリスちゃんが可愛いですね。
以上で今回は終了となります。Namazuの次回進捗にご期待ください。
4.参考にしたサイト
5.懸念事項
私の環境では、実は画像の表示が一筋縄にいかず、困っていました。
ソースコードはそのままでも、おそらくソリューションファイルが壊れているとTexture2Dを正しく読み込んでくれないという内容でした。
具体的には、using Microsoft.Xna.Framework.Graphics;でTexture2Dはインポート出来ているはずなのですがBuild&Deployしてみると、BuildとDeployは成功するのですが実行時に下の画像のようなエラーが出るというものです。
Unhandled Exception:
Microsoft.Xna.Framework.Content.ContentLoadException:Could not load asset as a non - content file!
原因が分からないので、もしこれを読んでいる方の中に原因が特定できる方がいらっしゃれば是非教えてください。
(2016/8/9追記)
まだ完全には特定できていませんが、このエラーは素材の読み込みに失敗したときに出るものです。(英文そのままですが)
Monogame Pipelineで正しい設定でビルドしないとこのエラーが起きるようです。
主な原因としては、
- Processorに指定する型が実際に使うものと違う
例えば、音楽素材をSoundEffectクラスで扱うときにProcessorをSongにしてビルドしてしまうなど - ファイルを追加するとき、Add a linkにした際に正しいリンクが指定されていない
念のため、Add a linkではなくcopy the fileを使うようにしましょう
などが考えられます。
引き続き、詳しい方がいらっしゃれば是非コメントでお願いします。
質問や不明な点等あればコメントまたはTwitterで是非ご指摘ください。
Twitter→@blonde_namazu