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 Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

沁恒CH32在MounRiver Studio上环境配置以及使用详细教程

目录 1.  RISC-V简介 2.  CPU架构现状 3.  MounRiver Studio软件下载 4.  MounRiver Studio软件安装 5.  MounRiver Studio软件介绍 6.  创建工程 7.  编译代码 1.  RISC-V简介         RISC就是精简指令集计算机(Reduced Instruction SetCom

前端技术(七)——less 教程

一、less简介 1. less是什么? less是一种动态样式语言,属于css预处理器的范畴,它扩展了CSS语言,增加了变量、Mixin、函数等特性,使CSS 更易维护和扩展LESS 既可以在 客户端 上运行 ,也可以借助Node.js在服务端运行。 less的中文官网:https://lesscss.cn/ 2. less编译工具 koala 官网 http://koala-app.

【Shiro】Shiro 的学习教程(三)之 SpringBoot 集成 Shiro

目录 1、环境准备2、引入 Shiro3、实现认证、退出3.1、使用死数据实现3.2、引入数据库,添加注册功能后端代码前端代码 3.3、MD5、Salt 的认证流程 4.、实现授权4.1、基于角色授权4.2、基于资源授权 5、引入缓存5.1、EhCache 实现缓存5.2、集成 Redis 实现 Shiro 缓存 1、环境准备 新建一个 SpringBoot 工程,引入依赖:

Windows环境利用VS2022编译 libvpx 源码教程

libvpx libvpx 是一个开源的视频编码库,由 WebM 项目开发和维护,专门用于 VP8 和 VP9 视频编码格式的编解码处理。它支持高质量的视频压缩,广泛应用于视频会议、在线教育、视频直播服务等多种场景中。libvpx 的特点包括跨平台兼容性、硬件加速支持以及灵活的接口设计,使其可以轻松集成到各种应用程序中。 libvpx 的安装和配置过程相对简单,用户可以从官方网站下载源代码

PHP APC缓存函数使用教程

APC,全称是Alternative PHP Cache,官方翻译叫”可选PHP缓存”。它为我们提供了缓存和优化PHP的中间代码的框架。 APC的缓存分两部分:系统缓存和用户数据缓存。(Linux APC扩展安装) 系统缓存 它是指APC把PHP文件源码的编译结果缓存起来,然后在每次调用时先对比时间标记。如果未过期,则使用缓存的中间代码运行。默认缓存 3600s(一小时)。但是这样仍会浪费大量C

Qt多语种开发教程

Qt作为跨平台的开发工具,早已应用到各行各业的软件开发中。 今天讲讲,Qt开发的正序怎么做多语言开发。就是说,你设置中文,就中文显示;设置英语就英文显示,设置繁体就繁体显示,设置发育就显示法语等。 开发环境(其实多语种这块根环境没太大关系):win10,Qt.5.12.10 一.先用QtCreator创建一个简单的桌面程序 1.工程就随便命名“LanguageTest”,其他默认。 2.在设计师

如何打造个性化大学生线上聊天交友系统?Java SpringBoot Vue教程,2025最新设计思路

✍✍计算机编程指导师 ⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流! ⚡⚡ Java实战 | SpringBoot/SSM Python实战项目 | Django 微信小程序/安卓实战项目 大数据实战项目 ⚡⚡文末获取源码 文章目录