XNA教程(二)—— Into the 2D World

2024-01-19 00:32
文章标签 教程 world 2d xna

本文主要是介绍XNA教程(二)—— Into the 2D World,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  作者:Mike Fleishauer & clayman
本文版权归原作者所有,仅供个人学习使用,请勿转载,勿用于任何商业用途。
由于本人水平有限,难免出错,不清楚的地方请大家以原著为准。欢迎大家和我多多交流。
Blog:
http://blog.csdn.net/soilwork
clayman_joe@yahoo.com.cn 
special thanks to Mike Fleishauer ^_^

        在第一章里,我们介绍了关于 XNA 的一些基础知识。但坦白的说,至今为止,我们还没有编写任何代码,而且只创建了一个单调的蓝色屏幕。
         这一章,我们将尝试在屏幕上绘制一些东西,简单的 2D 图形。虽然 2D 游戏的时代已经渐渐远去,但即使你编写一个全 3D 的游戏,也不得不处理处理一些 2D 图形,比如简单的选项菜单、 HUD head up displays )等等。好了让我们开始把。
         打开上一章创建的项目,当然,你也可以创建一个新 XNA 项目。把解决方案改名为“ Chapter2”,把工程和Game1.cs 都重命名为“ Sprite ”,当弹出确认更改文件名的对话框时,点击确认。
         接下来,我们将在屏幕上绘制一张 2D 图片。但在这之前,需要介绍一点关于 Sprite 的概念。
什么是 Sprite
Sprite ,也称为精灵,是一个直接绘制到屏幕上的 2D 图形。在传统的 2D 游戏中,你所看到的一切几乎都是 sprite 。但在 3D 游戏中,比如 Halo sprite 逐渐演变为了用于增加 3D 图形视觉效果的纹理。在讨论 3D 图形时我们会详细讲解它。现在,简单的把 sprite 认为是 2D 图形就可以了。
        
         继续,我们将把一些外部资源添加到工程中,为了方便管理,统一把资源放到一个单独的文件夹中。在 Solution Explorer 邮件点击 Add->New Floder ,命名为 Graphics 。接下来,邮件点击新创建的文件夹 Add->Existion Item…. 在弹出窗口中,导航到安装 MC2 源代码的目录下,在 /Source/Data/Art 中,选择 mcl_splashscreen_planet_2.tga. 文件。(当然,可以选择一张任何你喜欢的图片)。
         接下来,编写代码:
namespace Chapter2
{
    partial class Sprites : Microsoft.Xna.Framework.Game
    {
        private Microsoft.Xna.Framework.Graphics.SpriteBatch _sb;
        private Microsoft.Xna.Framework.Graphics.Texture2D _sprite;
        public Sprites()
        {
            InitializeComponent();
            _sb = new SpriteBatch(this.graphics.GraphicsDevice);
            _sprite = Texture2D.FromFile(this.graphics.GraphicsDevice, "../../Graphics/mcl_splashscreen_planet_2.tga");
        }
        protected override void Update()
        {
            float elapsed = (float)ElapsedTime.TotalSeconds;
            UpdateComponents();
        }
        protected override void Draw()
        {
              if (!graphics.EnsureDevice())
                return;
            graphics.GraphicsDevice.Clear(Color.Black);
            graphics.GraphicsDevice.BeginScene();
            _sb.Begin();
            _sb.Draw(_sprite, new Vector2(0.0f, 0.0f), Color.Red);
            _sb.End();
            DrawComponents();
            graphics.GraphicsDevice.EndScene();
            graphics.GraphicsDevice.Present();
        }
    }
}
(加粗部分为我们添加的代码)
         这些代码是什么意思呢?
         首先,我们为 Sprite 类添加了两个全新的成员:
private Microsoft.Xna.Framework.Graphics.SpriteBatch _sb;
private Microsoft.Xna.Framework.Graphics.Texture2D _sprite;
     _sb 是一个SpriteBatch对象。SpriteBatch对象代表了一批sprite,并且将在同样的状态设置下,绘制他们。大多数情况下,几乎所有的sprite都在同一个批次中。
     _sprite 实际上是一张2D的纹理。它代表了一张将要绘制到屏幕上的图片。我们稍后将讨论不同类型的纹理,现在,只需知道2D纹理储存了在X和Y方向上,每个像素的颜色信息。也可以就把Texture2D认为是一张图片。XNA直接支持jpg,tga,dds,bmp,png格式的文件作为纹理。
