`
wgcode
  • 浏览: 599626 次
  • 性别: 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
分享到:
评论

相关推荐

    双缓冲技术原理以及优缺点

    双缓冲技术作为一项重要的图形渲染技术,在游戏开发等领域有着广泛的应用。它通过在后台缓冲区完成所有的绘制操作,再一次性交换到前台显示,有效地解决了图像更新时的闪烁和撕裂问题,提升了用户体验。然而,双缓冲...

    循环图像缓冲区.zip

    循环图像缓冲区是一种在计算机图形学和游戏开发中常见的技术,用于提高图像处理效率和流畅度。这种技术基于双缓冲或多缓冲的概念,特别是在实时渲染环境中,例如游戏引擎、动画软件和用户界面。下面我们将深入探讨...

    防止图像闪烁之后备缓冲技术

    【后备缓冲技术】是一种在计算机图形学和游戏开发中广泛使用的优化技术,主要目的是消除屏幕上的图像闪烁,提高用户体验。这种技术尤其适用于动态图形显示,如动画、视频播放或者复杂的用户界面。以下是对后备缓冲...

    双缓冲技术解决刷新闪烁

    双缓冲技术是计算机图形学和GUI编程中一种重要的优化手段,主要目的是解决界面元素在更新时出现的闪烁问题。在日常使用计算机时,比如浏览网页、玩...在实际开发中,理解和运用双缓冲技术对于优化图形应用至关重要。

    MFC游戏开发6by七十一雾央

    在本文中,我们将深入探讨MFC(Microsoft Foundation Classes)框架下的游戏开发,特别是关于图像双缓冲技术的应用。图像双缓冲是一种提高图形显示质量和流畅性的技术,对于游戏开发来说至关重要,因为它能有效避免...

    循环图像缓冲区(1).zip

    循环图像缓冲区在实际应用中广泛使用,特别是在需要高帧率和流畅动画效果的场景中,如游戏开发、实时视频处理和虚拟现实。通过合理利用多缓冲区,可以有效避免画面撕裂和卡顿现象,提供更佳的用户体验。 例如,在...

    Direct3D游戏开发技术详解(源码光盘)

    Direct3D是微软开发的一种图形应用程序接口(API),主要用于在Windows平台上创建高性能的三维图形,尤其在游戏开发领域应用广泛。本书“Direct3D游戏开发技术详解”深入剖析了这一技术,帮助开发者掌握Direct3D的核心...

    双缓冲技术教程加源码.rar

    双缓冲技术是计算机图形学中一种优化显示更新的技术,尤其在游戏开发和用户界面设计中广泛应用。它旨在解决屏幕闪烁和图像撕裂问题,提供更流畅的视觉体验。本教程结合源码,将深入讲解双缓冲的工作原理及其应用。 ...

    Java双缓冲技术.doc

    通过理解和实践这两种双缓冲技术,开发者可以有效地提升Java应用程序中的动画质量和用户体验,消除屏幕闪烁,使游戏和多媒体应用更加流畅。 总结来说,Java双缓冲技术是解决屏幕闪烁问题的关键。通过在内存中创建一...

    Direct3D游戏开发技术详解游戏开发实例

    Direct3D是微软开发的一种图形应用程序接口(API),主要用于创建高性能的3D图形,尤其在游戏开发领域广泛应用。本教程“Direct3D游戏开发技术详解游戏开发实例”着重于通过实际项目来教授Direct3D的核心技术和游戏...

    基于双缓冲技术的VC++图形刷新技术的原理和实现

    ### 基于双缓冲技术的VC++图形刷新技术的原理和实现 #### 1. 引言 在Windows环境中,界面设计对于程序的整体表现至关重要。...这种技术在需要频繁刷新窗口内容的应用场景中尤为重要,可以显著提升用户的视觉体验。

    Visual C++游戏开发技术与实例:Visual C++游戏开发技术与实例

    2. **图形和图像处理**:由于游戏开发离不开图形界面,书中会讲解如何使用DirectX或其他图形库进行2D和3D图形渲染,包括坐标系统、顶点缓冲、纹理映射等。此外,还会涉及光照、阴影、粒子效果等高级图形技术。 3. *...

    Visual C++游戏开发技术与实例(随书源码)

    在“Visual C++游戏开发技术与实例”这本书中,你可能会学到如何创建DDraw的2D游戏项目,包括初始化DirectDraw对象、创建双缓冲区以避免闪烁、加载和显示图像、处理键盘和鼠标输入等。同时,你也会接触到OpenGL的3D...

    WIN32GDI双缓冲打螃蟹小游戏

    双缓冲技术是解决窗口应用程序中图形更新问题的一种方法,特别是在进行连续动画或快速绘图时,可以避免屏幕闪烁和图像残影。在双缓冲中,我们首先在内存中的一个“后台缓冲区”上完成所有的绘图操作,然后一次性将这...

    双缓冲应用

    在计算机图形学和游戏开发领域,双缓冲技术是一种优化显示性能和减少屏幕闪烁的重要方法。在本项目"双缓冲应用"中,我们聚焦于利用这种技术来实现一个室内地图引擎的绘图功能。这个项目是开发阶段的一个初期成果,...

    双缓冲绘图技术教程实例

    双缓冲绘图是一种在计算机图形学中用于减少屏幕闪烁和提高图像质量的技术。在传统的单缓冲绘图中,每当图形需要更新时,程序会直接在屏幕上绘制新的图像,这可能导致用户看到部分完成或未完成的图像,即所谓的“闪烁...

    开发用的图标缓冲系列

    在计算机图形学中,图像缓冲是一种将图像数据存储在内存中的技术,这样可以提高渲染效率并避免屏幕闪烁。当改变图像时,先在缓冲区中完成修改,然后再一次性显示到屏幕上,这个过程称为双缓冲或多缓冲技术,能有效...

    双缓冲技术解决刷新闪烁_thenq78_Vc_

    在计算机图形学和软件开发中,特别是在Windows编程中,"双缓冲技术"是一个重要的概念,用于优化用户界面的更新和防止闪烁。这个技术主要应用于GUI(图形用户界面)应用程序,尤其是那些需要频繁更新画布或者窗口内容...

    双缓冲绘图技术实例讲解

    双缓冲绘图技术是一种在计算机图形学中广泛使用的优化策略,尤其在GUI(图形用户界面)和游戏开发中。它的核心思想是减少屏幕闪烁和图像撕裂现象,从而提供更流畅、更高质量的视觉体验。在本文中,我们将通过一个...

    匀速运动-图片的双缓冲技术

    在计算机图形学中,双缓冲技术是一种优化图形渲染效率并避免屏幕闪烁的策略,尤其在处理动态图像时显得尤为重要。标题“匀速运动-图片的双缓冲技术”暗示了我们将探讨如何利用双缓冲来实现一个平滑的小球匀速运动的...

Global site tag (gtag.js) - Google Analytics