如何实现一个水面
August 13, 2017
如何在2d游戏中实现一个水面?
水如何影响被水淹没的物体的颜色?
被水淹没的物体改变了颜色,这里处于水面以下的物体经过了一层映射,处于水面的物体经过了两层映射。颜色的映射存储在sprite-sheet中。
水下颜色的映射关系
通过一段简单的代码获取颜色的映射关系。
function dr_image()
for i=0, 15 do
local x = i * 8
rectfill(x, 40, x+8, 48, i)
rectfill(x, 50, x+8, 58, sget(48+i, 2))
end
end
因为要表现的是绿色的水,所以大部分颜色都映射成了绿色,以及黄色。
水表面颜色的映射关系
映射代码,注意两次sget实现了颜色的两次映射:
function dr_image()
for i=0, 15 do
local x = i * 8
rectfill(x, 40, x+8, 48, i)
local pix=sget(48+i,1)
rectfill(x, 50, x+8, 58, sget(48+pix, 2))
end
end
这次大部分的颜色都被映射成了浅绿色和黄色,这就是水表面的颜色。
如何让水面波动起来?
水面的波形很像cos,sin的函数图像。还记得高中的三角函数知识么?
- 其中cmx=hero.x-64,将hero的x坐标带入,这样当hero移动的时候水面的波浪也能显示正常。
- 第一个cos负责产生原始的波浪
第二个cos负责随时间波浪的强度变化
function gwy(x) local n=cos((cmx*1.5+x)/48)*cos(t/40)*3 --具体负责产生弯曲的波浪 local wy=water_y+get_tide(x-cmx)+n --负责潮涨潮落 return wy end
具体绘制函数
通过遍历x轴的每一个像素,计算当前x对应的y坐标,波浪是通过三角函数计算所得。
通过first变量存储水面的厚度,这些像素会存在两次要颜色转换。
-- ocean
for x=0,127 do
first=2 --水面同色层的厚度
by=gwy(x) --获取高度
for y=by,128 do
pix=pget(x,y) --获取屏幕上需要绘制点的原始颜色
if first>0 then
for i=1,first do
pix=sget(48+pix,1) --获取spritesheet上(48+pix, 1)位置的颜色,一次颜色映射
end
first-=1
end
pset(x,y,sget(48+pix,2)) --获取spritesheet上(48+pix, 2)位置的颜色, 一次颜色映射
end
end
让它平静如水
给循环中获取高度的地方传递一个固定的值,让水面的y值固定下来,就能获得一个平静的水面了。
by=90
让水面变厚实一些
first=5 --水面同色层的厚度
让水面波动更加明显些
给一个三角函数乘上一个值,让它y值范围增加。
local n=cos((cmx*1+x)/48)*cos(t/40)*7
总结一下本次实现一个水面的要素
- 颜色转换。
- 水表面颜色的特殊处理。
- 水面波浪。
- 高低起伏的潮汐效果。
颜色转换
和水表面颜色的特殊处理
主要体现了水的物理材质特性,想不想喝一口呢:)