一.综述
LuaSTG是基于hge以Lua作为扩展脚本的弹幕射击游戏引擎。
新建并运行第一个工程。
首先在mod文件夹下新建一个文件夹,文件夹名即为工程名。比如在这里我们新建一个叫做hello的文件夹。之后在hello文件夹下新建一个root.lua文件,内容如下:
hello_stage=stage.New('hello',true)
function hello_stage:init()
Print('Hello, LuaSTG.')
end
之后打开根目录下的setting.lua,将mod设置为工程名’hello’,并且将debug设置为true。此时运行lstg.exe,将会出现一个黑窗口,同时命令行里将会出现以下内容:
zip warning: ../hello.zip not found or empty
adding: root.lua (104 bytes security) (deflated 16%)
Hello, LuaSTG.
这样我们就新建并运行了一个最简单的LuaSTG工程。
二.关卡、类和单位
1.关卡
stage.New(stage_name,as_entrance,is_menu)
声明并返回一个关卡。stage_name是关卡的名称,为字符串类型,不能重复。as_entrance参数表示是否将该关卡作为整个工程的入口关卡,默认为false。is_menu参数表示该关卡是否为一个菜单关卡,默认为false。(菜单关卡和游戏关卡的唯一区别在于按下ESC键时是否弹出暂停菜单。)函数将返回这个关卡。声明关卡之后,还需要为其定义回调函数,否则他将什么都不会做,这些回调函数在各自特定的时机会被系统调用。定义的格式是:function your_stage:function_name()
— do something
end
your_stage是由stage.New函数返回的关卡,function_name为init、del、frame、render之一,他们都有各自的作用。init和del函数分别在进入和离开这个关卡时被调用,当这个关卡为当前关卡时,他的frame和render函数分别在每帧进行帧逻辑运算和帧渲染的时候被调用。所有这些函数都把关卡本身作为第一个参数self隐式传入,此外不再接受任何参数。
stage.Set(stage_name)
离开当前关卡并进入新的关卡。
stage.SetTimer(timer)
关卡的计数器为其timer域(即your_stage.timer),这个计数器在每次进入或者重新进入关卡时被设置为0零,之后每帧自动+1。该函数可以强制设置当前关卡的计数器。
stage.QuitGame()
退出程序。
参考:tut01
2.类和单位
LuaSTG的类和单位类似面向对象中类和对象的概念。LuaSTG实现的是一种较为简易的面向对象编程。
Class(base)
声明一个类,base为新声明类的基类。和关卡类似,类也需要定义一系列回调函数,他们是init、del、kill、frame、render、colli。新定义的类会继承基类所有的回调函数,并且可以对其进行覆盖式的重定义,除此之外不继承基类的任何其他内容。所有回调函数都把单位作为第一个参数self隐式传入,此外还可能会有额外的参数。
回调函数:
init
在单位被创建时被调用,创建时的初始化参数列表将会被作为额外的参数传入。
del
在单位被清除时被调用。
kill
在单位被击杀时被调用。
frame
在进行帧逻辑运算的时候被调用。
render
在进行帧渲染的时候被调用。
colli
在单位被其他单位碰撞的时候被调用。将碰撞他的单位作为第二个参数传入。
New(class,…)
创建并返回一个类为class的单位,…是初始化参数列表,数量可以是任意个,会被作为参数传进class的init函数。
Del(unit)
清除一个单位。该单位的类的del函数会被触发。
RawDel(unit)
清除一个单位。该单位的类的del函数不会被触发。
Kill(unit)
击杀一个单位。该单位的类的kill函数会被触发。
RawKill(unit)
击杀一个单位。该单位的类的kill函数不会被触发。
PreserveUnit(unit)
保存一个单位,即取消当前帧里之前对其进行的Del、RawDel、Kill、RawKill操作。
IsValid(unit)
判断该单位是否为一个有效的而且存活的单位。一个单位在其被清除或者击杀之后的一帧开始,将会变成无效的。
UnitList(group)
返回一个迭代器,能够遍历碰撞组为group的所有单位,如果group为GROUP_ALL=16,则遍历所有单位。用法是:for i,unit in UnitList(group) do
–do something
end
GetnUnit()
返回单位的总数。
SetV(unit,v,angle,set_rot)
设置单位的速度和角度。等价于下面函数:
function SetV(unit,v,angle,set_rot)
unit.vx=v*cos(angle)
unit.vy=v*sin(angle)
if set_rot then unit.rot=angle end
end
BoxCheck(unit,x1,x2,y1,y2)
检查单位的坐标是否处在指定的矩形范围内。等价于下面函数:
function BoxCheck(unit,x1,x2,y1,y2)
return unit.x>x1 and unit.x<x2 and unit.y>y1 and unit.y<y2
end
Dist(unit1,unit2)
Dist(x1,y1,x2,y2)
返回两个单位之间的距离。
Angle(unit1,unit2)
Angle(x1,y1,x2,y2)
返回单位1指向单位2的角度,取值-pi~+pi之间。
3.单位的属性
单位的属性可以通过“单位.属性”的格式来访问。
单位的属性分为内建属性和自定义属性。他们的访问方式完全相同。内建属性是被赋予了一定意义的属性,自定义属性只是为了方便的为每个单位存储和他相关的一些变量。
内建属性:
class
单位的类。
x
单位的x坐标。默认为0。
y
单位的y坐标。默认为0。
rot
单位的朝向。默认为0。
vx
单位的x坐标的每帧的自增量。默认为0。
vy
单位的y坐标的每帧的自增量。默认为0。
omiga
单位的朝向的每帧的自增量。默认为0。
(注:x/y/rot的自增运算在帧逻辑函数之后进行。)
timer
计数器,在单位被创建时为0,以后每帧+1。
img
单位的显示图像,字符串类型,默认为空。可以是image、animation或者particle system的name(见图像处理部分)。如果单位设置了img属性而且默认的render函数没有被重定义覆盖,那么将会把img的图像根据x、y、rot、hscale、vscale属性进行渲染。对单位的img属性进行赋值时,会自动改变该单位的碰撞尺寸a和b(见下文)为该图像的a和b。
layer
单位的图层,决定单位之间渲染的先后顺序,越大渲染的顺序越靠后,即越是在顶层。取值可以是任意浮点数。单位的layer默认为0。LuaSTG预定义的图层:
LAYER_BG=-700
LAYER_ENEMY=-600
LAYER_PLAYER_BULLET=-500
LAYER_PLAYER=-400
LAYER_ITEM=-300
LAYER_ENEMY_BULLET=-200
LAYER_ENEMY_BULLET_EF=-100
LAYER_TOP=0
a
单位的纵向碰撞大小的一半。默认为0。
b
单位的横向碰撞大小的一半。默认为0。
rect
单位的碰撞判定是否为矩形。如果为true,则单位的碰撞判定为长和宽分别为2a和2b的矩形,否则为长轴和短轴分别为a和b的椭圆。默认为false。
colli
单位是否参与碰撞检测。默认为true
group
单位所在的碰撞组。LuaSTG一共支持16个碰撞组。LuaSTG预定义的碰撞组:
GROUP_GHOST=0
GROUP_ENEMY_BULLET=1
GROUP_ENEMY=2
GROUP_PLAYER_BULLET=3
GROUP_PLAYER=4
GROUP_INDES=5
GROUP_ITEM=6
在每帧,LuaSTG会做如下的碰撞检查:
CollisionCheck(GROUP_PLAYER,GROUP_ENEMY_BULLET)
CollisionCheck(GROUP_PLAYER,GROUP_ENEMY)
CollisionCheck(GROUP_PLAYER,GROUP_INDES)
CollisionCheck(GROUP_ENEMY,GROUP_PLAYER_BULLET)
CollisionCheck(GROUP_ITEM,GROUP_PLAYER)
逐个检测前一组中的每个对象是否与后一组中的任何对象发生碰撞,如果是,则调用前一个象的colli函数,将后一个对象作为参数传入。单位的碰撞组默认为GROUP_GHOST。
dx
单位的x坐标和前一帧相比的变化值。
dy
单位的y坐标和前一帧相比的变化值。
status
单位的状态,可以是’normal’、’del’、’kill’之一,分别表示正常、被清除、被击杀。被清除或者击杀的单位在当前帧仍然是有效的,但是status属性会被设置为STATUS_DEL或STATUS_KILL;status属性为STATUS_DEL或STATUS_KILL的单位在当前帧结束之后变为无效的单位。所以,Del函数等效于:function Del(unit)
unit.status=’del’
unit.class.del(unit)
end
Kill同样。
hide
是否隐藏单位,如果为true,则每帧跳过该单位的render函数的执行。默认为false。
bound
单位离开显示范围之后是否被自动清除。默认为true。
navi
是否根据单位的运动方向自动计算并调整其朝向。即用dx和dy计算rot。默认为false。
hscale
单位的纵向拉伸率。只改变图像大小,不对碰撞判定大小造成影响。默认为1。
vscale
单位的横向拉伸率。只改变图像大小,不对碰撞判定大小造成影响。默认为1。
ani
单位的动画计数器。和timer类似,但是专门用于动画的渲染。引入其的目的是为了避免在timer的值发生跳变的时候单位的动画会跳变的情况。一般情况下不会对其进行手动修改。
三.资源
LuaSTG的资源文件有脚本(.lua)、图像(.png .bmp)、粒子效果(.psi)、字体索引(.fnt)、声音(.wav .mp3)几种,存储在data文件夹和mod文件夹下的工程文件夹内。LuaSTG以debug模式运行时,会分别先将他们打包成data.zip和project_name.zip,然后在加载这两个zip包,非debug模式会省略打包的过程,直接加载zip包。加载资源时,LuaSTG会优先从project_name.zip里搜索,没有找到则在data.zip里继续搜索。
Include(scriptfilename)
加载脚本。因为加入了对已加载脚本的判断,所以可以重复加载甚至循环加载。
除脚本资源之外的其他资源的加载函数都以Load开头,这些函数的第一个参数都为一个字符串型,叫做资源的name,同种资源的name不能重复。
LuaSTG的资源共有下列几种:
1.纹理(tex)
通过函数LoadTexture、LoadImageFromFile从png等图像格式文件中加载。
2.图像(img)
通过函数LoadImage、LoadImageFromFile、LoadImageGroup从纹理中加载。
3.动画(ani)
通过函数LoadAnimation从纹理中加载。
4.背景音乐(bgm)
通过函数LoadMusic从.mp3等音频格式文件中加载。
5.音效(snd)
通过函数LoadSound从.wav等音频格式文件中加载。
6.粒子效果(psi)
通过函数LoadPS从psi文件中加载。
7.位图字体(fnt)
通过函数LoadFont从fnt文件中加载。
8.true type字体(ttf)
通过函数LoadTTF从ttf等字体格式文件中加载。
除脚本资源之外的其他资源,如果是在脚本的顶级代码里加载,那么此时加载的资源被认为是全局的,会一直存在;否则这些资源在离开当前关卡之后将会被自动清除。
CheckRes(restype,resname)
检查指定资源是否存在,如果是全局资源资源,则返回’global’;如果是关卡资源,则返回’stage’;如果资源不存在,则返回nil。
restype可以为’tex’、’img’、’ani’、’bgm’、’snd’、’psi’、’fnt’、’ttf’之一。
EnumRes(restype)
返回两个table,内容分别是指定类型的所有全局资源和关卡资源的名字。
restype可以为’tex’、’img’、’ani’、’bgm’、’snd’、’psi’、’fnt’、’ttf’之一。
四.图像处理
1. 颜色
Color(hexcode)
Color(A,R,G,B)
返回一个颜色对象,这个对象支持加法、数乘、tostring、==和~=。LuaSTG里面所有的颜色参数都应使用这个对象。
颜色对象的成员函数:
:ARGB()
返回该颜色的A、R、G、B分量。
2. 坐标系统
LuaSTG的坐标习惯是,x轴正方向为水平向右,y轴正方向竖直向上;用4个数表示一个矩形范围的习惯是左、右、下、上。(纹理坐标除外)
LuaSTG在渲染时有3套坐标,分别是世界坐标、UI坐标和3D坐标。通过函数SetViewMode来切换。
世界坐标:进行单位渲染时的坐标,单位是像素(如果分辨率是640×480的话,否则要乘以一个缩放因子)。世界区域的左下角是(-192,-224),右上角是(192,224)。单位的x和y属性指得就是在世界坐标中的值。
UI坐标:进行UI渲染时的坐标。左下角为(0,0),右上角为(640,480)。
3D坐标:进行3D渲染时的坐标。可通过Set3D函数对相机和雾效果进行具体设置。
SetViewMode(mode)
mode可以是’world’、’ui’、’3d’之一。
Set3D(key,a,b,c)
key为不同的字符串时函数将对不同的参数进行设置。
Set3D(‘eye’,x,y,z)
Set3D(‘at’,x,y,z)
Set3D(‘up’,x,y,z)
Set3D(‘z’,znear,zfar)
Set3D(‘fovy’,fovy)
上述参数的意义见:
http://www.opengl.org/sdk/docs/man/xhtml/gluLookAt.xml
http://www.opengl.org/sdk/docs/man/xhtml/gluPerspective.xml
Set3D(‘fog’,start,end[,color=Color(0x00FFFFFF)])
设置雾效果。如果start>0,则设置线性雾;若start==-1,则设置指数雾;若start==-2,则设置二次指数雾。在后面两种情形下,end参数表示雾的强度。如果start等于end,则关闭雾效果。color是雾的颜色。
Set3D只是修改3D模式的设置,并不会立即将坐标系统切换至3D模式。
3. 混合模式
混合模式blendmode可用下面字符串之一:
‘mul+add’ 顶点颜色和纹理颜色相乘,新的绘制与背景相加。
‘mul+alpha’ 顶点颜色和纹理颜色相乘,新的绘制与背景alpha混合。
‘add+add’ 顶点颜色和纹理颜色相加,新的绘制与背景相加。
‘add+alpha’ 顶点颜色和纹理颜色相加,新的绘制与背景alpha混合。
” (空字符串)默认的混合模式,与’mul+alpha’等价。
4. 图像绘制
LoadTexture(texturename,filename[,mipmap=false])
从资源文件中加载纹理。支持BMP、DDS、DIB、JPG、PNG和TGA格式。建议使用PNG格式。
LoadImage(imagename,texturename,x,y,w,h[,a=0[,b=0[,rect=false]]])
从纹理中新建图像。x、y是图像左上角在纹理中的坐标(左上角是(0,0));w、h是图像的宽和高;a、b、rect是图像的纵向、横向碰撞判定和判定形状,意义同对象的a、b、rect属性,当把一个图像的名字(imagename)赋值给一个对象的img属性时,那么对象的a、b、rect属性将会自动被赋值为图像的a、b、rect。
LoadImageFromFile(teximgname,filename[,mipmap=false])
从资源文件中加载纹理同时将整幅纹理加载为同名的图像。
LoadImageGroup(imagenameprefix,texturename,x,y,w,h,n,m[,a=0[,b=0[,rect=false]]])
从纹理中新建一组图像。n、m为列数和行数。这组图像将被命名为imagenameprefix1、imagenameprefix2、imagenameprefix3……
LoadImageGroupFromFile(teximgname,filename,mipmap,n,m[,a=0[,b=0[,rect=false]]])
从资源文件中加载纹理同时将整幅纹理加载为一组同前缀的图像。
LoadAnimation(animationname,texturename,x,y,w,h,n,m,intv[,a=0[,b=0[,rect=false]]])
从纹理中新建动画。intv是动画中相邻两幅图像间隔的帧数,即每多少帧切换为下一幅。
LoadAniFromFile(texaniname,filename,mipmap,n,m,intv[,a=0[,b=0[,rect=false]]])
从资源文件中加载纹理同时将整幅纹理加载为动画。
LoadPS(particlesystemname,filename,imagename[,a=0[,b=0[,rect=false]]])
从资源文件中加载粒子效果,所需要的psi文件可由工具Particle Editor生成。
LoadFont(fontname,filename)
从资源文件中加载位图字体。filename为fnt格式,可由工具Font Editor生成,生成的fnt文件和png文件要在同一目录下。
LoadTTF(ttfname,filename,facename,size,weight,…)
从资源文件中加载字体,支持fon/fnt/ttf/ttc/fot/otf/mmm/pfb/pfm格式。facename是字体的名称;size为字体的高度,单位是像素;weight是字体的粗细,400为普通粗细,700为粗体;可选参数是字体的变形,可以取以下一个或多个字符串:
‘italic’ 斜体
‘underline’ 下划线
‘strikeout’ 删除线
RenderClear(color)
用一种颜色填满整个绘图区域。
Render(imagename,x,y[,rot=0[,hscale=1[,vscale=hscale[,z=0.5]]]])
绘制一个图像。
RenderRect(imagename,x1,x2,y1,y2)
将图像绘制到一个矩形上。
Render4V(imagename,x0,y0,z0,x1,y1,z1,x2,y2,z2,x3,y3,z3)
将图像绘制到一个3维的四边形上。图像左上角的顶点编号为0,顺时针旋转编号增加。如果不是在3D模式下,那么所有的z坐标要取0.5。
RenderTexture(texturename,blendmode,vertex0,vertex1,vertex2,vertex3)
将纹理的一个四边形区域绘制到一个3维四边形上。vertext是一个数组,格式为{x,y,z,u,v,color},其中u、v是纹理坐标(左上角是(0,0))。如果不是在3D模式下,那么所有的z坐标要取0.5。
RenderText(fontname,text,x,y,size,…)
绘制文字。可选参数表示文字排列和对齐的模式,可以取以下一个或多个字符串(每行限1个):
‘left’ ‘center’ ‘right’
‘top’ ‘vcenter’ ‘bottom’
或者:
‘centerpoint’ 等效于同时取’center’和’vcenter’
RenderTTF(ttfname,text,left,right,bottom,top,color,…)
在一个矩形区域中绘制文字。可选参数表示文字排列和对齐的模式,可以取以下一个或多个字符串(每行限1个):
‘left’ ‘center’ ‘right’
‘top’ ‘vcenter’ ‘bottom’
‘wordbreak’ ‘singleline’ ‘expantextabs ‘noclip’ ‘calcrect’ ‘rtlreading’
或者:
‘paragraph’等效于同时取’left’、’top’和’wordbreak’
‘centerpoint’ 等效于同时取’center’、’vcenter’和’noclip’
GetTextureSize(texturename)
返回纹理的宽和高。
SetImageState(imagename,blendmode)
SetImageState(imagename,blendmode,color0)
SetImageState(imagename,blendmode,color0,color1,color2,color3)
设置图像的混合模式和顶点颜色。图像左上角的顶点编号为0,顺时针旋转编号增加。若省略color0,则维持原顶点颜色;若省略color1、color2、color3,则将所有顶点的颜色都设置为color0。
SetImageCenter(imagename,x,y)
设置图像的中心点。默认的中心点为矩形的中心。
SetAnimationState(animationname,blendmode)
SetAnimationState(animationname,blendmode,color0)
SetAnimationState(animationname,blendmode,color0,color1,color2,color3)
设置动画的混合模式和顶点颜色。图像左上角的顶点编号为0,顺时针旋转编号增加。若省略color0,则维持原顶点颜色;若省略color1、color2、color3,则将所有定点的颜色都设置为color0。
SetAnimationCenter(animationname,x,y)
设置动画的中心点。默认的中心点为矩形的中心。
SetImgState(object,blendmode,alpha,red,green,blue)
设置单位的img的混合模式和颜色。对particle system无效。
SetFontState(fontname,blendmode)
SetFontState(fontname,blendmode,color)
设置字体的混合模式和颜色。若省略color,则维持原颜色。
SetFontState2(proportion,rotation,spacing,tracking)
设置字体的几何参数。每个参数均可以为nil,这样将被视为默认值。
ParticleStop(unit)
停止单位的粒子特效的发射,不会立即清除已发射粒子。
ParticleFire(unit)
恢复单位的粒子特效的发射。
ParticleGetn(unit)
返回单位粒子特效的当前存活的粒子数。
ParticleGetEmission(unit)
返回单位粒子特效每秒钟发射的粒子数。
ParticleSetEmission(unit,n)
设置单位粒子特效每秒钟发射的粒子数。
注:动画和粒子特效不能单独绘制,必须通过设置img属性的方式和单位绑定,并且由单位默认的render函数绘制。
五. 声音处理
LoadSound(soundname,filename)
从资源文件中加载音效。
LoadMusic(musicname,filename,loopend,looplength)
从资源文件中加载音乐。loopend是循环的结束点,looplength是循环长度,单位均为秒。
PlaySound(soundname,volume[,pan=0])
播放音效。pan取值范围-1~+1,-1表示最左边,+1表示最右边,0表示中间。
PlayMusic(musicname[,volume=1[,start=0]])
播放音乐。start为播放的起始点,单位秒。
PauseMusic(musicname)
暂停音乐。
ResumeMusic(musicname)
恢复播放音乐。
StopMusic(musicname)
停止播放音乐。
GetMusicState(musicname)
返回音乐的状态。如果音乐已经停止,则返回’stopped’;如果音乐处于播放状态,则返回’playing’和当前播放到的位置;如果音乐处于暂停状态,则返回’paused’和当前播放到的位置;
六. 键盘输入
KeyIsDown(keyname)
判断某个键是否处于按下的状态。keyname是键名,可以取’up’、’down’、’left’、’right’、’slow’、’shoot’、’spell’、’special’之一。每个键名具体对应的键由setting.lua决定。
KeyIsPressed(keyname)
判断某个键是否在当前帧被按下。即上一帧处于抬起的状态,当前帧处于按下的状态。keyname是键名,可以取’up’、’down’、’left’、’right’、’slow’、’shoot’、’spell’、’special’之一。每个键名具体对应的键由setting.lua决定。
GetLastKey()
返回最近一次按键的key code。
GetLastChar()
返回最近一次按键的character code。
GetKeyState(keycode)
判断某个键是否处于按下的状态。
七.任务系统
task.New(self,f)
为目标添加一个新的任务。目标self可以是任意的Lua table。f是任务流程函数。
注意:task系统会占用目标table的’task’域,注意不要冲突。
task.Do(self)
使目标的所有任务执行一帧。
task.Clear(self)
清除目标的所有任务。
下列函数只可在任务流程函数中被调用:
task.Wait([t=1])
等待t帧。
task.Until(t)
只能应用于关卡和单位。等待直到目标的timer等于t。
task.MoveTo(x,y,t[,mode=0])
只能应用于单位。使目标在t帧内从当前位置移动到坐标(x,y)。mode表示移动的模式,取值的意义如下:
0 匀速(默认)
1 加速(开始移动时瞬时速度为0)
2 减速(结束移动时瞬时速度为0)
3 先加速再减速(开始和结束移动时瞬时速度都为0)
task.GetSelf()
返回当前任务的所有者,即调用task.New(self,f)时传入的self。
八. 玩家数据
LuaSTG支持将玩家数据(比如通关情况、最高分等)存储至硬盘,不同的mod和玩家(以setting.lua中的username区分)之间的数据不共享,存储的文件为score文件夹下mod名文件夹下的username.dat。
玩家数据的读写可通过读写scoredata这个Lua表来实现。scoredata的所有key的类型必须是string或者number,所有value的类型必须是除了function、userdata、thread之外的Lua类型,而且其子表也要满足这些条件,否则在设置的时候将会报错。
mod加载时会从硬盘读取这个表,如果不存在,将会读入一个空表,并且在硬盘上创建这个文件。每次改变scoredata表的时候,LuaSTG都会自动将其存储至硬盘。
九. 随机数
Rand()
创建并返回一个随机数生成器,种子的初始值为0。
随机数生成器的成员函数
:Seed(seed)
设置随机数生成器的当前种子。
:Int(a,b)
随机返回介于a与b之间(包括a和b)的整数。
:Float(a,b)
随机返回介于a与b之间(包括a和b)的浮点数。
:Sign()
等概率的随机返回-1或+1。
在LuaSTG中,已定义好一个随机数生成器ran,可以直接通过调用ran:Int(a,b)、ran:Float(a,b)、ran:Sign()得到随机数。
十. 其他
Print(…)
同Lua的print函数,但是会将内容同时输出到命令行和log.txt。
发表回复