官方网址:https://docs.coronalabs.com/guide/programming/02/index.html
Corona 知识:每建立一个空白corona项目,除main.lua以外,都会包含build.settings和config.lua。
1、build.settings:该文件为真实设备(手机、平板)提供了有关应用程序所需的详细信息。包括应用支持的方向、图标文件的名称、要包含的插件、设备所需的特殊信息等。
例如:此游戏需锁定屏幕方向为竖向,即使用户旋转屏幕,游戏仍然为竖向。
用文本编辑器打开build.settings文件。(我用VS打不开,改用记事本打开的)
找到其中这一段代码:
orientation =
{
-- Supported values for orientation:
-- portrait, portraitUpsideDown, landscapeLeft, landscapeRight
default =
"portrait"
,
supported = {
"portrait"
, },
},
其中:default="portrait" 表示用户第一次加载游戏时默认以竖屏开始。
supported={"portrait",}, 表示游戏唯一支持的方向是竖向,即使用户转屏幕也不会改变。
【花括号表示lua语言中的table,可以包含多个元素,比如至多4个方向,但由于此游戏只需要竖向,所以花括号里一个足够。】
2、config.lua:包含所有corona的应用程序的配置设置。这里可以指定应用程序运行的分辨率,内容比例模式,如何处理高分辨率的设备等。
content =
{
width = 768,
height = 1024,
scale =
"letterbox"
,
其中,scale有三种方案:letterbox【不拉伸,留黑条】、zoomEven【不拉伸,裁剪占满屏幕】、zoomStretch【拉伸占满屏幕】。
此游戏适合zoomEven。
游戏设计:
游戏标题 | Star Explorer - 太空射击游戏。 |
描述 | 在小行星场中操纵你的星舰,随着你的进步摧毁小行星。 |
控制 | 点击船上开火; 拖动船左右移动。 |
声音 | 当船与小行星碰撞时拍摄声音和爆炸声。 |
【添加物理】
local physics=require("physics")
physics.start( )
physics.setGravity(0,0)【设置重力值,默认为地球引力,这里水平x、垂直y都设为0】
math.randomseed(os.time( ) )【随机种子】
【图像表格】
local sheetOptions=
{
frame=
{
{x=0,y=0,width=102,height=85},--第1帧
{x=0,y=85,width=90,height=83},--第2帧
{x=0,y=168,width=100,height=97},--第3帧
{x=0,y=265,width=98,height=79},--第4帧
{x=98,y=265,width=14,height=40},--第5帧
},
}【1,2,3,4,5分别对应5张图,均从一张图上切割而来】
【初始化】
local objectSheet =graphics.newImageSheet("gameObjects.png",sheetOptions)
local lives=3
local score=0
local dead=false
local asteroidsTable={ }【行星表】
local ship
local gameLoopTimer
local livesText
local scoreText
【显示】
local backGroup=dispaly.newGroup( )
local mainGroup=display.newGroup( )
local uiGroup=display.newGroup( )
local background=display.newImageRect(backGroup,"backgroup.png",800,1400)【backGroup表示将加载的图片插入该组】
background.x=display.contentCenterX
background.y=display.contentCenterY
ship=display.newImageRect(mainGroup,objectSheet,4,98,79)【ship为objectSheet图表中的第4张】
ship.x=display.contentCenterX
ship.y=display.contentHeight-100
physics.addBody(ship, {radius=30, isSensor=true} )【isSensor=true表示添加传感器,检测碰撞但不反弹】
ship.myName="ship"
【生命和分数】
livesText=newText( uiGroup, "lives:"..lives, 200, 80, native.systemFont, 36)【这里的..用来串联两个字符串】
scoreText=newText( uiGroup, "score:"...score, 400, 80, native.systemFont, 36)
display.setStatusBar(display.HiddenStatusBar) 【隐藏状态栏】
local function updateText( )【更新文本函数】
livesTxet.text="lives:"..lives
scoreText.text="score:"..score
end
【行星函数】
local function createAsteriod()
local newAsteriod=display.newImageRect(mainGroup,objectSheet,1,102,85)
table.insert(asteroidTable,newAsteriod)【新建的行星图片加入行星表中】
physics.addBody(newAsteriod,"dynamic",{radius=40,bounce=0.8})
newAsteriod.myName="asteriod"
local whereFrom=math.random(3)
if(whereFrom==1) then
newAsteriod.x=-60
newAsteriod.y=math.random(500)
newAsteriod:setLinearVelocity(math.random(40,120),math.random(20,60))
elaeif(whereFrom==2) then
newAsteriod.x=math.random(display.contentWidth)
newAsteriod.y=-60
newAsteriod:setLinearVelocity(math.random(-40,40),math.random(40,120))
elseif(whereFrom==3) then
newAsteriod.x=display.contentWidth+60
newAsteriod.y=math.random(500)
newAsteriod:setLinearVelocity(math.random(-120,-40),math.random(20,60))
end
newAsteriod:applyTorque(math.random(-6,6))【施加扭转力】
end
【激光函数】
local function fireLaser()
local newLaser=display.newImageRect(mainGroup,objectSheet,5,14,40)
physics.addBody(newLaser,"dynamic", {isSenser=true})
newLaser.isBullet=true【使激光接受连续碰撞检测而不是世界时间步骤的周期性碰撞检测,确保不会“穿过”任何行星】
newLaser.myName="laser"
newLaser.x=ship.x
newLaser.y=ship.y
newLaser:toBack()【将对象发送到自己显示组的最后面】
transition.to(newLaser,{y=-60,time=500,onComplete=function() display.remove(newLaser) end})【过渡,第二个参数包含一个表,使对象到达y=-60的目标,时间为500毫秒,完成后调用onComplete函数(这里是个匿名函数),进行清理。】
end
ship:addEventListener("tap",fireLaser)
【移动船】
local function dragShip(event)
local ship=event.target
local phase=event.phase
if("begin"==phase) then
display.currentStage:setFocus(ship)【把触摸焦点设置在ship上】
ship.touchOffsetX=event.x-ship.x【存储最初的偏移量】
elseif("move"==phase) then
ship.x=event.x-ship.touchOffsetX【移动ship】
elseif("ended"==phase or "cancelled"==phase) then
display.currentStage:setFocus(nil)
end
return true【告诉corona触摸事件应该“停止”在这个对象上,而不是传播到底层对象】
end
ship:addEventListener("touch",dragShip)
【游戏循环】---创造新的小行星并清理“死”小行星
local function gameLoop()
createAsteriod()
for i=#asteriodsTable,1,-1 do【表名前面加#可以得到表中元素的数量】
local thisAsteriod=asteriodsTable[i]
if(thisasteriod.x<-100 or thisasteriod.x>display.contentWidth+100 or
thisasteriod.y<-100 or thisasteriod.y>display.contentHeight+100)
then
display.remove(thisAsteriod)【从视觉上删除屏幕上小行星,但不释放内存,因为表中存储了对小行星的附加引用,所以需要下一步】
table.remove(asteriodsTable,i)【删除表中元素】
end
end
end
gameLoopTimer=timer.performWithDelay(500,gameLoop,0)【定时器,延迟500毫秒执行一次,最后是迭代次数,注意0或-1会导致计时器无限重复】
【碰撞处理】---恢复船只
local function restoreShip()
ship.isBodyActive=false【停止ship的物理模拟,停止交互】
ship.x=display.contentCenterX
ship.y=display.contentHeight-100
transition.to(ship, {alpha=1,time=4000,onComplete=function() ship.isBody=true died=false end})
end
【碰撞处理】---碰撞功能
local function onCollision(event)
if(event.phase=="began") then
local obj1=event.object1
local obj2=event.object2
if( (obj1.myName=="laser" and obj2.myName=="asteriod") or 【激光和小行星碰撞】
(obj2.myName=="laser" and obj1.myName=="asteriod"))
then
display.remove(obj1)
display.remove(obj2)
for i=#asteriodsTable,1,-1 do
if(asteriodsTable[i]==obj1 or asteriodsTable[i]==obj2) then
table.remove(asteriodsTable,i)
break
end
end
score=score+100
scoreText.text="score:"..score
elseif( (obj1.myName=="ship" and obj2.myName=="asteriod") or 【船和小行星碰撞】
(obj2.myName=="ship" and obj1.myName=="asteriod"))
then
if(died=false) then
died=true
lives=lives-1
livesText.text="lives:"..lives
if(lives==0) then
diaplay.remove(ship)
else
ship.alpha=0
timer.performWithDelay(1000,restoreShip)
end
end
end
end
end
Runtime:addEventListener("collision",onCollision)
//知识总结
命令/物业 | 描述 |
---|---|
physics.setGravity() | 以m /s²为单位设置全球重力矢量的x和y分量。 |
math.randomseed() | 设置伪随机数生成器的“种子” 。 |
graphics.newImageSheet() | 创建一个ImageSheet对象,用于从单个较大的图像文件中加载多个图像/帧。 |
display.newGroup() | 创建用于组织/分层显示对象的显示组。 |
display.contentHeight | 内容区域高度的快捷方式。 |
display.setStatusBar() | 隐藏或更改大多数设备上状态栏的外观 |
命令/物业 | 描述 |
---|---|
table.insert() | 将给定值插入表中。 |
table.remove() | 从指定索引处的表中删除项。 |
的Math.random() | 从具有均匀分布的序列返回伪随机数。 |
对象:setLinearVelocity() | 设置主体线速度的x和y分量。 |
对象:applyTorque() | 对身体施加旋转力。 |
object.isBullet | 是否应将身体视为“子弹”的布尔值。 |
对象:toBack后() | 将目标对象移动到其父组的可视后退。 |
transition.to() | 使用可选的缓动算法为显示对象设置动画(过渡)。 |
display.remove() | 如果没有,则删除对象或组nil 。 |
对象:的setFocus() | 将特定显示对象设置为所有未来命中事件("touch" 和"tap" )的目标。 |
timer.performWithDelay() | 延迟后调用指定的函数。 |
object.isBodyActive | 设置或获取物理实体的当前活动状态。 |
与点击事件不同的触摸事件根据用户触摸的状态有四个不同的阶段:
"began"
- 表示已在对象上开始触摸(屏幕上的初始触摸)。"moved"
- 表示触摸位置已在对象上移动。"ended"
- 表示触摸已在对象上结束(触摸从屏幕上抬起)。"cancelled"
- 表示系统取消了对触摸的跟踪(不要混淆 "ended"
)。