TOP

ただいま開発中です

フォローはどうぞお気楽に!

SoundCloud (ゲームBGM集)

今後、力をいれていきます。

PSMゲーム
Bloodred Wyvern (ブラッドレッドワイバーン)
Bloodred Wyvern 2
Gravity Anomaly Zone 不可思議重力帯
その他
PlayStation®Mobile関連リンク集
PlayStation®Mobile学習日記

XBLIG
BLASTER AND AMETHYST
BLASTER AND MORION
LEUCISTIC WYVERN
Bioerosion
URGENT EVASION 360
The Undead Syndrome / TUS 2
Dark Storm Blast 360

その他
Making Of The Undead Syndrome[3DCG]
Making Of The Undead Syndrome2
XNA関連リンク集
xna学習日記
第1〜3話
第4〜5話
第6〜7話
第8〜9話
第10〜12話
第13〜14話
第15話

ブラウザゲーム
発火少年の地面焦がし
MAGICAL METEOR SHOWER

メタセコイア備忘録
東日本大震災(Aftermath of the 2011 Tohoku earthquake and tsunami)

ムカゴソフトウェア開発
e-mail:cqp00202@nifty.ne.jp

[TOP] [xna学習日記TOP] [前へ] [次へ]
2009年04月09日:第8話:ゲームパッドで立体モデルをグリグリ動かす

前回のサンプルコードに、ゲームパッドで立体モデルを動かすコードを追加してみた。

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace WindowsGame1
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Model samplemodel;
        Vector3 model_pos = Vector3.Zero; //立体モデルの位置

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

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            //モデルの読み込み
            samplemodel = Content.Load<Model>("sample_model");
        }

        protected override void UnloadContent()
        {
        }

        // デフォルトで1/60秒固定で呼び出される
        protected override void Update(GameTime gameTime)
        {
            //if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit();

            //ゲームパッドに関する情報取得用
            GamePadState gamepadstate = GamePad.GetState(PlayerIndex.One);

            //trueの場合、ゲームパッドが接続されている
            if (gamepadstate.IsConnected)
            {
                //終了
                if (gamepadstate.Buttons.Back == ButtonState.Pressed) this.Exit();
                
                //左スティックの位置を取得
                model_pos.X += gamepadstate.ThumbSticks.Left.X * 0.2f;
                model_pos.Z -= gamepadstate.ThumbSticks.Left.Y * 0.2f;

            }
            
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            foreach (ModelMesh mesh in samplemodel.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    //デフォルトのライティングを有効
                    effect.EnableDefaultLighting();

                    //ワールド行列を設定
                    //Matrix.CreateTranslationメソッドで、移動用のマトリックスを作成
                    effect.World = Matrix.CreateTranslation(model_pos);
                    
                    //ビュー行列を設定
                    effect.View = Matrix.CreateLookAt(new Vector3(16.0f, 8.0f, 18.0f), Vector3.Zero, Vector3.Up);

                    //射影行列を設定
                    effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f),
                                                                            GraphicsDevice.Viewport.AspectRatio,
                                                                            1.0f, 10000.0f);

                    //スペキュラカラーの設定
                    effect.SpecularColor = new Vector3(0.4f, 0.4f, 0.4f);
                }
                mesh.Draw();
            }
            base.Draw(gameTime);
        }
    }
}

前回、サンプルコードに追加した、leftmoveフィールドは不要となったので削除した。
前回のサンプルコードのこの1行(削除)。

bool leftmove = false;          //Uターン用  

今回、ゲームパッドに関する処理を記述したのは、Update()メソッドである(他のメソッドは、前回のサンプルコードと変更無し)。

//if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit();

上の1行は、元々テンプレートが自動的に生成したコードで、ゲームパッドのBackボタンを押すと、プログラムが終了する処理である。
このコードは、新たに追加したゲームパッド関連処理の方に記述し直したので、コメントとした。

新たに追加したゲームパッド関連処理は・・・

//ゲームパッドに関する情報取得用
GamePadState gamepadstate = GamePad.GetState(PlayerIndex.One);

//trueの場合、ゲームパッドが接続されている
if (gamepadstate.IsConnected)
{
    //終了
    if (gamepadstate.Buttons.Back == ButtonState.Pressed) this.Exit();
                
    //左スティックの位置を取得
    model_pos.X += gamepadstate.ThumbSticks.Left.X * 0.2f;
    model_pos.Z -= gamepadstate.ThumbSticks.Left.Y * 0.2f;

}

Xbox LIVEインディーズゲームとしてリリースする場合、PlayerIndex.Oneだけでは無く、複数のゲームパッドに対応させる必要があります。
詳細は、プレイテストとピアレビューでチェックすべき項目のチェックリストを参照して下さい。

2010年5月24日追記

ゲームパッドの左スティックはこれ。

これだけのコードで、スティックの傾き具合にもきちんと対応している。
xnaは、ゲームパッドに関する情報を、かなり簡単に取得できるようだ。

2009年04月11日:第9話:ゲームパッドで立体モデルをグリグリ動かす2

