制作一款打飞机游戏教程6:射击优化
我们能够驾驶飞船四处移动,这很酷,我们还能开火,但这射击效果并不理想。我们得想办法改进这个射击效果。
另外,我们还忘记了上次没有创建喷射火焰,也就是飞船尾部喷出的实际火焰。这是我们没做好的地方,也是今天我们要做的一个重要方面。
添加喷射火焰
我想这是一个很好的练习,因为今天我们要做很多动画,而喷射火焰是一个不错的、简单的方式来测试动画。
现在,我要拖入一些资源。
动画实现
我们可以通过拖放PNG文件来添加资源。现在我有了一个美丽的火焰动画,我们需要让两个火焰从飞船尾部射出。
调整火焰位置
我们需要调整火焰的位置。让我们给y坐标加上15看起来更合适一些。然后,在曝光上我们加上6,看起来不错。
动画循环
现在我们需要做动画。让我们创建一个数组,然后计算我们需要的动画帧数。火焰的动画是伸展和收缩,伸展和收缩。
我们需要循环播放这个动画,所以我们将使用一个t
变量作为计数器。在init
函数中,我们将t
设置为0,然后在update60
函数的一开始,我们将t
加1。
我们还需要打印一些信息到屏幕上,让我们清除一些不必要的信息,只打印t
和shot_weight
。现在我们可以看到顶部的值在增加,这就是帧数的计数。
调整动画速度
现在,我们可以使用t
变量来做动画。一个简单的方法是使用t
来索引数组,但为了循环播放动画,我们需要对t
进行取模操作。因为Lua数组的索引是从1开始的,所以我们需要对t
除以4的结果加1来得到正确的帧索引。
但是,直接这样做会导致问题,因为t
是一个浮点数。我们可以使用math.floor
函数来解决这个问题。
不过,动画看起来有点太快了,我们可以通过调整t
的值来减慢动画速度。
改进射击效果
现在,让我们来讨论如何改进射击效果。这看起来并不理想。首先,我们想在屏幕上显示当前有多少颗子弹。这可以通过在绘制时附加一些字符串来实现。
另外,如果子弹离开了屏幕,我们应该删除它们。我们可以通过检查子弹的y坐标是否小于某个值(比如-8)来实现这一点。
双发子弹与射击限制
接下来,我们尝试添加双发子弹,并调整它们的位置,让它们看起来像是从飞船的机身射出。但是,仅仅增加子弹的数量并不够,我们还需要让子弹射得更快一些。
然而,增加子弹的射击频率又会导致另一个问题:子弹看起来像是在闪烁,这就是所谓的“闪烁效应”。为了解决这个问题,我们可以降低射击频率,或者给子弹添加一些变化,比如不同的颜色或动画。
此外,我们还可以设置一个子弹数量的上限,这样当子弹数量达到这个上限时,就不能再发射新的子弹了。这个上限、子弹的速度和射击频率是相互关联的,我们需要根据游戏的感觉来调整它们。
我还做了一些研究,查看了其他射击游戏(shmups)的子弹速度和效果。我发现它们的子弹速度都比我们之前尝试的要快得多。
现在,让我们尝试一种新的子弹效果。我受到Dodonpachi游戏的启发,制作了一个更长的、有动画的子弹效果。这种子弹效果看起来更有力量感,也更容易跟踪其运动轨迹。
我们还可以通过切换不同的武器来比较它们的效果。我创建了一个武器切换系统,现在我们可以尝试使用Ryden和Dodonpachi两种不同的子弹效果了。
这里有一个子弹动画,我们想让这个子弹动画应用到每个子弹上。现在每个子弹只是显示这个精灵(箭头精灵)。
我认为如果我们添加动画,我们可以进一步改善这种感觉。当我们添加动画时,我们还想添加枪口火光,这很重要,每当有东西出现时。现在,它就像子弹突然出现,而且它们就像出现在飞船上一样。我们想让这看起来更自然,通过制作枪口火光,这样就有了一个视觉解释,解释为什么子弹会出现以及它们是从哪里来的。
动画实现与调整
现在我们有了动画,当我们绘制射击时,我们需要从sunny
数组中获取精灵,而不是从之前的s
属性中获取。
这是计算数组中我们将要在这一帧显示的条目的索引的代码。我们从sunny
数组中获取这个值,并把它放入这个变量中,然后我们可以直接把这个变量放入精灵函数中。
但是,我们可以让每颗子弹都有自己的动画偏移量,为整个射击添加更多运动。我们可以在发射时记录时间,并为每颗子弹跟踪其当前帧。
现在动画正在播放,但看起来有点快。我们可以放慢动画速度。现在我们可以把速度调回来,让子弹飞得很快,但我们仍然能够看到一些运动。我们可以使用动画来做到这一点。
为了做到这一点,我们正在改变每颗子弹的动画起始帧。这样每颗子弹都会有一个不同的起始动画帧,这会打破那种闪烁效应,因为我们不是重复相同的动画序列,而是每颗子弹都有一个新的序列。
枪口火光与声音效果
接下来我们处理之前提到的枪口火光。我做了很多枪口火光的实验,这是我最后想出来的。每当我带来新资产时,它们都会放在Doobly Doo里。
我们将创建一个新的数组来包含所有的枪口火光,然后在发射子弹时,使用与添加射击相同的技术来添加枪口火光。我们需要为枪口火光添加动画,然后当它完成时,它会删除自己。
现在我们需要把这个添加到更新函数中,然后绘制枪口火光。枪口火光应该在射击后面绘制,我感觉稍后我们需要把飞船放在所有东西的最上面。
现在我们有了枪口火光,但位置不太对。我们需要调整它的位置。现在子弹出现得太低了,我们可以把它们调高一点。
现在还有一个问题是枪口火光感觉像是在闪烁,它看起来不连贯。我认为问题是我们射击得太频繁了。让我们降低射击频率,现在它感觉更像是在动画了。
最后,我们没有声音效果,所以你不能真正判断某样东西感觉起来如何。让我们添加一个声音效果。
pico-8 cartridge // http://www.pico-8.com
version 41
__lua__
-- t: make basic movement feel nice
-- ❎: fixed cobblestoning
-- ❎: what is a good movement speed
-- ❎: do banking-- ❎: make shooting feel nice!-- ❎: normalized diagonalsbutarr={1,2,0,3,5,6,3,4,8,7,4,0,1,2,0}dirx={-1,1, 0,0, -0.7, 0.7,0.7,-0.7}
diry={ 0,0,-1,1, -0.7,-0.7,0.7,0.7}butarr[0]=0shiparr={1,3,5,7,9}shipspr=0shots={}
shotwait=0wep=2muzz={}function _init()px,py=64,64spd=1.4lastdir=0cls(0)t=0
endfunction _draw()cls(12)for s in all(shots) do spr(s.sani[flr(s.si)],s.x,s.y,1,s.sh)endfor m in all(muzz) do spr(m.sani[flr(m.si)],px+m.x,py+m.y,2,2)end--shipspr(shiparr[flr(shipspr*2.4+3.5)],px,py,2,2)local flamearr={12,13,14,13}local fframe=flamearr[t\3%4+1]spr(fframe,px+6,py+15)spr(fframe,px+3,py+15)local btnv=btn()&0b1111print(t,5,5,7)print(shotwait,5,11,7)print("shots:"..#shots,5,17,7)print("",5,23,7)
endfunction _update60()t+=1local dir=butarr[btn()&0b1111]if lastdir!=dir and dir>=5 then--anti-cobblestonepx=flr(px)+0.5py=flr(py)+0.5endlocal dshipspr=0if dir>0 thenpx+=dirx[dir]*spdpy+=diry[dir]*spddshipspr=mysgn(dirx[dir])endshipspr+=mysgn(dshipspr-shipspr)*0.15shipspr=mid(-1,shipspr,1)lastdir=dirif shotwait>0 thenshotwait-=1endif btn(❎) thenif wep==1 thenshot_raiden()elseif wep==2 thenshot_ddp()endenddoshots()domuzz()
endfunction doshots()for s in all(shots) dos.x+=s.sxs.y+=s.sys.si+=0.5if flr(s.si)>#s.sani thens.si=1endif s.y<-16 thendel(shots,s)endend
endfunction domuzz()for m in all(muzz) dom.si+=1 if flr(m.si)>#m.sani thendel(muzz,m)endend
endfunction mysgn(v) return v==0 and 0 or sgn(v)
end
-->8
function shot_raiden()if shotwait<=0 and #shots<6 thenlocal shotspd=-3.5shotwait=4add(shots,{x=px+3,y=py,sx=0,sy=shotspd,sani={11},si=1,sh=1})add(shots,{x=px+9,y=py,sx=0,sy=shotspd,sani={11},si=1,sh=1})add(muzz,{x=-4,y=-8,sani={35,37,39,41},si=0,})add(muzz,{x=4,y=-8,sani={35,37,39,41},si=0,})sfx(0)end
endfunction shot_ddp()if shotwait<=0 and #shots<100 thenlocal shotspd=-6shotwait=3add(shots,{x=px,y=py-5,sx=0,sy=shotspd,sani={32,33,34},si=(t\2)%3+1,sh=2})add(shots,{x=px+8,y=py-5,sx=0,sy=shotspd,sani={32,33,34},si=(t\2)%3+1,sh=2})add(muzz,{x=-4,y=-8,sani={35,37,39,41},si=0,})add(muzz,{x=4,y=-8,sani={35,37,39,41},si=0,})sfx(0)end
end
__gfx__
00000000000000011000000000000001100000000000000110000000000000011000000000000001100000000990000000070000000700000007000000000000
00000000000000167100000000000016710000000000001661000000000000167100000000000016710000009779000000777000007770000077700000000000
00700700000000111d100000000000111d1000000000011111100000000001d111000000000001d11100000097790000007c7000007c70000077700000000000
00077000000001ccc1100000000001ccc1100000000001cccc1000000000011ccc1000000000011ccc1000009aa9000000070000007c7000007c700000000000
0007700000001c77cc11000000001c77cc11000000001c77ccc10000000011c77cc10000000011c77cc100009aa900000000000000070000007c700000000000
0070070000001c7c1c11000000001c7c1c11000000001c7cc1c10000000011c7c1c10000000011c7c1c100000990000000070000000000000007000000000000
0000000000001c111c11100000011c111c11100000111c1111c11100000111c111c11000000111c111c100000000000000000000000700000007000000000000
0000000000001c111c17100000011c111c17100000171c1111c17100000171c111c11000000171c111c100000000000000000000000000000007000000000000
0000000000011cc17116100000161cc1171610000016117117116100000161711cc16100000161171cc110000000000000000000000000000000000000000000
000000000001d1c711d6d1000016d1c77116d10001d6d117711d6d10001d61177c1d6100001d6d117c1d10000000000000000000000000000000000000000000
00000000001ddd111d6d7d1001dddd1111dd6710176d6d1111d6d6710176dd1111dddd1001d7d6d111ddd1000000000000000000000000000000000000000000
00000000001dd6ddd6d66d1001dd66dddd6d66101666d6dddd6d66610166d6dddd66dd1001d66d6ddd6dd1000000000000000000000000000000000000000000
00000000001d676676d6dd1001d6676676d6dd101dd6d676676d6dd101dd6d6766766d1001dd6d676676d1000000000000000000000000000000000000000000
00000000000176d167d1110000117dd1171111000111171661711110001111711dd7110000111d761d6710000000000000000000000000000000000000000000
000000000000151155d110000001655155d11000000161511516100000011d551556100000011d55115100000000000000000000000000000000000000000000
00000000000001111111000000001111111100000000111111110000000011111111000000001111111000000000000000000000000000000000000000000000
00099000000990000009900000000000000000000000000770000000000000000000000000007000000700000000000000000000000000000000000000000000
00099000000990000009900000000000000000000000000770000000000070000007000000000000000000000000000000000000000000000000000000000000
00977900000990000009900000000000000000000000000770000000000070000007000000000000000000000000000000000000000000000000000000000000
00977900009aa9000009900000000000000000000000700770070000000000000000000000000000000000000000000000000000000000000000000000000000
09777790009779000009900000000007700000000007707777077000000000077000000000000000000000000000000000000000000000000000000000000000
0977779000977900009aa90000000777777000000007707777077000000000077000000070000000000000070000000000000000000000000000000000000000
97a77a7909a77a900097790000007777777700000000777777770000070000077000007000000000000000000000000000000000000000000000000000000000
97a77a7909a77a900097790000007777777700000070777777770700007000777700070000000000000000000000000000000000000000000000000000000000
9aa77aa909a77a90009aa90000077777777770000077777777777700000007777770000000000000000000000000000000000000000000000000000000000000
9aa77aa9099aa990009aa90000077777777770000007777777777000000007777770000007000007700000700000000000000000000000000000000000000000
9a9aa9a9099aa990009aa90000077777777770000000777777770000007007777770070000000007700000000000000000000000000000000000000000000000
999aa999099999900099990000007777777700000000777777770000000007777770000000000077770000000000000000000000000000000000000000000000
999aa999099999900099990000000777777000000000077777700000000000777700000000000077770000000000000000000000000000000000000000000000
90999909099999900099990000000077770000000000007777000000000000077000000000000007700000000000000000000000000000000000000000000000
90099009090990900009900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00099000000990000009900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
__sfx__
a3010000070401f6401f6300e6200d610050100301001050000100201000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000