2D游戏平滑的迷雾战争效果

2024-02-12 09:08

本文主要是介绍2D游戏平滑的迷雾战争效果,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近刚好有做2D游戏的点光源效果,然后就扩展一下,研究了一下战争迷雾的效果。主要是想实现类似魔兽争霸那种人物走动,然后黑色的战争迷雾随着人物的移动渐渐打开的效果。使用具有渐变透明图片作为光源来使得战争迷雾呈现出平滑的效果。本文后面介绍了两个简单的实现方法,效果有细微的差别,有兴趣的同学可以分别研究。最后也有完整展示代码和提供例子下载。

一、常见的战争迷雾效果

早期的红警的战争迷雾大家应该也比较熟悉,不过看起来没那么平滑,应该是采用图块拼出来。可以明显看得出一些方方块块。
这里写图片描述
可见早期魔兽争霸2也是没那么平滑的。
后面出的一些有些的战争迷雾就会有比较平滑的过渡效果了。比如英雄联盟,魔兽3(这两个是3D的)。但是也有2D也做得比较平滑(看图的最后一个截图)
这里写图片描述

二、实现的简单原理讲解

由于是做2D游戏,所以思路基本上是2D,但是同时也有3D思想,例如图层混合方式处理等。主要原理就是根据图片的alpha值来进行反向擦除(alpha为1时完全擦除,alpha越小则越不透明,实现渐变过程效果)。最后用了两种比较简单的方法来实现了这种效果,两者有微弱的差别。这里采用的是AS3实现的,源码也提供了几种渐变图片,可以作为点光源来擦亮迷雾,可以替换上去看各种效果的。
这里写图片描述

  1. 遮罩擦除做法
    最先想到的原理,是基于之前实现类似点光源效果的做法。通过一层带有alpha值遮罩图来擦掉对应的战争迷雾,就是移动版增大的点光源效果。首先人物背景,然后一层战争迷雾在最顶层,人物带了个点光源,然后人物移动的时候,不会把那个点光源层进行绘制,那么光源层就会原来越大。那个迷雾自然就会越来越大了。
    下图:刚开始是一个圆圈,然后随着人物移动,圆圈会扩大。
    这里写图片描述
    得到这个图之后,就是对黑色战争迷雾层根据alpha进行擦了。
//一个专门做点光源的顶层容器
var topContainer:Sprite = new Sprite();
//强制为该显示对象创建一个透明度组
topContainer.blendMode = BlendMode.LAYER;
//根据显示对象的 Alpha 值擦除迷雾
openFogBitmap.blendMode = BlendMode.ERASE;

合成遮罩图来去除迷雾的代码是,最后一个参数true是合并alpha:

bitmapData.copyPixels(bitmapData,pointRect,new Point(role.x,role.y),null,null,true);

这样跟随人物移动不断地把遮罩扩大。除了最开始的合成遮罩图,后面的处理跟之前讲的新手引导遮罩和点光源实现机制一样,后面会给出相关的代码。不过这种实现是有点不好的是合并alpha,这样会导致范围突然变亮(因为alpha相加大于1,就全部擦了,大部分亮了,也就是会有个逐渐变亮的效果,使得战争迷雾开启效果没那么真实)。最终表现效果如下图:
这里写图片描述
2. 直接擦出战争迷雾方法(橡皮擦功能)
实际测试了下,对遮罩擦除做法这个效果不太满意。于是再研究了一下,想到了橡皮效果,直接用点光源图片把战争迷雾一点点擦掉又如何呢?赶紧仔细看了相关api,还真有类似的实现效果。主要还是bitmapData的draw方法,重点是这个方法的第四个参数,

source:IBitmapDrawable — 要绘制到 BitmapData 对象的显示对象或 BitmapData 对象 
matrix:Matrix (default = null) — 一个 Matrix 对象,用于缩放、旋转位图或转换位图的坐标。。 
colorTransform:flash.geom:ColorTransform (default = null) — 一个 ColorTransform 对象
blendMode:String (default = null) — 指定要应用于所生成位图的混合模式。 

