ms dx 如果这也算是游戏,比那个掐泡泡的还要无聊

纯备忘,刚刚好找到的例子

将一张图片转呀转,WSAD可以移动,ESC退出

用到的程序集

System

System.Data

System.Drawing

System.Windows.Forms

Microsoft.DirectX

Microsoft.DirectX.Direct3D

Microsoft.DirectX.Direct3DX

Microsoft.DirectX.DirectInput

一张显示小球的图片 my.bmp,放在运行exe相同目录:Game2D\bin\Debug

 

Game.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.DirectInput;



namespace Game2D
{
    class Game : Form
    {
        ///代表了你的显示卡,也代表了你的绘图空间。
        Microsoft.DirectX.Direct3D.Device d3dev = null;
        ///DX9 Graphics的灵魂所在,它提供了一系列的运算和绘画功能,让你可以轻松的把想呈现在荧幕上的画面画出来
        Sprite sprite;
        ///就是一般3D游戏中贴在3D模型上的材质,在这里,它成了你的物件的图像的寄身所在。
        ///在DX9 Graphics里面,每一个Sprite事实上是一个平面的正方形polygon,
        ///其normal永远和z-轴平行(就像以前Doom 2 时代的 Billboard object 一般永远对着镜头。
        ///只在这里,我们的镜头也是永远不变的跟z-轴平行着的),
        ///其画像就是贴在上面的Texture了。
        Texture myTexture;
        ///从起源点(Origin, X=0, Y=0, Z=0),发射向某个点(X=nx, Y=ny, Z=nz)的假想线
        /// 在2D 环境下,我们可以把它当作一个点(point),因为我们只对其X和Y值有兴趣(Z值无视),
        /// 我们有两个Vector3,pos和ctr。
        /// pos是用来代表我们的Sprite在这个2D空间的位置,
        /// ctr则是Sprite的中心点。为何要使用中心点呢?那是因为,
        /// 如果你要使用Sprite的Origin(X=0, Y=0)来代表它的位置的话,
        /// 你得同时keep track 它的宽和高,十分麻烦,而使用中心点的话,你只需注意一个point,方便很多。
        /// pos被设定为 X=400,Y=300,正处在画面中间(我们的画面,也就是Direct3D.Device.Viewport, 会被设定为 800x600)
        Vector3 ctr;
        Vector3 pos = new Vector3(400.0f, 300.0f, 0.0f);
        float angle = 0.0f;

        /// 用来进行transfrmation的,例如旋转(rotation),放大缩小(scaling),以及转移位置(translation)。
        /// Sprite 的Transformation功能有个Bug, 导致任何Sprite.Rotation 的运算都会以viewport的(0,0)作为中心点,
        /// 而忽略了你所选择的中心点(例如 X=400, Y=300),所以我们不能使用Sprite的回旋功能。
        /// 其解决方法就是使用两个transformation,先 rotate 再 translate 到你想要的位置。
        Matrix transformmatrix, rotatematrix, finalmatrix;
        //--input---
        Microsoft.DirectX.DirectInput.Device kb;

        public Game()
        {
            this.ClientSize = new Size(800, 600);
            this.Text = "The Game - Managed DirectX";
        }

        /// 启动和初始化Direct3D
        public bool InitD3D()
        {
            try
            {
                //PresentParameters (发音 Pri-sent,“呈现”的意思)是用来决定Direct3D如何描绘画面的设定的structure
                PresentParameters pp = new PresentParameters();
                //pp.Windowed决定你的游戏是Full Screen还是Windowed。
                //要注意的是,如果你把Windowed设定为true,所有关于backbuffer的设定将会被无视,
                //而viewport size和color depth将会跟随现有windows的Client Size和deskto color depth
                // 全屏时,不知道是不是因为我的是宽屏,出错了,改成窗口显示
                pp.Windowed = true;
                pp.BackBufferWidth = 800;
                pp.BackBufferHeight = 600;
                pp.SwapEffect = SwapEffect.Discard;
                //BackBuffer Format采用Alpha8, Red8, Green8, Blue8,表示Sprite可以有256阶段的透明度(8-bit Alpha)。
                //如果你的BackBuffer Format选择了错误的设定,会导致你的D3D初始化失败的,要注意。
                pp.BackBufferFormat = Format.A8R8G8B8;

                //设定好PresentParameters 后就可以制造一个D3D Device了
                d3dev = new Microsoft.DirectX.Direct3D.Device(0, //adapter id, 0 for default, 也就是你的主显示卡
                               Microsoft.DirectX.Direct3D.DeviceType.Hardware,//如果你的显示卡友支援完整的DX9功能,你可以使用硬体加速,不然就只能使用软件模拟(很慢的)
                               this, //这个游戏的视窗本身  
                               CreateFlags.SoftwareVertexProcessing, //不支援Shader的显示卡只能使用软件模拟的VP了
                               pp //PresentParameter
                               );

                //接下来是制造Sprite和Texture物件,由于它们都会用到D3D Device物件,所以必须在制造了D3D Device 才能制造这两个物件。
                sprite = new Sprite(d3dev);
                //在制造Texture物件前,你得先把一个图画加入在project里面,作为Texture的画像
                //我个人喜欢使用PNG格式,因为它支援透明背景,同时也不会像BMP般占大量空间,
                //却也不会像JPG般压缩了之后会出现边缘模糊的情形。记着你的图形最好是正方形,
                //而且尺寸必须是2的倍数(2,4,8,16,32,64,128,256。。。。),
                //不然D3D会把你的图画缩小到最近似的2的倍数,例如你的图画是300x300的话,
                //会被缩小成256x256。而在某些function中,不是2的倍数的texture尺寸会导致function fail。
                myTexture = TextureLoader.FromFile(d3dev, "my.bmp");
                //通过一个Bitmap object来获取texture图像的尺寸(奇怪的是我无法通过Texture object来获得这些讯息,
                //有知道如何直接从Texture object获得图像来源的尺寸的高手请指教),一边计算出Texture的中心点。
                System.Drawing.Image bmp = System.Drawing.Image.FromFile("my.bmp");
                ctr = new Vector3(bmp.Width / 2, bmp.Height / 2, 0.0f);

                //最后,我们制造一个键盘物件,并通过SetCooperativeLevel设定其运作个性(Behavior),
                //以避免当玩家按 Alt-Tab 跳回桌面时,游戏仍然死抓着键盘控制权不放,造成操作上的不便。
                kb = new Microsoft.DirectX.DirectInput.Device(SystemGuid.Keyboard);
                kb.SetCooperativeLevel(this,
                                       CooperativeLevelFlags.NonExclusive |
                                       CooperativeLevelFlags.Background);

                //Acquire() 是确定键盘处在准备妥当的状态(没有别的program正在抓着键盘控制权)。
                kb.Acquire();

                return true;
            }
            catch (DirectXException)
            {
                return false;
            }
        }

