`
wgcode
  • 浏览: 576919 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

图像缓冲技术在游戏开发中的应用

阅读更多

第一篇:基本应用

在塔防类、空战类游戏中,经常会出现同屏幕有很多对象的情况(如子弹)。而如果使用MovieClip来实现的话,当数量太多的时候,就会占用太多资源,令程序运行很慢。这个时候,可以通过使用图像缓冲来替代。同时,本文所描述的实现思路,也是一种将数据和显示分开进行的方法。在很多的游戏设计中经常会用到。
我们以同屏幕500个子弹为例,来看一下图像缓冲的实现方法。首先,来看一下总体的程序思路

1.主场景使用名为bitmapfill的BitmapData,通过graphics.beginBitmapFill来进行全场景填充。这样,我们就可以通过enterFrame事件,定期刷新bitmapfill的内容来实现动画
2.声明子弹的时候,把bitmapfill传递给子弹类
3.enterFrame侦听,触发渲染事件。在渲染事件中循环全部子弹对象调用其自身的渲染函数
4.在子弹自身的渲染函数中,计算子弹当前的位置,然后使用copyPiexl方法将自身的素材复制到bitmapfill的正确位置
5.循环实现子弹的动画效果
为了实现以上方法,我们首先构建一个子弹类:

package 
{ 
    import flash.display.BitmapData; 
    import flash.geom.Point; 
    /** 
     * 图形缓冲范例子弹类 
     * Author:D5Power 
     * www.d5power.com www.webgamei.com 
     */ 
    public class zidan 
    { 
        /** 
         * 子弹的图形素材 
         */ 
        private var doc:BitmapData; 
        /** 
         * 主场景的缓冲区 
         */ 
        private var buffer:BitmapData; 
         
        /** 
         * x坐标 
         */ 
        private var x:uint; 
        /** 
         * y坐标 
         */ 
        private var y:uint; 
        /** 
         * x轴速度 
         */ 
        private var speed_x:uint = 3; 
        /** 
         * y轴速度 
         */ 
        private var speed_y:uint=3; 
         
        /** 
         * 子弹构造函数 
         * @param   _doc        子弹素材 
         * @param   _buffer     主场景缓冲区 
         */ 
        public function zidan(_doc:BitmapData,_buffer:BitmapData) 
        { 
            doc = _doc; 
            buffer=_buffer; 
        } 
         
        /** 
         * 设置子弹的位置 
         */ 
        public function set Pos(p:Point):void 
        { 
            x = p.x; 
            y = p.y; 
        } 
         
        /** 
         * 渲染函数,当子弹超出屏幕边界则反弹 
         */ 
        public function render():void 
        { 
            x+=speed_x; 
            y+=speed_y; 
             
            if(x>main.W || x<0) 
            { 
                speed_x=speed_x*-1; 
            } 
             
            if(y>main.H || y<0) 
            { 
                speed_y=speed_y*-1; 
            } 
             
            // 将子弹的素材按照数据的标准位置,复制到缓冲区 
            buffer.copyPixels(doc,doc.rect,new Point(x,y),null,null,true); 
             
        } 
    } 
}

 

接下来看一下主场景的实现方法:

package  { 
    import flash.display.Sprite; 
    import flash.display.BitmapData; 
    import flash.events.Event; 
    import flash.geom.Point; 
     
    /** 
     * 图形缓冲范例主场景 
     * Author:D5Power 
     * www.d5power.com www.webgamei.com 
     */ 
    public class main extends Sprite 
    { 
        /** 
         * 缓冲区 
         */ 
        private var buffer:BitmapData; 
        /** 
         * 子弹序列 
         */ 
        private var objects:Array; 
         
        /** 
         * 场景宽度 
         */ 
        public static var W:uint = 550; 
        /** 
         * 场景高度 
         */ 
        public static var H:uint = 400; 
         
         
        public function main() { 
             
            // 声明缓冲区 
            buffer = new BitmapData(W,H,true,0x00000000); 
            objects = new Array(); 
            // 获取子弹素材 
            // 本例用FLASH开发,因此zidan_doc实际为库中导出的BitmapData类 
            var doc:BitmapData = new zidan_doc(0,0); 
             
            // 渲染侦听 
            addEventListener(Event.ENTER_FRAME,render); 
             
            // 声明500个子弹,添加到子弹序列中 
            for(var i:uint=0;i<500;i++) 
            { 
                var zd:zidan = new zidan(doc,buffer); 
                var rand_x:uint = Math.floor(Math.random()*W); 
                var rand_y:uint = Math.floor(Math.random()*H); 
                zd.Pos = new Point(rand_x,rand_y); 
                addObjects(zd); 
            } 
             
            // 以缓冲区填充场景 
            graphics.beginBitmapFill(buffer); 
            graphics.drawRect(0,0,buffer.width,buffer.height); 
            graphics.endFill(); 
        } 
         
        /** 
         * 向子弹序列中添加对象 
         * @param   o 
         */ 
        private function addObjects(o:zidan):void 
        { 
            objects.push(o); 
        } 
         
        /** 
         * 渲染 
         * @param   e 
         */ 
        private function render(e:Event):void 
        { 
            buffer.fillRect(buffer.rect,0); 
             
            // 循环全部子弹序列,渲染每个子弹 
            for each(var zd:zidan in objects) 
            { 
                zd.render(); 
            } 
             
             
        } 

    } 
}

 

 

 

 

 

本文代码只是提供了一个基本的思路,在实际的使用过程中,还是要做一些必要的扩展。例如,本文的主场景只提供了addObject来向子弹序列中增加对象,而没有反操作的过程。同时,在RPG游戏中,可能需要可以触发鼠标事件,而我们使用了位图缓冲后,就不能直接进行事件侦听了。等等这些问题,都是需要大家在实际的开发中思考的。

第二篇 响应鼠标事件

采用图像缓冲后,整个场景其实只是在不断的重新绘制(渲染)。场景中再没有任何的childObject。因此是无法通过addEventListener来进行鼠标事件的判断的。因此我们需要通过其他的方法来实现。

在上一篇中,我们使用了addObjects方法把某个渲染对象增加到渲染序列中,我们可以对渲染序列加以利用,从而找出当前所点击的渲染对象。

我们已经知道每个渲染对象都有自己的坐标,而鼠标点下后,又可以获得舞台坐标stageX和stageY。于是我们可以计算当前的鼠标对应每个渲染对象的坐标(stageX-x,stageY-y),同时,Bitampdata为我们提供了像素级的碰撞检测。于是,我们就可以通过鼠标的相对坐标来判断与场景中的哪个渲染对象发生了碰撞,也就是点击的对象了。

重新写过的代码如下:

package  {
        import flash.display.BitmapData;
        import flash.geom.Rectangle;
        
        public class gObject {
                /* 位图数据 */
                public var bitmap:BitmapData;
                /* x坐标 */
                public var x:Number;
                /* y坐标 */
                public var y:Number;
                /* 当前渲染对象的ID */
                public var ID:uint;
                
                public function gObject() {
                        // constructor code
                        // 绘制一个40*40的画布,并在画布中央画一个20*20的正方形,其他位置透明
                        bitmap = new BitmapData(40,40,true,0x00000000);
                        bitmap.fillRect(new Rectangle(10,10,20,20),0xFF0000ff);
                }

        }
        
}

 以上类相当于子弹类。我们只保留了最基本的属性,以免程序变的不好读懂:)

再看一下实现功能的代码:
(以下代码没有通过类实现,而是直接写到了FLASH的时间轴上)

import flash.display.BitmapData;
import flash.geom.Rectangle;
import flash.geom.Point;
// 渲染列表
var objList:Array = new Array();
// 缓冲区
var bd:BitmapData = new BitmapData(550,400,true,0x00000000);

var rx:int;
var ry:int
for(var i:uint = 0;i<10;i++)
{
        var obj:gObject = new gObject();
        rx = Math.floor(550*Math.random());
        ry = Math.floor(400*Math.random());
        obj.x = rx;
        obj.y = ry;
        obj.ID=i;
        objList.push(obj);
        bd.copyPixels(obj.bitmap,obj.bitmap.rect,new Point(rx,ry));
}
// 渲染
graphics.beginBitmapFill(bd);
graphics.drawRect(0,0,550,400);

// 增加侦听事件
stage.addEventListener(MouseEvent.CLICK,onclick);

// 循环渲染列表,确认当前点击的是哪个对象
function onclick(e:MouseEvent):void
{
        var tx:Number;
        var ty:Number;
        for each(var obj:gObject in objList)
        {
                tx = e.stageX-obj.x;
                ty = e.stageY-obj.y;
                if(obj.bitmap.hitTest(new Point(0,0),0xFF,new Point(tx,ty)))
                {
                        trace("您点击了"+obj.ID);
                        break;
                }
        }
}
// 向渲染列表中增加渲染对象
function addObject(obj:gObject):void
{
        objList.push(obj);
}

 

 

 

 

以上代码只是从功能上实现了对鼠标时间的相应,确认点击的是哪个对象。但是在实际的游戏开发中,同场景(如果你的场景非常大)的角色可能很多,全部循环过去是非常浪费资源的。所以,可以通过其他对象相对主角的距离等方式来加以限制。这样在渲染的时候也可以节约资源:)

 

 

 

 

 

 

 

  • 大小: 52.9 KB
  • 大小: 12.5 KB
分享到:
评论

相关推荐

    HTML5 Canvas核心技术 图形、动画与游戏开发

    217 4.9.3 遍历图像数据 218 4.10 放大镜 222 4.10.1 使用离屏canvas 224 4.10.2 接受用户从文件系统中拖放进来的图像 225 4.11 视频处理 227 4.11.1 视频格式 227 4.11.2 在canvas中播放视频 229 4.11.3 ...

    GIS开发算法,根据线,生成缓冲区

    图像开发中的缓冲区生成 根据作用的数据性质不同,可以分为:1.基于空间图形数据的分析运算;2。基于非空间属性的数据运算;3.空间和非空间数据的联合运算。空间分析赖以进行的基础是地理空间数据库,其运用的手段...

    C#开发实例大全(基础卷).软件开发技术联盟(带详细书签) PDF 下载

    主要内容有C#开发环境的使用、C#语言基础应用、字符串处理技术、数组和集合的使用、面向对象编程技术、数据结构与算法、Windows窗体基础、特色窗体界面、窗体控制技术、MDI窗体和继承窗体、Windows常用控件的使用、...

    《Android应用开发揭秘》源码

    精通Java、C、C++等语言,专注于移动通信软件开发,在机顶盒软件开发和MTK平台软件开发方面有非常深厚的积累。2007年获得中国软件行业协会游戏软件分会(CGIA)认证及国际游戏开发教育联合会国际认证。曾经领导和参与...

    《Android应用开发揭秘》附带光盘代码.

    《Android应用开发揭秘》全部实例源代码,配合《Android应用开发揭秘》使用 前言  第一部分 准备篇  第1章 Android开发简介  1.1 Android基本概念  1.1.1 Android简介  1.1.2 Android的系统构架  1.1.3 ...

    android开发揭秘PDF

    5.2.10 双缓冲技术 5.2.11 全屏显示 5.2.12 获得屏幕属性 5.3 动画实现 5.3.1 Tween动画 5.3.2 Frame动画 5.3.3 GIF动画播放 5.4 小结 第6章 Android数据存储 6.1 Android数据存储初探 6.2 数据存储之Shared ...

    Android应用开发揭秘pdf高清版

    它还以迭代的方式重现了各种常用的Android应用和经典Android游戏的开发全过程,既可以以它们为范例进行实战演练,又可以将它们直接应用到实际开发中去。 目录 -------------------------------------------------...

    基于FPGA和嵌入式系统的实时图像处理--浙江大学

    控制系统的理想选择,本文接着对嵌入式系统在陆地自主车视觉导航中的应用进行了研究"第二章重点介绍了嵌入式系统的组成及应用开发"首先明确了嵌入式系统的定义和体系结构,接着介绍了其软硬件组成"在此基础上介绍了...

    Pr65教学.rar

    但是,Premiere 6.5也可以动态调节实时预览的视频质量和帧速率,当用户的系统配置较低或者在视频中运用了大量的特效,Premiere 6.5会适当地降低视频质量和帧速率以完成实时预览。用户可以通过选择“Project | ...

    明日科技C#开发入门及项目实战

    实例165 在图像中实现自定义标记 实例166 辉光效果的文字 实例167 渐变效果的文字 实例168 绘制多边形 实例169 简单画图程序 实例170 仿qq截图功能 实例171 模拟石英钟 实例172 绘制贝塞尔曲线 实例173 绘制图形...

    Visual C++音频视频处理技术及工程实践(含源码2/2)

    采用的案例均来源于作者实际开发工作,具有很好的实用价值,可以帮助读者在开发中进行参考或直接应用。 第1篇 开发基础 1 第1章 数字音视频开发技术基础 3 1.1 数字音视频基本概念 4 1.1.1 数字音频技术基础 4 ...

    Visual C++音频视频处理技术及工程实践(分卷0)

    采用的案例均来源于作者实际开发工作,具有很好的实用价值,可以帮助读者在开发中进行参考或直接应用。 第1篇 开发基础 1 第1章 数字音视频开发技术基础 3 1.1 数字音视频基本概念 4 1.1.1 数字音频技术基础 4 1.1.2...

    VC与Labview、Matlab编程论文资料[2].rar

    LabVIEW和MATLAB在现代光测图像处理中的应用.pdf LabVIEW在自定义应用层CAN总线通讯中的应用.pdf LabVIEW测控系统的网络访问技术研究.pdf LZW压缩算法VC实现、改进及其应用研究.pdf MATCOM与VC_混合编程中自定义...

    VC与Labview、Matlab编程论文资料

    LabVIEW和MATLAB在现代光测图像处理中的应用.pdf LabVIEW在自定义应用层CAN总线通讯中的应用.pdf LabVIEW测控系统的网络访问技术研究.pdf LZW压缩算法VC实现、改进及其应用研究.pdf MATCOM与VC_混合编程中自定义...

    VC与Labview、Matlab编程论文资料[4].rar

    LabVIEW和MATLAB在现代光测图像处理中的应用.pdf LabVIEW在自定义应用层CAN总线通讯中的应用.pdf LabVIEW测控系统的网络访问技术研究.pdf LZW压缩算法VC实现、改进及其应用研究.pdf MATCOM与VC_混合编程中自定义...

Global site tag (gtag.js) - Google Analytics