游戏编程入门(1) -- 精灵 ISprite

    对于游戏编程而言,我也是个初学者,这个游戏编程入门系列的文章,就当作是我在学习游戏编程的笔记和阶段小结吧。我们先从最简单的“精灵”开始,暂时我们不需要考虑DirectX或是OpenGL,不需要考虑3维等等这些复杂情形,直接使用GDI+绘图功能就可以了。

    精灵,是构成游戏中活动体(比如,飞机、野兽等游戏人物)的最基本单元,任何一个活动体都可以由一个或多个精灵组合而成,每个精灵都是一个对象实例,它能够绘制自己、移动(更复杂的还可以旋转)等等基本动作。
    我让所有的精灵都实现ISprite接口,该接口如下:

    对应的代码如下:

    public interface ISprite
    {
        Graphics Graphics{set ;} //绘制的设备
        Bitmap   Source{set ;}   //精灵表面位图
        Image    BackgroundImage{set ;} //游戏背景

        Point Location{get ;}

        void Erase() ;
        void Draw() ;

        void SetDirection(CompassDirections dir) ;
        void Move() ;
    }

    public enum CompassDirections 
    {
        NotSet = 0 ,
        North = 1,
        NorthEast = 2,
        East = 3,
        SouthEast = 4,
        South = 5,
        SouthWest = 6,
        West = 7,
        NorthWest = 8
    }

    这个接口也许并不是完整的,随了实际的深入,可能还会有很多的元素添加进来,甚至CompassDirections枚举还可以进一步细分,但是ISprite已经有最基本“精灵”功能了。对于大多数简单的任务,我们已经可以给出ISprite的一个实现:

    public class Sprite :ISprite
    {
        private CompassDirections direction = CompassDirections.South ;

        #region ISprite 成员
        private Graphics graphics = null ;
        public  Graphics Graphics
        {
            set
            {
                this.graphics = value ;
            }
        }

        private Bitmap source = null ;
        public  Bitmap Source
        {
            set
            {
                this.source = value ;
            }
        }

        private Point location = new Point(0 ,0) ;
        public  Point Location
        {
            get
            {
                return this.location ;
            }
        }

        #region BackgroundImage
        private Image backgroundImage = null ; 
        public  Image BackgroundImage
        {
            set
            {
                this.backgroundImage = value ;
            }
        }
        #endregion
        
        public void Erase()
        {
            Rectangle ret = new Rectangle(this.location.X  , Location.Y, this.source.Width ,this.source.Height );
            this.graphics.DrawImage(this.backgroundImage, ret, ret, GraphicsUnit.Pixel);            
        }

        public void Draw()
        {
            this.graphics.DrawImage(this.source,this.location.X ,this.location.Y);
        }

        public void SetDirection(CompassDirections dir)
        {
            this.direction = dir ;
        }

        public void Move()
        {
            int stepSize = 5 ;
            if(this.direction == CompassDirections.South)
            {
                this.location.Y += stepSize ;
                return ;
            }

            if(this.direction == CompassDirections.East)
            {
                this.location.X += stepSize ;
                return ;
            }

            if(this.direction == CompassDirections.West)
            {
                this.location.X -= stepSize ;
                return ;
            }

            if(this.direction == CompassDirections.North)
            {
                this.location.Y -= stepSize ;
                return ;
            }
        }

        #endregion
    }

    我们要特别注意Erase方法的实现,所谓Erase实际上就是用背景图对应的区域重新绘制精灵所在的区域表面--这种技巧在游戏编程中是最基本的技巧之一。

    当精灵接收到游戏环境的时钟脉冲通知时,最常见的方法调用组合是:

                theSprite.Erase() ;
                theSprite.Move() ;
                theSprite.Draw() ;
    首先,精灵擦除自己,然后依据方向CompassDirections移动自己到新的位置,最后在新的位置绘制自己。
    所以,当时钟脉冲连续不断的到来时,我们就可以看到精灵在移动了,通过我们的游戏操纵杆或键盘我们可以调用目标精灵的SetDirection方法来指定其要移动的方向。

    下篇文章,我们将基于ISprite构建一个最简单的游戏示例,在这个示例中,我们可以通过键盘的方向键来控制游戏中主角的移动。

时间: 2024-09-25 21:11:16

游戏编程入门(1) -- 精灵 ISprite的相关文章

游戏编程入门莫里森那本书类似的小游戏

问题描述 游戏编程入门莫里森那本书类似的小游戏 有没有大神可以帮忙做一个莫里森编写的游戏编程入门那本书中的用到GameEngine的c++小游戏 解决方案 很急的.求好心大神帮忙

《C++游戏编程入门(第4版)》——1.5 声明和初始化变量