_sb = new SpriteBatch(this.graphics.GraphicsDevice);
     使用GraphicsDevice对象作为参数,实例化SpriteBatch。这里,参数的含义表示以后将用哪一个(一个程序中可以有多个GraphicsDevice)GraphicsDevice对象绘制_sb。
_sprite = Texture2D.FromFile(this.graphics.GraphicsDevice, "../../Graphics/mcl_splashscreen_planet_2.tga");
         这行代码把图片加载到内存中,实例化 Texture2D 对象。同样把当前的 graphics device 和图片的路径作为参数。如果在给定路径没有找到所要的图片,那么这个方法将抛出一个异常。
graphics.GraphicsDevice.Clear(Color.Black);
         把屏幕清理为黑色。上一节已经介绍过如何使用这个方法。现在我会告诉你为什么需要调用这个方法。如果把渲染比作绘图,那么显存就是我们的画板,通常把用于绘图的显存称为帧缓冲,如何不清理帧缓冲,那么上次在帧缓冲中绘制的图形仍然会保留在其中,并且这些数据处于一种不确定的状态。假设我们下次只在屏幕的左上角绘制图形,那么显示时,除了进行绘制的区域,其他部分可能会显示一些随机数据,相当于我们在一块绘制了大量图形的旧画板上绘图。因此,需要用 Clear 方法对帧缓冲进行初始化,填充为某个我们希望的背景颜色。
