level 5
文花帖的照相机拍照过程中,游戏内容几乎是暂停的。此时只有照相能正常移动。以此得到的原理就是拍照过程中不执行游戏内的帧逻辑,而只执行照相机的帧逻辑。
我们知道游戏的暂停菜单就是这样的。当玩家切出暂停菜单后,游戏内帧逻辑停止,此时luastg只处理暂停菜单的帧逻辑。以此类推,我们需要将照相机制作成一个类似暂停菜单的东西。这里就需要修改ext.lua实现。
2018年09月02日 13点09分
3
level 5
这里我们创建一个名为tengucamera的obj
使用到函数
tengucamera=Class(object)
function tengucamera:init(VV,HH,preok,RR3,photob,photoPRE,photoOK,decay,speed)
.......
end
function tengucamera:frame()
.......
end
function tengucamera:render()
.......
end
2018年09月02日 13点09分
4
level 5
我们知道,玩家在没拍照的时候是有个小型取景框跟随在自机旁边的。拍照时取景框会张开变为一个大取景框,并且随时间缩小。
VV 是小取景框的半宽度
HH 是小取景框的半长度 则self.RR=sqrt(VV^2+HH^2)
对于取景框来说,无论是拍摄时还是拍摄后,VV / HH的比值是不变的。
preok 是蓄力需要的总时间
RR3 是拍摄时取景框张开后对角线一半的长度
photob 是小取景框的取景框的素材
photoPRE 是小取景框的蓄力时取景框中心旋转的素材
photoOK 是小取景框的蓄力完成后取景框中心十字型素材
decay 是大取景框随时间衰减的系数。
speed 是大取景框移动的速度。
2018年09月02日 13点09分
6
level 5
这样我们就有
function tengucamera:init(VV,HH,preok,RR3,photob,photoPRE,photoOK,decay,speed)
--三个照片机的素材
self.photob=photob
self.photoPRE=photoPRE
self.photoOK=photoOK
--
self.decay=decay --拍照时取景框大小衰减系数
self.moveSpeed=speed --相机移动速度
self.centerx=player.x
self.centery=player.y
self.rot=0
self.layer=LAYER_TOP+3
self.group=GROUP_GHOST
self.bound=false
self.VV=VV-- --小取景框宽
self.HH=HH-- --小取景框长
self.preok=preok-- --蓄力量
self.RR=sqrt(self.VV^2+self.HH^2)
self.RR3=RR3
self.ata=atan(self.HH/self.VV) --比值
self.photoing=false
self.writing=false
self.numofphoto=0
self.photodata={} --当前照相机储存的照片表
self.obj=nil
self.photo_hscore=0
self.A={x=self.centerx+self.RR*cos(self.rot+self.ata),y=self.centery+self.RR*sin(self.rot+self.ata)}
--照相机角A的位置, 根据照相机中心点P的坐标换算
self.B={x=self.centerx+self.RR*cos(self.rot-self.ata),y=self.centery+self.RR*sin(self.rot-self.ata)}
--照相机角B的位置
self.C={x=self.centerx-self.RR*cos(self.rot+self.ata),y=self.centery-self.RR*sin(self.rot+self.ata)}
--照相机角C的位置
self.D={x=self.centerx-self.RR*cos(self.rot-self.ata),y=self.centery-self.RR*sin(self.rot-self.ata)}
--照相机角D的位置
globecamera=self
end
2018年09月02日 13点09分
7
由于照相机在同一时刻有且仅有一个,为了方便获取照相机表的变量,这里使用全局变量globecamera代表照相机。
2018年09月02日 13点09分
level 5
上述中我们还需要两个flag
self.photoing=false
self.writing=false
来判断照相机的两个状态
其中self.photoing=true是指在拍摄键按下后取景框变大,直到到达照相限制时间这一段状态。
self.writing=true 是指在拍摄键按下,并松开后,取景完毕,生成照片,照片飞行到指定位置的这一段状态。
2018年09月02日 13点09分
8
level 5
需要注意的是,在self.photoing=true 和self.writing=true 时,照相机的帧逻辑是靠ext.lua内的帧逻辑处理函数处理的。self.photoing=true
故这里照相机的帧逻辑只处理小取景框状态下的照相机。
function tengucamera:frame()
if player.hide then self.hide=true end
if self.photoing then return end --在拍照时跳过下面的逻辑处理
self.C={x=self.centerx+self.RR*cos(self.rot+self.ata),y=self.centery+self.RR*sin(self.rot+self.ata)}
self.D={x=self.centerx+self.RR*cos(self.rot-self.ata),y=self.centery+self.RR*sin(self.rot-self.ata)}
self.A={x=self.centerx-self.RR*cos(self.rot+self.ata),y=self.centery-self.RR*sin(self.rot+self.ata)}
self.B={x=self.centerx-self.RR*cos(self.rot-self.ata),y=self.centery-self.RR*sin(self.rot-self.ata)}
end
2018年09月02日 13点09分
9
level 5
找到ext.lua的FrameFunc()函数,该函数使用来处理游戏内整体帧逻辑的。
在不是正在播放录像的状态下,我们添加代码
if IsValid(globecamera) then
if globecamera.photoing then
........
end
end
第一个if用来判断globecamera是否有效。以免产生错误的索引。
第二个if用来判断globecamera是否正在拍照(此时是大取景框)。
在拍照的时候我们使用
task.Do(globecamera)来执行globecamera的帧逻辑处理。如果使用frame函数的话,必须需要DoFrame()来驱动,为了剥离globecamera的帧逻辑,这里沿袭pause menu的做法,使用task来完成。
加入lilycameraticker变量,来暂停效果逐渐变弱的功能。
实际上就是相机照相时刻的timer
lilycameraticker=lilycameraticker+1
local A=10
if lilycameraticker<60 and lilycameraticker>45 then
A=2
elseif lilycameraticker<45 and lilycameraticker>30 then
A=6
elseif lilycameraticker<30 and lilycameraticker>15 then
A=9
elseif lilycameraticker<15 and lilycameraticker>7 then
A=10
end
if lilycameraticker%A==0 then --照相机的timer能被A整除时就执行一次游戏内的帧逻辑处理。
DoFrame() ---执行 游戏内的帧逻辑
ext.pause_menu_order=nil ---禁止弹出暂停菜单(可以去掉)
end
2018年09月02日 13点09分
13
level 5
当照相机处于writing状态时,此时相机的帧逻辑暂停,处理照片的帧逻辑。(照片边旋转边飞向指定位置)
故上述第二个if内完整的为
if IsValid(globecamera) then
if globecamera.photoing then
task.Do(globecamera)
lilycameraticker=lilycameraticker+1
local A=10
if lilycameraticker<60 and lilycameraticker>45 then
A=2
elseif lilycameraticker<45 and lilycameraticker>30 then
A=6
elseif lilycameraticker<30 and lilycameraticker>15 then
A=9
elseif lilycameraticker<15 and lilycameraticker>7 then
A=10
end
if lilycameraticker%A==0 then
--cheat=true
DoFrame()
--PlaySound("lgods2",1)
ext.pause_menu_order=nil
end
elseif globecamera.writing then
task.Do(lilyphoto)
else
lilycameraticker=0
--cheat=true
DoFrame()
end
else
DoFrame()
end
2018年09月02日 13点09分
14
照相机的照片是全局变量lilyphoto
2018年09月02日 13点09分
level 5
此时我们考虑取景框,照片的渲染,以及如何使用shader获得纹理信息
2018年09月02日 13点09分
15
level 5
注意观察函数RenderFunc()
原本顺序是
BeginScene()
BeforeRender()
stage.current_stage:render()
ObjRender()
AfterRender()
EndScene()
2018年09月02日 13点09分
16