`
leecong1p
  • 浏览: 147902 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

2D手机游戏的即时阴影效果

    博客分类:
  • J2ME
阅读更多

        转载要注明作者、出处哟。

        前段时间在做可以兼容J2ME和Android的ARPG引擎,获得一些心得。2D手机游戏似乎画面上没什么突破,几乎都是靠美工把地图画得华丽一些,然后加一些云朵、光晕的贴图,再弄点下雨、下雪啥的,已经见怪不怪了。看了一些前几年的PC游戏,同样是2D,像暗黑就有模拟的光照效果,场景有明暗之分,人物也阴影效果。目前手机游戏有点类似当年的形态,当然即时是现在的手机也无法与当年的PC性能抗衡。要在2D手机游戏上实现这些效果肯定要降低效果的质量。

 

      先来说阴影,原理其实很简单,比如要给一个人物精灵绘制阴影:

      1)将精灵原图按比例拉伸、旋转

      2)转换成带alpha效果的黑色图片

      3)绘制到人物脚下

 

      OK!既然这么简单,立马实现到现有的游戏中去看看效果!

      结果,效果是出来了,速度却慢得惊人,由于是即时绘制,在我的N85上帧速只有5~8左右,这还只是一个人物精灵的绘制,如果给每个NPC都加上阴影……嗯,你懂的。

 

      好吧,这可是即时运算,我们得找找影响CPU发挥的瓶颈在哪:

       1)图像的拉伸、旋转网上有很多算法,什么插值法、扫描法……前辈们总结了很多,这可是在虚拟机上跑,过高的时间复杂度,甚至涉及浮点运算肯定会让速度大打折扣。

       2)还有,获取原图的RGB信息,经过一系列的翻转、拉伸,然后新建个动态图像,把RPG值转成黑色填进去,再调整alpha值,再贴到指定位置……这么折腾N85居然能做到5帧,太给力了!

 

       了解了瓶颈所在,下面停止扯淡,介绍一下我的优化方法:

       跳过拉伸、旋转操作,每帧都做这么大开销的操作就是手机电池也不会答应。我们可以直接扫描图像的RGB信息,扫描到非透明的RGB值时计算出对应点的位置(计算这里涉及三角函数,为了提升性能以及兼容MIDP1.0,建议用查表法)。跳过新建图像以及alpha调整的操作,我们可以预先建立好一个半透明的黑色影子图片来贴图。

 

       coding...经过一系列的折腾,效果出来了:

 

        感觉还不错吧?场景中有4棵树绘制了阴影,N85实机帧数是20上下。(这是WTK2.5的模拟器截图,由于还开启了引擎的模拟明暗效果,所以帧数下降到了12。)

 

        等等,N85在主流J2ME手机里算不错的,一个影子效果就让PFS降到了20,那以后加上模拟水波、模拟光照、模拟天气等等效果,不是得卡死?嗯……让我来进一步优化,不过这次可就要稍微降低一些影子的质量了:

        逐个像素扫描图片,运算量也是相当惊人的,80x32的一棵小树就要判断2560次!我们可以间隔着扫描,比如扫描某行RGB信息时,扫描1个像素然后跳过下面4个像素再扫描下一个,这样影子效果可能有一些偏差,但是大致轮廓还是很清晰的。(如果扫描的像素非透明就用准备好的半透明影子图片绘制一个1x4的影子,跳过接下来4个像素继续扫描,继续绘制……)来看效果:

跳过2个像素

 

跳过4个像素

       

        FPS提升了5倍!好吧,你应该有所启发,横向、纵向扫描越过几个像素完全由你控制,我们可以理解为扫描精度。来更进一步优化,即便是跳着扫描,仍然需要判断很多次,而我们只是要获得精灵的大致轮廓,画出阴影而已。我们完全可以从图片的两边扫描不透明点的起始位置,然后计算不透明区域的长度,根据这个长度直接贴图!

        好吧,光放几张鸟图,不贴代码是不厚道的,下面是影子绘制部分的核心代码(写的比较烂,望海涵):

    /** 利用透明图片绘制向下的影子
     * @param g Graphics  画布对象
     * @param img Image  要绘制阴影的原图
     * @param px int  绘制x位置
     * @param py int  绘制y位置
     * @param height int  影子高度(<=原图像素高度)
     * @param scanSkip int  扫描跳过的像素个数(1最高精度,建议用2)
     * @param cot256 int  影子角度的cot值(这里是查表法得来的256倍)
     */
    public static void drawTransShadowDown(Graphics g, Image img, int px,
	    int py, int height, int scanSkip, int cot256) {

	int w = img.getWidth();
	int h = img.getHeight();
	int pels[] = new int[w];
	int ofx = 0;
	int scanH = 256 * h / height;

	int startX = 0;
	int endX = 0;
	int rowIn = 0;
	int scanIn = (h - 1) * 256;
	g.setColor(0x000000);

	while (scanIn >= 0) {
	    //跳过扫描?
	    if (rowIn % scanSkip == 0) {
		img.getRGB(pels, 0, w, 0, scanIn >> 8, w, 1);
		//扫描起始位置
		for (int j = 0; j < w; j++) {
		    if ((pels[j] >> 24) == -1) {
			startX = j;
			break;
		    }
		}
		//扫描结束位置
		for (int j = w - 1; j >= 0; j--) {
		    if ((pels[j] >> 24) == -1) {
			endX = j;
			break;
		    }
		}
		//这个方法是我自己里面封装的,类似DrawRegion,transImg是一张半透明黑色图片
		BaseCanvas.drawImage(g, transImg, 0, 0, endX - startX + 1,
			scanSkip, 0, px + (ofx >> 8) + startX, py + rowIn, 20);
	    }
	    ofx += cot256;
	    rowIn++;
	    scanIn -= scanH;
	}
    }

 

      查表法求三角函数:

    //sin(0°) to sin(90°)    all *256
    public final static int SIN_TABLE[] = {
        0, 4, 8, 13, 17, 22, 26, 31, 35, 39,
        44, 48, 53, 57, 61, 65, 70, 74, 78, 83,
        87, 91, 95, 99, 103, 107, 111, 115, 119, 123,
        127, 131, 135, 138, 142, 146, 149, 153, 156, 160,
        163, 167, 170, 173, 177, 180, 183, 186, 189, 192,
        195, 198, 200, 203, 206, 208, 211, 213, 216, 218,
        220, 223, 225, 227, 229, 231, 232, 234, 236, 238,
        239, 241, 242, 243, 245, 246, 247, 248, 249, 250,
        251, 251, 252, 253, 253, 254, 254, 254, 254, 254,
        255
    };


    /** 查表法求SIN值
     *
     * @param angle int 0到360度
     * @return int  返回SIN值的256倍
     */
    public static int sin256(int angle) {
        angle %= 360; // 360 degrees
        if (angle <= 90) { // 0..90 degrees
            return SIN_TABLE[angle];
        }
        else if (angle <= 180) { // 90..180 degrees
            return SIN_TABLE[180 - angle];
        }
        else if (angle <= 270) { // 180..270 degrees
            return -SIN_TABLE[angle - 180];
        }
        else { // 270..360 degrees
            return -SIN_TABLE[360 - angle];
        }
    }

    public static int cos256(int angle) {
        return sin256(angle + 90); // i.e. add 90 degrees
    }

    public static int cot256(int angle){
        return cos256(angle)*256/Math.sin256(angle);
    }

    public static int tan256(int angle){
        return sin256(angle)*256/Math.cos256(angle);
    }

 

      最后,有一个问题值得注意,细心观察自然界的影子,其实并不是直接旋转一下原图的效果,而是根据光源的位置投影而来的。网上有些那原图直接翻转的方法其实是错的,本文的方法也不太正确,但至少在2D游戏里看上去像那么回事,哈哈,看图为证~ 

 

 

 

      刚开始在这写点东西,技术不足还请多多指教。我对J2ME、Android游戏开发很感兴趣,望有朋友能一起交流QQ:350751373。

  • 大小: 45.8 KB
  • 大小: 25.2 KB
  • 大小: 26.8 KB
  • 大小: 14.9 KB
2
0
分享到:
评论

相关推荐

    echarts2D地图实现3D阴影效果 山东省.zip

    在本文中,我们将深入探讨如何使用ECharts,一个流行的JavaScript数据可视化库,来实现2D地图的3D阴影效果,特别是在展示山东省地图时的应用。ECharts 提供了丰富的图表类型和自定义选项,使得开发者能够创建出具有...

    Unity3D+2D手机游戏开发(第2版)

    本书以实例教学为主线,循序渐进地介绍了Unity在游戏开发方面的不同功能。第1章,由零开始,引导读者熟悉Unity编辑器的各个功能模块,这部分内容对Unity程序员、美工和策划都有帮助。 第2~4章是3个不同特色的3D游戏...

    Unity3D 2D手机游戏开发 第二版上

    Unity3D 2D手机游戏开发 第二版

    unity制作2D的灯光阴影

    制作UNITY2D平面游戏的灯光阴影,类似战争迷雾类似,

    Unity 3D/2D手机游戏开发(金玺曾)(第2版)版本5.x--part2

    Unity 3D/2D手机游戏开发(金玺曾)(第2版)版本5.x,分卷是csd限制,完整版,第2版。

    大富翁手机游戏开发实战基于Cocos2d-x3.2引擎

    资源名称:大富翁手机游戏开发实战基于Cocos2d-x3.2引擎内容简介:李德国编著的《大富翁手机游戏开发实战(基于 Cocos2d-x3.2引擎)》使用Cocos2d-x游戏引擎技术,带领读者一步一步从零开始进行大富翁移动游戏的开发...

    cocos2d-x手机游戏开发

    《cocos2d-x手机游戏开发》一书深入浅出地介绍了如何利用cocos2d-x框架进行Android游戏的开发。cocos2d-x是一款跨平台的2D游戏开发框架,广泛应用于iOS、Android以及Windows等多个操作系统。它以其高效、易学、功能...

    Unity3D 2D手机游戏开发 第二版下

    Unity3D 2D手机游戏开发 第二版下

    COCOS2D手机游戏开发飞机大战实战案例

    资源名称:COCOS2D手机游戏开发飞机大战 实战案例 教程内容:1.COCOS2D 飞机大战 实战案例-项目简介2.COCOS2D 飞机大战 实战案例-改变项目场景大小3.COCOS2D 飞机大战 实战案例-欢迎界面背景4.COCOS2D 飞机大战 ...

    cocos2d-x即时战斗类游戏《战三国》源码

    cocos2d-x即时战斗类游戏《战三国》源码 说明: 绚丽的游戏画面,酷炫的游戏场景 ☆让你体验统领千军万马的感觉 群雄逐鹿 热血三国!12位各具特色的人物和32种华丽震撼的技能带给玩家炫彩的视觉感受与轰动的战争体验!...

    Cocos2d-JS开发之旅 从HTML 5到原生手机游戏 PDF 带书签目录 完整版

    《Cocos2d-JS开发之旅:从HTML5到原生手机游戏》是一本深入探讨Cocos2d-JS框架的书籍,旨在帮助开发者从Web前端的HTML5技术过渡到跨平台的原生手机游戏开发。Cocos2d-JS是Cocos2d-x引擎的一个分支,它结合了...

    大富翁手机游戏开发实战 基于Cocos2d-x3.2引擎

    李德国编著的《大富翁手机游戏开发实战(基于 Cocos2d-x3.2引擎)》使用Cocos2d-x游戏引擎技术,带领读者一步一步从零开始进行大富翁移动游戏的开发。本书根据大富翁项目一一展开讲解游戏开发过程中涉及的各方面内容...

    《cocos2d-x 手机游戏开发 》源码

    《cocos2d-x 手机游戏开发》是徐松林撰写的一本关于使用cocos2d-x框架进行移动游戏开发的专业书籍。cocos2d-x是一个开源的、跨平台的游戏开发框架,它基于cocos2d-iphone扩展而来,支持C++、Lua和JavaScript等多种...

    Unity3D 2D手机游戏开发 第2版 金玺

    本书以实例教学为主线,循序渐进地介绍了Unity在游戏开发方面的不同功能 是第2版

    Unity 2D和3D游戏开发.rar

    本资源包含两份PDF文档,分别专注于Unity 2D手机游戏开发和Unity 5.x 3D游戏开发技术。 《Unity 3D游戏开发技术详解与典型案例》PDF文件可能详细介绍了Unity引擎在3D游戏制作中的应用。这可能包括以下几个关键知识...

    cocos2d-x手机游戏开发.part6.rar

    cocos2d-x手机游戏开发,是一本介绍cocos2d游戏引擎,已经如何扩平台开发手机游戏的书。由于上传大小的限制,分成6个压缩包,不好意思。第6卷。

    MFC 窗口阴影效果

    然后,我们可以在该子窗口上使用GDI+或Direct2D等图形库绘制阴影效果。 3. **处理消息**:为了响应窗口的移动和大小改变事件,我们需要重载MFC的`OnMove`和`OnSize`成员函数。在这些函数中,我们需要更新子窗口的...

    【免费】Unity 3D手机游戏开发 金玺曾.pdf【高清扫描版带书签】

    Unity 3D手机游戏开发 金玺曾.pdf,扫描版很清晰,适合游戏开发者参考。

    基于C#实现的多人2D格斗游戏(emoji大乱斗)源码.zip

    基于C#实现的多人2D格斗游戏(emoji大乱斗)源码.zip基于C#实现的多人2D格斗游戏(emoji大乱斗)源码.zip基于C#实现的多人2D格斗游戏(emoji大乱斗)源码.zip基于C#实现的多人2D格斗游戏(emoji大乱斗)源码.zip基于C#实现的...

    BOX2D 物理游戏编程初学者指南 陈文登(高清,带目录)

    高清带目录《Box2D物理游戏... 《Box2D物理游戏编程初学者指南》最后,通过大量的游戏效果模拟,直截了当地介绍相关知识点的实际应用,这些游戏包括《愤怒的小鸟》《叫醒盒子》《跨越重力》《星星大盗》《割绳子》等

Global site tag (gtag.js) - Google Analytics