所以我们每次在战争迷雾这个层次这里每次根据玩家移动,调用draw方法把角色带的点光源图片给draw进入战争迷雾的BitmapData中,然后设置为根据alpha的参数来擦出,露出最终的背景就行了。

BlendMode.ERASE //提供混合模式可视效果的常量值的类。
//设置需要draw的坐标位置
var matrix:Matrix = new Matrix(1,0,0,1,role.x,role.y);
fogBitmapData.draw(pointBitmap,matrix,null,BlendMode.ERASE);

最终效果图:
这里写图片描述

代码实现

代码已经有比较详细的注释了,这里不做解释,具体自己看代码了。可以运行两个例子来比较。
代码例子源码下载:2D游戏战争迷雾的实现例子(AS3版本)
1. 遮罩擦除做法代码,FogLightTest.as

/*** 战争迷雾遮罩灯效果测试例子* @author sodaChen* Date:2017-2-16*/[SWF(width="1274",height="768")]public class FogLightTest extends Sprite{/** 背景 **/[Embed(source = "res/alpha/bg.jpg")]private var bgClass:Class;//点光源图片[Embed(source = "res/alpha/light4.png")]private var shadowClass:Class;/** 打开的迷雾图像源,用来擦出迷雾 **/private var openFogBitmap:Bitmap;/** 原始点光源图片,用来确定一个角色视野范围的 **/private var pointBitmap:Bitmap;/** 存放已经开启的迷雾图片 **/private var pointBitmapDatas:Vector.<uint>;/** 点光源的大小范围 **/private var pointRect:Rectangle;private var role:Sprite;/** 光源的移动 **/private var speed:int = 10;public function FogLightTest(){addEventListener(Event.ADDED_TO_STAGE,onStage);}private function onStage(evt:Event):void{//添加背景addChild(new bgClass());/文本的正式测试代码啦///新建一个专门做点光源的顶层容器var topContainer:Sprite = new Sprite();topContainer.mouseEnabled = false;//强制为该显示对象创建一个透明度组topContainer.blendMode = BlendMode.LAYER;addChild(topContainer);//创建黑色的迷雾var mask:Shape = new Shape();mask.graphics.beginFill(0x000000);mask.graphics.drawRect(0,0,1274,768);mask.graphics.endFill();topContainer.addChild(mask);//制作点光源,用来擦亮迷雾,具体的擦出在下面的鼠标事件那里pointBitmap = new shadowClass();//创建擦亮迷雾后的视野图片pointRect = new Rectangle(0,0,pointBitmap.bitmapData.width,pointBitmap.bitmapData.height);openFogBitmap = new Bitmap(new BitmapData(1274,768,true,0));//复制最开始的位置openFogBitmap.bitmapData.copyPixels(pointBitmap.bitmapData,pointRect,new Point(450,300));//根据显示对象的 Alpha 值擦除迷雾openFogBitmap.blendMode = BlendMode.ERASE;topContainer.addChild(openFogBitmap);/** 移动中的主角 **/role = new Sprite();role.x = 450; role.y = 300;topContainer.addChild(role);stage.addEventListener(KeyboardEvent.KEY_DOWN,onKeyDown);}private function onKeyDown(evt:KeyboardEvent):void{//4个方向键的控制if(evt.keyCode == Keyboard.DOWN) role.y += speed;else if(evt.keyCode == Keyboard.UP) role.y -= speed;else if(evt.keyCode == Keyboard.LEFT) role.x -= speed;else if(evt.keyCode == Keyboard.RIGHT) role.x += speed;//暂时不考虑性能,不停地写新的图像数据openFogBitmap.bitmapData.copyPixels(pointBitmap.bitmapData,pointRect,new Point(role.x,role.y),null,null,true);}
  1. 直接擦出战争迷雾方法(橡皮擦功能)代码,EraserFogTest.as
   /*** 迷雾战争擦除效果* @author sodaChen* Date:2017-2-16*/[SWF(width="1274",height="768")]public class EraserFogTest extends Sprite{/** 背景 **/[Embed(source = "res/alpha/bg.jpg")]private var bgClass:Class;//点光源图片[Embed(source = "res/alpha/light4.png")]private var shadowClass:Class;/** 打开的迷雾图像源,用来擦出迷雾 **/private var openFogBitmap:Bitmap;/** 光源,擦亮迷雾的范围 **/private var pointBitmap:Bitmap;private var role:Sprite;/** 光源的移动 **/private var speed:int = 10;/** 迷雾的图像数据源 **/private var fogBitmapData:BitmapData;public function EraserFogTest(){addEventListener(Event.ADDED_TO_STAGE,onStage);}private function onStage(evt:Event):void{//添加背景addChild(new bgClass());/文本的正式测试代码啦///新建一个专门做点光源的顶层容器var topContainer:Sprite = new Sprite();topContainer.mouseEnabled = false;//强制为该显示对象创建一个透明度组topContainer.blendMode = BlendMode.LAYER;addChild(topContainer);//创建黑色的迷雾var mask:Shape = new Shape();//颜色可以选自己喜欢的mask.graphics.beginFill(0x000000);mask.graphics.drawRect(0,0,1274,768);mask.graphics.endFill();fogBitmapData = new BitmapData(1274,768);fogBitmapData.draw(mask);topContainer.addChild(new Bitmap(fogBitmapData));//制作点光源,用来擦亮迷雾,具体的擦出在下面的鼠标事件那里pointBitmap = new shadowClass();/** 移动中的主角 **/role = new Sprite();role.x = 450; role.y = 300;topContainer.addChild(role);//默认位置openFog();stage.addEventListener(KeyboardEvent.KEY_DOWN,onKeyDown);}private function onKeyDown(evt:KeyboardEvent):void{//4个方向键的控制if(evt.keyCode == Keyboard.DOWN) role.y += speed;else if(evt.keyCode == Keyboard.UP) role.y -= speed;else if(evt.keyCode == Keyboard.LEFT) role.x -= speed;else if(evt.keyCode == Keyboard.RIGHT) role.x += speed;openFog();}private function openFog():void{//设置需要draw的坐标位置var matrix:Matrix = new Matrix(1,0,0,1,role.x,role.y);//正常的daw方法,主要参数是后面的BlendMode.ERASE。根据pointBitmap的透明度来擦除fogBitmapDatafogBitmapData.draw(pointBitmap,matrix,null,BlendMode.ERASE);}

这篇关于2D游戏平滑的迷雾战争效果的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/702237

相关文章

基于Python实现PDF动画翻页效果的阅读器

《基于Python实现PDF动画翻页效果的阅读器》在这篇博客中,我们将深入分析一个基于wxPython实现的PDF阅读器程序,该程序支持加载PDF文件并显示页面内容,同时支持页面切换动画效果,文中有详... 目录全部代码代码结构初始化 UI 界面加载 PDF 文件显示 PDF 页面页面切换动画运行效果总结主

React实现原生APP切换效果

《React实现原生APP切换效果》最近需要使用Hybrid的方式开发一个APP,交互和原生APP相似并且需要IM通信,本文给大家介绍了使用React实现原生APP切换效果,文中通过代码示例讲解的非常... 目录背景需求概览技术栈实现步骤根据 react-router-dom 文档配置好路由添加过渡动画使用

使用Python实现生命之轮Wheel of life效果

《使用Python实现生命之轮Wheeloflife效果》生命之轮Wheeloflife这一概念最初由SuccessMotivation®Institute,Inc.的创始人PaulJ.Meyer... 最近看一个生命之轮的视频,让我们珍惜时间,因为一生是有限的。使用python创建生命倒计时图表,珍惜时间

Python开发围棋游戏的实例代码(实现全部功能)

《Python开发围棋游戏的实例代码(实现全部功能)》围棋是一种古老而复杂的策略棋类游戏,起源于中国,已有超过2500年的历史,本文介绍了如何用Python开发一个简单的围棋游戏,实例代码涵盖了游戏的... 目录1. 围棋游戏概述1.1 游戏规则1.2 游戏设计思路2. 环境准备3. 创建棋盘3.1 棋盘类

防近视护眼台灯什么牌子好?五款防近视效果好的护眼台灯推荐

在家里,灯具是属于离不开的家具,每个大大小小的地方都需要的照亮,所以一盏好灯是必不可少的,每个发挥着作用。而护眼台灯就起了一个保护眼睛,预防近视的作用。可以保护我们在学习,阅读的时候提供一个合适的光线环境,保护我们的眼睛。防近视护眼台灯什么牌子好?那我们怎么选择一个优秀的护眼台灯也是很重要,才能起到最大的护眼效果。下面五款防近视效果好的护眼台灯推荐: 一:六个推荐防近视效果好的护眼台灯的

国产游戏崛起:技术革新与文化自信的双重推动

近年来,国产游戏行业发展迅猛,技术水平和作品质量均得到了显著提升。特别是以《黑神话:悟空》为代表的一系列优秀作品,成功打破了过去中国游戏市场以手游和网游为主的局限,向全球玩家展示了中国在单机游戏领域的实力与潜力。随着中国开发者在画面渲染、物理引擎、AI 技术和服务器架构等方面取得了显著进展,国产游戏正逐步赢得国际市场的认可。然而,面对全球游戏行业的激烈竞争,国产游戏技术依然面临诸多挑战,未来的

火柴游戏java版

代码 /*** 火柴游戏* <p>* <li>有24根火柴</li>* <li>组成 A + B = C 等式</li>* <li>总共有多少种适合方式?</li>* <br>* <h>分析:</h>* <li>除去"+"、"="四根,最多可用火柴根数20根。</li>* <li>全部用两根组合成"1",最大数值为1111。使用枚举法,A和B范围在0~1111,C为A+B。判断</li>** @

国产游戏行业的崛起与挑战:技术创新引领未来

国产游戏行业的崛起与挑战:技术创新引领未来 近年来,国产游戏行业蓬勃发展,技术水平不断提升,许多优秀作品在国际市场上崭露头角。从画面渲染到物理引擎,从AI技术到服务器架构,国产游戏已实现质的飞跃。然而,面对全球游戏市场的激烈竞争,国产游戏技术仍然面临诸多挑战。本文将探讨这些挑战,并展望未来的机遇,深入分析IT技术的创新将如何推动行业发展。 国产游戏技术现状 国产游戏在画面渲染、物理引擎、AI

Golang支持平滑升级的HTTP服务

前段时间用Golang在做一个HTTP的接口,因编译型语言的特性,修改了代码需要重新编译可执行文件,关闭正在运行的老程序,并启动新程序。对于访问量较大的面向用户的产品,关闭、重启的过程中势必会出现无法访问的情况,从而影响用户体验。 使用Golang的系统包开发HTTP服务,是无法支持平滑升级(优雅重启)的,本文将探讨如何解决该问题。 一、平滑升级(优雅重启)的一般思路 一般情况下,要实现平滑

Golang服务平滑重启

与重载配置相同的是我们也需要通过信号来通知server重启,但关键在于平滑重启,如果只是简单的重启,只需要kill掉,然后再拉起即可。平滑重启意味着server升级的时候可以不用停止业务。 我们先来看下Github上有没有相应的库解决这个问题,然后找到了如下三个库: facebookgo/grace - Graceful restart & zero downtime deploy for G