WPF 3Dプログラミング

第6回「キャラを凹凸地形で移動」の巻

WPF 3Dプログラミング WPF 3Dプログラミング WPF 3Dプログラミング

先生「次はVC#で、キャラを凹凸地形の上を歩かせます。
まずは『Identity』で、『Identity』フォルダの『Grass.idt』を開いてください。ツリービューに『Swordsman』と『Grass』の2つのキャラアイテムがありますね。
xamlでは、1つのシーンに複数のキャラなどを表示する場合、別々に分けることができず、1つのxamlファイルに全て含めなくてはいけません」
WPF 3Dプログラミング



先生
タクヤ
WPF 3Dプログラミング WPF 3Dプログラミング WPF 3Dプログラミング
WPF 3Dプログラミング タクヤ「独特な仕様ですね。
『Identity』から『Grass.xaml』に書き出しました。InternetExplorerでのプレビューも正常です」




WPF 3Dプログラミング WPF 3Dプログラミング WPF 3Dプログラミング

先生「VC#で、第4回を参考に、新たなプロジェクトを作ります。
プロジェクト名は『WpfApplication2』にしましょう」
WPF 3Dプログラミング



先生
WPF 3Dプログラミング WPF 3Dプログラミング WPF 3Dプログラミング

ツカサ「第4回のように、テキストエディタで『Grass.xaml』を開いて全て選択コピーし、『Window1.xaml』の『Grid』タグの間に貼り付けて、『デバッグ>実行』メニューで剣士キャラと地面が現れました」 WPF 3Dプログラミング



天使
タクヤ
WPF 3Dプログラミング WPF 3Dプログラミング WPF 3Dプログラミング
WPF 3Dプログラミング タクヤ「前回までのを以下のようにコーディングを真似てみました。
今回はxamlファイルが違っているので、『ModelVisual3D』の剣士の『x:Name』も『Character_Grass_Swordsman』に変更しました」

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
//3Dが使えるようにする
using System.Windows.Media.Media3D;//追加
//タイマーが使えるようにする
using System.Windows.Threading;//追加

namespace WpfApplication2
{
    /// ‹summary›
    /// Window1.xaml の相互作用ロジック
    /// ‹summary›
    public partial class Window1 : Window
    {
        //タイマー
        private DispatcherTimer intervalTimer = new DispatcherTimer();
        //キャラの位置
        Vector3D pos = new Vector3D(0, 0, 0);
        //キャラの向き
        float angle = 0;

        public Window1()
        {
            InitializeComponent();

            //30ミリ秒ごとに、『Update3DEvent』関数を呼び出す
            intervalTimer.Interval = TimeSpan.FromMilliseconds(30);
            intervalTimer.Tick += new EventHandler(Update3DEvent);
            intervalTimer.Start();
        }

        //30ミリ秒ごとに呼ばれる関数
        void Update3DEvent(object sender, EventArgs e)
        {
            if (Keyboard.IsKeyDown(Key.Right))
            {
                //キャラの角度を減算
                angle -= 10;
                //0度を下回ったら360度加算
                if (angle < 0)
                {
                    angle += 360;
                }
            }
            if (Keyboard.IsKeyDown(Key.Left))
            {
                //キャラの角度を加算
                angle += 10;
                //1回転したら360度減算
                if (angle >= 360)
                {
                    angle -= 360;
                }
            }
            //ディグリーからラジアンへ変換
            float radian = toRadian(angle);
            if (Keyboard.IsKeyDown(Key.Up))
            {
                //向いた方向へXとZ座標を加算
                pos.X += (float)(Math.Sin(radian) * 10);
                pos.Z += (float)(Math.Cos(radian) * 10);
            }
            if (Keyboard.IsKeyDown(Key.Down))
            {
                //向いた方向へXとZ座標を減算
                pos.X -= (float)(Math.Sin(radian) * 10);
                pos.Z -= (float)(Math.Cos(radian) * 10);
            }
            //3D行列
            Matrix3D m = new Matrix3D();
            //回転
            Quaternion q = new Quaternion(new Vector3D(0, 1, 0), angle);
            //回転を3D行列にセット
            m.Rotate(q);
            //3D行列に平行移動した位置posをセット
            m.OffsetX = pos.X;
            m.OffsetY = pos.Y;
            m.OffsetZ = pos.Z;
            //3D行列を3D変形行列にセット
            MatrixTransform3D trans = new MatrixTransform3D(m);
            //剣士キャラに移動した変形行列をセット
            Character_Grass_Swordsman.Transform = trans;
        }

        //ディグリー(度)からラジアンへ変換
        private float toRadian(float degree)
        {
            return (float)((float)degree / 360 * Math.PI * 2);
        }
    }
}
            





WPF 3Dプログラミング WPF 3Dプログラミング WPF 3Dプログラミング

先生「WPFで凹凸地形に合わせてキャラを上下させるには、キャラと地面の当たり判定を調べて、交点をキャラのY軸にセットすればよいのです。
以下の赤字のようにコーディングしてください」

        //30ミリ秒ごとに呼ばれる関数
        void Update3DEvent(object sender, EventArgs e)
        {
            (中略)

            //剣士キャラに移動した変形行列をセット
            Character_Grass_Swordsman.Transform = trans;

            //地面と当たり判定
            //pointはキャラの位置
            Point3D point = new Point3D(pos.X, pos.Y, pos.Z);
            //レイの向き
            Vector3D dir = new Vector3D(0, -1, 0);
            //キャラの位置からのレイのセット
            RayHitTestParameters rayparams = new RayHitTestParameters(point, dir);
            //レイが地面Character_Grass_GrassにヒットしたらResultsOfHit関数を呼び出すようにセット
            VisualTreeHelper.HitTest(
                Character_Grass_Grass, null, new HitTestResultCallback(ResultsOfHit), rayparams);

            //カメラ位置
            Camera_Grass.Position = new Point3D(pos.X + 3000, pos.Y + 1000, pos.Z + 3000);
            //カメラの向き
            Camera_Grass.LookDirection = new Vector3D(-3, -0.9, -3);
        }

        //地面とキャラとの距離だけY座標を移動
        private HitTestResultBehavior ResultsOfHit(HitTestResult myresult)
        {
            RayHitTestResult rayResult = myresult as RayHitTestResult;

            if (rayResult != null)
            {
                RayMeshGeometry3DHitTestResult rayMeshResult = rayResult as RayMeshGeometry3DHitTestResult;
                //レイがヒットした場合
                if (rayMeshResult != null)
                {
                    pos.Y = pos.Y + 10 - rayMeshResult.DistanceToRayOrigin;
                    return HitTestResultBehavior.Stop;//Exit
                }
            }

            return HitTestResultBehavior.Continue;
        }
            
WPF 3Dプログラミング



先生
タクヤ
WPF 3Dプログラミング WPF 3Dプログラミング WPF 3Dプログラミング
WPF 3Dプログラミング タクヤ「今回は全然理解できません・・・」



WPF 3Dプログラミング WPF 3Dプログラミング WPF 3Dプログラミング

ツカサ「まずは文法を理解するより、改造できるようにしたらいいんでしょう?」 WPF 3Dプログラミング



天使
WPF 3Dプログラミング WPF 3Dプログラミング WPF 3Dプログラミング

先生「はい、そうです。
私はむしろ、文法の本は最初ほとんど読みませんでした。
今までのプロジェクトはここまで」
WPF 3Dプログラミング



先生

前のページへ HOME 1 2 3 4 5 6 7 8 9 次のページへ