前回のサンプルコードを三人称視点に変更した。
また、それに合わせて、ゲームパッドに関する処理を修正。
自キャラとなる立体モデルも、平行移動だけでは無くて、Y軸を中心とした回転を加えてみた(回転行列x移動行列)。

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace WindowsGame1
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Model samplemodel;   //自キャラの立体モデル
        Model samplemap;     //マップの立体モデル

        Vector3 camera_pos;               //カメラの位置
        Vector3 model_pos = Vector3.Zero; //自キャラの位置
        float model_rotate_y;             //自キャラの角度

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

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            //モデルの読み込み
            samplemodel = Content.Load<Model>("sample_model"); //自キャラ
            samplemap   = Content.Load<Model>("sample_map");   //マップ

        }

        protected override void UnloadContent()
        {
        }

        // デフォルトで1/60秒固定で呼び出される
        protected override void Update(GameTime gameTime)
        {

            //ゲームパッドに関する情報取得用
            GamePadState gamepadstate = GamePad.GetState(PlayerIndex.One);
            {
                //trueの場合、ゲームパッドが接続されている
                if (gamepadstate.IsConnected)
                {
                    //終了
                    if (gamepadstate.Buttons.Back == ButtonState.Pressed) this.Exit();

                    //立体モデルを左右に回転
                    model_rotate_y -= gamepadstate.ThumbSticks.Left.X * 0.05f;

                    //立体モデルの前進と後退
                    Vector3 vec3 = new Vector3(0, 0, gamepadstate.ThumbSticks.Left.Y * 3.0f);
                    vec3 = Vector3.Transform(vec3, Matrix.CreateRotationY(model_rotate_y)); //正面
                    model_pos.Z += vec3.Z;
                    model_pos.X += vec3.X;
                }
            }

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            //カメラの位置を更新
            camera_pos = Vector3.Transform(new Vector3(0, 0, -8), Matrix.CreateRotationY(model_rotate_y))
                       + model_pos;
            
            //マップの描画
            DrawModel(samplemap, Matrix.CreateTranslation(Vector3.Zero));

            //自キャラの描画
            DrawModel(samplemodel, Matrix.CreateRotationY(model_rotate_y) 
                                   * Matrix.CreateTranslation(model_pos));

            base.Draw(gameTime);
        }


        //立体モデルの描画
        void DrawModel(Model model, Matrix world)
        {
            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    //デフォルトのライティングを有効
                    effect.EnableDefaultLighting();

                    //ワールド行列を設定
                    effect.World = world;

                    //ビュー行列を設定
                    effect.View = Matrix.CreateLookAt(camera_pos, model_pos, new Vector3(0.0f, 1.0f, 0.0f));

                    //射影行列を設定
                    effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f),
                                                                            GraphicsDevice.Viewport.AspectRatio,
                                                                            1.0f, 10000.0f);

                    //スペキュラカラーの設定
                    effect.SpecularColor = new Vector3(0.4f, 0.4f, 0.4f);

                }
                mesh.Draw();
            }
        }
    }
}

カメラの位置とアングルを計算する部分と、自キャラの描画部分・・・

//カメラの位置を更新
camera_pos = Vector3.Transform(new Vector3(0, 0, -8), Matrix.CreateRotationY(model_rotate_y))
+ model_pos;

//自キャラの描画
DrawModel(samplemodel, Matrix.CreateRotationY(model_rotate_y)
* Matrix.CreateTranslation(model_pos));

Matrix.CreateRotationYメソッドの引数(角度)は、ラジアン単位で渡すべきです。
model_rotate_yの値をMathHelper.ToRadiansメソッド(度をラジアンに変換)を用いて、ラジアン単位に変換してから渡して下さい。
また、model_rotate_yの値が360度を超えたり、0度未満になった時の処理も、きちんと組んだ方が良いと思います。

2010年5月24日追記

今回、新たに迷路の立体モデル「sample_map1.x」を追加した(DirectXのX形式ファイル)。

立体モデル「sample_map1.x」ダウンロード
http://mukago.game.coocan.jp/sample/sample_map.x

この立体モデルは、コンテント・パイプラインを使って、プロジェクトに組み込む必要がある。
詳細は、第4話:コンテント・パイプラインを参照。

アセット名は、デフォルトの「sample_map」とした。

また、この立体モデルは、左の画像のビットマップファイル(サイズは64x64)をテクスチャとしている。ファイル名は「map1.bmp」。

テクスチャ「map1.bmp」ダウンロード
http://mukago.game.coocan.jp/sample/map1.bmp

このビットマップファイルは、プログラム中で直接操作しない。
よって、プロジェクトに組み込む際に、コンテント・パイプラインを利用しない方が良いだろう。

そこで、エクスプローラ等のファイラを使って、プロジェクトのContentフォルダに、手動でファイルをコピペする。
詳細は、第6話:補足を参照。


[TOP] [xna学習日記TOP] [前へ] [次へ]
〜 様々なデジタルコンテンツを制作しています 〜
MUKAGOSOFTWARE DEVELOPMENT
XBOX360の開発環境「XNA Game Studio」を弄くってみる・・・
xna学習日記