        /// 以上Function我只检测键盘的5个键:WASD 移动物件(Sprite)的 pos,Escape键结束游戏。
        /// 要注意的是,UpdateGame 里面就只纯粹更新状态,
        /// 别把描绘的工作掺杂在里面,以免你无法迅速的完成工作而导致游戏出现控制反应迟缓的现象。
        internal void UpdateGame()
        {
            KeyboardState ks = kb.GetCurrentKeyboardState();
            if (ks[Key.Escape])
            {
                this.Close();
                return;
            }
            if (ks[Key.A])
            {
                pos.X -= 5;
                if (pos.X < 0)
                    pos.X = 0;
            }
            if (ks[Key.D])
            {
                pos.X += 5;
                if (pos.X > d3dev.Viewport.Width)
                    pos.X = d3dev.Viewport.Width;

            }
            if (ks[Key.W])
            {
                pos.Y -= 5;
                if (pos.Y < 0)
                    pos.Y = 0;
            }
            if (ks[Key.S])
            {
                pos.Y += 5;
                if (pos.Y > d3dev.Viewport.Height)
                    pos.Y = d3dev.Viewport.Height;
            }
            //图片旋转的角度
            angle += 0.1f;
            if (angle >= 360)
            {
                angle = 0;
            }
            Render();
        }

        /// 最后,把游戏状态描绘成画面,然后呈现在荧幕
        public void Render()
        {
            //首先清空画面,填上Color.xxxx 的颜色
            d3dev.Clear(ClearFlags.Target, Color.SkyBlue, 1.0f, 0);
            //然后就启动D3D Device的描绘机制,当你呼叫Device.Begin()时,
            //系统就会自动的锁定你的Frame Buffer(显示卡里面属于你的游戏的记忆空间),
            //以免被其它程式,或你的游戏里的其他Thread (如果你采用 Multi Threaded 设计)干扰
            d3dev.BeginScene();
            //Sprite本身也采用类似的locking来锁定自己的Texture Buffer。 
            //SpriteFlags.AlphBlend是告诉显示卡,我们要使用Alph channel, 来制造出透明效果
            sprite.Begin(SpriteFlags.AlphaBlend);
            //由于Sprite的Bug,我们不能使用它内建的Rotation功能,所以我们使用了两个Matrix,
            //把它们Multiply起来,再直接把结果set在Sprite.Transformation, 
            //Sprite 就会乖乖的完成你指定的变形(以 X=400,Y=300 为中心点,绕着自己的中心缓缓的旋转)。
            rotatematrix.RotateZ(angle);
            transformmatrix.Translate(pos);
            finalmatrix = Matrix.Multiply(rotatematrix, transformmatrix);
            sprite.Transform = finalmatrix;
            sprite.Draw(myTexture, Rectangle.Empty, ctr, Vector3.Empty, Color.White);
            //指令告诉显示卡,你已经完成工作,可以解开Frame Buffer的锁定
            sprite.End();
            d3dev.EndScene();

            //Flip Buffer, 因为这游戏是 Double-buffered 的,也是说它有两个Frame Buffer,
            //一个在前也就是显示在荧幕上的Front Buffer, 另一个是在荧幕显示之外的 Back Buffer。
            //你的一切更新都是在 Back Buffer 里进行的,当完成更新之后,Present() 就会把两个Buffer调换,
            //荧幕上就会显示出最新的画面,而你就继续将已经过时了的画面清掉,描绘下一个画面。
            //这么做得好处是你不必等待荧幕刷新时才能进行描绘,而且也能避免画面撕扯(tearing)的现象。
            d3dev.Present();
        }
    }
}

Program.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace Game2D
{
    class Program
    {
        static void Main(string[] args)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            using (Game MainForm = new Game())
            {
                if (!MainForm.InitD3D())
                {
                    MessageBox.Show("Failed to initialize Direct 3D Device");
                    return;
                }
                MainForm.Show();

                while (MainForm.Created)
                {
                    MainForm.UpdateGame();
                    Application.DoEvents();
                }
            }
            //Application.Exit();
        }
    }
}



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值