1.5 声明和初始化变量 C++游戏编程入门(第4版) 变量代表了计算机内存的某一部分,该部分被保留下来用于存储.检索和操作数据. 如果需要记录玩家的得分,则可以为它专门创建一个变量.这样一来,就可以读取并显示玩家得分.如果玩家将空中的外星敌人击毙,还可以将得分更新. 1.5.1 Game Stats程序简介 Game Stats程序显示在太空射击游戏中需要记录的诸如玩家得分.击毁敌人数目以及玩家防护盾是否开启等信息.该程序使用了一组变量来完成这些任务.程序如图1.5所示. 图1.5 游戏中每条

《C++游戏编程入门(第4版)》——2.14 问与答

2.14 问与答 C++游戏编程入门(第4版) 问:必须使用关键字true和false吗? 答:不一定,但最好这样做.在有关键字true和false之前,程序员经常使用1代表true,0代表false.然而,既然有了true和false,最好使用它们而不是过时的1和0. 问:可以将true或false以外的值赋给bool型变量吗? 答:可以.可以将表达式赋给bool型变量,变量将存储表达式的真或假. 问:可以使用switch语句对某个非整数值进行验证吗? 答:不可以.switch只能用于可以解释

《Android游戏编程入门经典》——4.4节对比模拟器和Android设备

4.4 对比模拟器和Android设备 Android游戏编程入门经典 模拟器允许您在不同的Android操作系统上并以不同的屏幕分辨率测试程序,但是模拟器(之前称为Android虚拟设备或AVD)存在限制.即使在高端开发PC上,模拟器也很缓慢.现在,高端机器将拥有类似6核处理器(或者是服务器主板上有两个这样的处理器)和8GB或更多RAM的配置.AVD通常配有512MB或1GB的RAM.图4.19显示了AVD配置对话框,注意Hardware(硬件)列表底部的Device RAM Size(设备R

《C++游戏编程入门(第4版)》——1.8 Lost Fortune简介

1.8 Lost Fortune简介 C++游戏编程入门(第4版) 本章最后一个项目Lost Fortune是一个拟人化的探险游戏.在游戏中,玩家输入一些信息,计算机把这些信息扩展成一个探险故事.程序的运行示例如图1.9所示. 图1.9 故事由玩家提供的细节构成 这里不一次展示全部代码,而是每次给出一部分.从Cengage Learning网站(www.cengageptr.com/ downloads)上可以下载到该程序的代码.程序位于Chapter 1文件夹中,文件名为lost_fortun

《Android游戏编程入门经典》——1.3节Android NDK简介

1.3 Android NDK简介 Android游戏编程入门经典 Android NDK(与SDK不同)支持您以本机C++代码而非Java语言编写应用程序或游戏的组件.NDK是一个单独的工具,可在Android SDK安装以后再安装它.NDK不允许以C++语言编写整个应用程序或游戏.更确切地说,它用来补充SDK,支持C++代码和库,并旨在充当许多没有Java库的硬件设备的桥梁.我们可以使用NDK优化游戏代码.除了许多C++库外,NDK还支持实现3D渲染的OpenGL ES 2.0.针对音频的O

《C++游戏编程入门(第4版)》——1.9 本章小结

1.9 本章小结 C++游戏编程入门(第4版) 本章介绍了以下概念: C++是编写一流游戏的主要编程语言. C++程序由一系列的C++语句组成. C++程序的基本生命周期包括构思.设计.源代码.目标文件和可执行文件. 编程错误包括3类:编译错误.链接错误和运行时错误. 函数是一组能完成某些任务并返回一个值的一组程序语句. 每个程序都必须包含main()函数,它是程序的运行起始点. include指令告诉预处理器在当前文件中包含另一个文件. 标准库是一些文件的集合.程序文件可以包含这些文件来实现像

《C++游戏编程入门(第4版)》——2.11 理解游戏主循环

2.11 理解游戏主循环 C++游戏编程入门(第4版) 游戏主循环是游戏中事件流的一般表示方式.事件的核心部分要重复执行,因此称之为循环.尽管不同游戏的主循环的实现不尽相同,但是几乎所有不同种类的游戏的基本结构是一样的.无论是简单的太空射击游戏,还是复杂的角色扮演游戏(Role-Playing Game, RPG),游戏通常由游戏主循环中相同的重复部分组成.游戏主循环如图2.13所示. 图2.13 游戏主循环描述了几乎适用于任何游戏的基本事件流 下面解释游戏主循环的各个部分: 初始化设置.这部分

《C++游戏编程入门(第4版)》——1.2 编写第一个C++程序

1.2 编写第一个C++程序 C++游戏编程入门(第4版)到此为止,我们已经介绍了足够多的理论知识.现在来实践编写第一个C++程序.麻雀虽小,五脏俱全.该程序同样演示了在控制台窗口中显示文本的方法. 1.2.1 Game Over程序简介 程序员在学习新语言时,编写的第一个程序便是经典的Hello World程序,在屏幕上显示Hello World.Game Over程序打破了这个传统,显示的是Game Over!.该程序的运行结果如图1.2所示. 图1.2 您的第一个C++程序显示的是计算机游