_sb.Begin();
_sb.Draw(_sprite, new Vector2(0.0f, 0.0f), Color.Red);
_sb.End();        
         和之前提到的 BeginScenne EndScene 一样, _sb.Begin _sb.End 方法告诉图形设备我们将要绘制 sprite ,所有绘制 sprite 的代码都必须在这两个方法之间。 Draw 方法是真正绘制图形的地方。这里的参数告诉显卡从坐标位置为( 0 0 )的地方开始绘制 sprite 。注意,绘制 sprite 的,所使用的是屏幕坐标系,这意味着屏幕中的每个像素对应一个( x y , 屏幕左上角的坐标总是( 0 0 ),而右下的坐标则取决于屏幕分辨率,如果分辨率为 1024 x 768 那么右下的坐标就是( 1024 768 )。绘制 sprite 的位置应该在这两个坐标之间。
         运行程序看看吧:

         虽然依旧很单调,但总是有了进步。
         这里你可能会有一些问题:为什么原来蓝色的天空,现在“燃烧”了起来。
         注意看绘制 sprite 的代码,最后一个参数表示了绘制 sprite 时的色调。如果我们把它改为 Color.White 那么将获得和原图一样的效果。你看,使用 XNA 轻易就能实现一些特效。
         再绘制几个 sprite
         现在我们有 4 个相同大小的 sprite 了。你已经掌握了 2D 绘图的基础,足够完成一个 2D 游戏的背景渲染。再次提醒,所有的 2D 绘图操作都因该在 Begin() End() 方法之间,而 SpriteBatch 方法调用又必须在 BeginScene() EndScene() 方法之间。简单的说,应该按照以下顺序:
--       开始渲染 3D 图形
l        渲染 3D 场景
l        开始渲染 2D 图形
n        渲染 2D 图片
l        结束 2D 渲染
--      结束 3D 渲染
         需要记住, 2D 图形的渲染和绘制他们的顺序有关系。在叠加区域,先渲染的图形总是会被后渲染的图形挡住,和在普通画布上绘图的原理一样。这也带领我们进入下一个话题,透明。
Transparent Blits
         首先,如果你要问我 Blits 是什么含意,那么我要告诉你,实际上你不必知道它是什么意思 =.= Blit 的含义来自于 BLT ,表示 Block Transfer ,意思是把一个平面的一部分复制到另一个平面。好了,关键的问题就在于我们如何把图片中,不透明的部分复制到已有图片上。
         为了渲染一个带透明效果的 sprite ,先来做一些辅助工作。首先,打开 windows 中的绘图板,任意绘制一个图形:
         哈哈,我绘制图形的能力确实很惊人,不是吗 ^_^ 。接下来,再创建一张同样大小的图片。上一张图片是我们希望显示的部分,而现在这张图片则作为它的透明遮罩:
         一般情况下,遮罩里白色部分是不透明的,而黑色部分则表示透明区域。把两张图片分别保存为 uglyStar.jpg uglyStarMask.jpg 。为了方便使用,把他们都添加到 Grahics 文件夹中。
         现在打开 DirectX SDK 中的 DxTex.exe 程序(它位于 sdk 安装路径的 Utilities/Bin/x86 件夹下)。选择 File->New Texture… ,在弹出的窗口中,把纹理尺寸设置为 32x32 ,把 Surface/Volume 格式设置为 Unsigned 32-bit: A8R8G8B8 ,如图所示:
         选择“ Open onto this surface”, 打开我们之前创建的红色星星 uglyStar.jpg
         选择“ Open onto Alpha Channel of this Surface” ,打开 uglyStarMask.jpg
         最后把文件保存为 star.dds ,并添加到 Graphics 文件夹。
         好了,现在有了一张带透明通道的图片,如何使用他呢。把它绘制到之前的天空上吧。添加如下代码:
………………….
private Microsoft.Xna.Framework.Graphics.Texture2D _spriteStar;
………………… .
public Sprites()
{
     ………………………
     _spriteStar = Texture2D.FromFile(graphics.GraphicsDevice, "../../Graphics/star.dds");
}
protected override void Draw()
{           
     …………… ..
     graphics.GraphicsDevice.BeginScene();          
    _sb.Begin(SpriteBlendMode.AlphaBlend);
     _sb.Draw(_sprite, new Vector2(0.0f, 0.0f), Color.White);
     _sb.Draw(_sprite, new Vector2(_sprite.Width, 0.0f), Color.White);
     _sb.Draw(_sprite, new Vector2(_sprite.Width, _sprite.Height), Color.White);
     _sb.Draw(_sprite, new Vector2(0.0f, _sprite.Height), Color.White);
    _sb.Draw(_spriteStar, new Vector2(50.0f, 50.0f), Color.Yellow);
     _sb.End();
  ……………………………
}
         运行程序,你因该可以看到下图所示的结果 :

         注意到我们只显示了红色的部分没有?这都是透明遮罩的功劳。简要来说,你使用 DirectX 纹理工具,告诉了图片哪些部分需要渲染,哪些部分是透明的,注意这里使用了 dds 格式的文件,而不是 bmp 格式。
         你因该对这行代码比较感兴趣:
_sb.Begin(SpriteBlendMode.AlphaBlend);
         使用 AlphaBlend 作为 SpriteBlendMode 参数,会告诉 XNA 将要渲染一些带透明效果的图片。还记得我先前说过“ 大多数情况下,几乎所有的sprite都在同一个批次中”吗,好吧,我撒谎了-_-b。Alpha混合通常需要进行额外的计算,因此,应该把需要进行Alpha混合的sprite单独作为一个批次。一个批次用来绘制(静态)背景图片,另一个用来绘制带透明效果的前景物品。作为一条规则,你应该总是把需要alpha混合的sprite作为一个批次:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Components;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
namespace Chapter2
{
    partial class Sprites : Microsoft.Xna.Framework.Game
    {
        private Microsoft.Xna.Framework.Graphics.SpriteBatch _sbBackground;
        private Microsoft.Xna.Framework.Graphics.SpriteBatch _sbForeground;
        private Microsoft.Xna.Framework.Graphics.Texture2D _sprite;
        private Microsoft.Xna.Framework.Graphics.Texture2D _spriteStar;
        public Sprites()
        {
            this.AllowUserResizing = true;
            this.IsMouseVisible = true;
            InitializeComponent();
            _sbBackground = new SpriteBatch(this.graphics.GraphicsDevice);
            _sbForeground = new SpriteBatch(this.graphics.GraphicsDevice);
            _sprite = Texture2D.FromFile(this.graphics.GraphicsDevice, "../../Graphics/mcl_splashscreen_planet_2.tga");
            _spriteStar = Texture2D.FromFile(graphics.GraphicsDevice, "../../Graphics/star.dds");
        }
        protected override void Update()
        {
             float elapsed = (float)ElapsedTime.TotalSeconds;
            UpdateComponents();
        }
        protected override void Draw()
        {
             if (!graphics.EnsureDevice())
                return;
            graphics.GraphicsDevice.Clear(Color.Black);
            graphics.GraphicsDevice.BeginScene();
            _sbBackground.Begin();
            _sbBackground.Draw(_sprite, new Vector2(0.0f, 0.0f), Color.White);
            _sbBackground.Draw(_sprite, new Vector2(_sprite.Width, 0.0f), Color.White);
            _sbBackground.Draw(_sprite, new Vector2(_sprite.Width, _sprite.Height), Color.White);
            _sbBackground.Draw(_sprite, new Vector2(0.0f, _sprite.Height), Color.White);          
            _sbBackground.End();
            _sbForeground.Begin(SpriteBlendMode.AlphaBlend);
            _sbForeground.Draw(_spriteStar, new Vector2(50.0f, 50.0f), Color.White);
            _sbForeground.End();
            DrawComponents();
            graphics.GraphicsDevice.EndScene();
            graphics.GraphicsDevice.Present();
        }
    }
}
         好了,第二部分到次结束,下一章,我们将让 sprite 动起来~~。
 

这篇关于XNA教程(二)—— Into the 2D World的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/620745

相关文章

深度解析Spring AOP @Aspect 原理、实战与最佳实践教程

《深度解析SpringAOP@Aspect原理、实战与最佳实践教程》文章系统讲解了SpringAOP核心概念、实现方式及原理,涵盖横切关注点分离、代理机制(JDK/CGLIB)、切入点类型、性能... 目录1. @ASPect 核心概念1.1 AOP 编程范式1.2 @Aspect 关键特性2. 完整代码实

Java Web实现类似Excel表格锁定功能实战教程

《JavaWeb实现类似Excel表格锁定功能实战教程》本文将详细介绍通过创建特定div元素并利用CSS布局和JavaScript事件监听来实现类似Excel的锁定行和列效果的方法,感兴趣的朋友跟随... 目录1. 模拟Excel表格锁定功能2. 创建3个div元素实现表格锁定2.1 div元素布局设计2.

SpringBoot连接Redis集群教程

《SpringBoot连接Redis集群教程》:本文主要介绍SpringBoot连接Redis集群教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 依赖2. 修改配置文件3. 创建RedisClusterConfig4. 测试总结1. 依赖 <de

Nexus安装和启动的实现教程

《Nexus安装和启动的实现教程》:本文主要介绍Nexus安装和启动的实现教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、Nexus下载二、Nexus安装和启动三、关闭Nexus总结一、Nexus下载官方下载链接:DownloadWindows系统根

CnPlugin是PL/SQL Developer工具插件使用教程

《CnPlugin是PL/SQLDeveloper工具插件使用教程》:本文主要介绍CnPlugin是PL/SQLDeveloper工具插件使用教程,具有很好的参考价值,希望对大家有所帮助,如有错... 目录PL/SQL Developer工具插件使用安装拷贝文件配置总结PL/SQL Developer工具插

Java中的登录技术保姆级详细教程

《Java中的登录技术保姆级详细教程》:本文主要介绍Java中登录技术保姆级详细教程的相关资料,在Java中我们可以使用各种技术和框架来实现这些功能,文中通过代码介绍的非常详细,需要的朋友可以参考... 目录1.登录思路2.登录标记1.会话技术2.会话跟踪1.Cookie技术2.Session技术3.令牌技

Python使用Code2flow将代码转化为流程图的操作教程

《Python使用Code2flow将代码转化为流程图的操作教程》Code2flow是一款开源工具,能够将代码自动转换为流程图,该工具对于代码审查、调试和理解大型代码库非常有用,在这篇博客中,我们将深... 目录引言1nVflRA、为什么选择 Code2flow?2、安装 Code2flow3、基本功能演示

Java Spring 中的监听器Listener详解与实战教程

《JavaSpring中的监听器Listener详解与实战教程》Spring提供了多种监听器机制,可以用于监听应用生命周期、会话生命周期和请求处理过程中的事件,:本文主要介绍JavaSprin... 目录一、监听器的作用1.1 应用生命周期管理1.2 会话管理1.3 请求处理监控二、创建监听器2.1 Ser

MySQL 安装配置超完整教程

《MySQL安装配置超完整教程》MySQL是一款广泛使用的开源关系型数据库管理系统(RDBMS),由瑞典MySQLAB公司开发,目前属于Oracle公司旗下产品,:本文主要介绍MySQL安装配置... 目录一、mysql 简介二、下载 MySQL三、安装 MySQL四、配置环境变量五、配置 MySQL5.1

MQTT SpringBoot整合实战教程

《MQTTSpringBoot整合实战教程》:本文主要介绍MQTTSpringBoot整合实战教程,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录MQTT-SpringBoot创建简单 SpringBoot 项目导入必须依赖增加MQTT相关配置编写