如何使用Corona SDK构建公路道奇

您将要创造的

介绍

在本教程中,您将学习如何创建一个简单但容易上瘾的游戏Highway Dodge 。 Highway Dodge易于拾起和玩耍,但在App Store中提供了其他流行游戏的令人上瘾的质量。

高速公路道奇通过将玩家放在高速公路上的赛车中而开始。 在游戏中,玩家必须通过点击三个可用车道之一来躲避高速公路上即将来临的交通。 对于每辆躲避的汽车,玩家都会得到1分,当迎面驶来的汽车撞上赛车时,游戏结束。 随着时间的流逝,迎面而来的赛车越来越快地出现,从而给玩家带来了真正的挑战。

要求

该游戏是使用Lua和Corona SDK构建的。 至少,您需要具有安装了Corona Labs和Corona SDK的帐户。 您可以在Corona Labs网站上免费获取Corona SDK。 在本教程中,我使用了Corona SDK的内部版本2015.2731

1.

让我们跳进去,通过创建一个空白模板来启动Highway Dodge。 打开Corona Simulator,然后从“ 文件”菜单中选择“ 新建项目 ”。 打开“ 创建新项目”窗口后,输入Highway Dodge作为项目名称,选择一个空白模板,然后将宽度设置为400并将高度设置为600 。 保持默认方向设置为Upright

建立新专案

设置项目后, 下载用于“公路道奇” 的图像 。 在新项目中创建一个新文件夹,将其命名为images,然后将图像添加到该文件夹​​中。 您的项目现在应如下所示:

快速浏览项目

2.项目设置

完成项目设置后,让我们快速看一下两个重要文件, build.settingsconfig.lua

构建设置

该文件处理游戏的构建时间属性。 它存储有关应用程序方向,图标信息,iOS设置和Android设置的信息。 默认设置适合我们的游戏。

config.lua

此配置文件控制游戏的运行时属性。 这包括widthheightscalefps (每秒帧数)和imageSuffix 。 我们需要看的属性是imageSuffiximageSuffix属性用于动态图像选择。 简而言之,它告诉应用程序在高分辨率设备上使用高分辨率图像。

我在images文件夹中提供了高分辨率图像,因此我们需要相应地更新config.lua 。 您项目的config.lua文件应类似于以下文件。 我省略了已被注释掉的推送通知部分。

application = {
    content = {
    	width = 400,
		height = 600, 
		scale = "letterBox",
		fps = 30,
		
		imageSuffix = {
		    ["@2x"] = 2,
		},
	},
}

3.发射点

设置项目和动态图像选择后,让我们继续main.lua 。 该文件是使用Corona SDK构建的每个应用程序的启动点。 在我们的游戏中,它将包含三行代码。

第1步

第一行隐藏iOS设备上的状态栏。 打开main.lua并在注释后添加以下行-- Your code here

display.setStatusBar( display.HiddenStatusBar )

第2步

接下来,我们通过要求将库加入游戏中来开始使用作曲家。 我们通过添加以下行来做到这一点:

local composer = require( "composer" )

第三步

接下来,我们使用作曲家移至菜单场景。 我们通过调用函数composer.gotoScene()并传递值"scene_menu"作为参数来移动场景。 值"scene_menu"是场景的名称,也是我们在下一部分中创建的文件的名称。

composer.gotoScene("scene_menu")

关于作曲家的一句话

Composer是Corona的官方场景管理库。 Composer使开发人员可以轻松创建场景并在场景之间进行转换。 在两行中,我能够从主场景过渡到菜单场景。 如果您想了解有关Composer的更多信息,请访问Corona Labs Docs网站上的 Corona的Composer库指南》

4.菜单

我们游戏的菜单场景将仅包含几个元素。 该场景将包含背景图形,标题和开始按钮。 我们将使用Corona的内置小部件库来创建开始按钮。 小部件库使我们能够快速轻松地创建常见的用户界面元素。 在我们的游戏中,我们将仅将其用于按钮创建。

第1步

在Highway Dodge的项目文件夹中,创建一个新文件scene_menu.lua ,然后在您选择的文本编辑器中将其打开。 我们将使用Corona Labs Docs网站上可用的场景模板,而不是从头开始。 有了他们的模板,我们将能够更快地移动。 转到Corona Labs Docs,然后将场景模板复制/粘贴到scene_menu.lua

第2步

通过在composer库下方添加以下行,将widget库添加到我们的游戏中。

local widget = require( "widget" )

第三步

我们使用您先前下载的图形添加背景。 背景应该位于屏幕的中央。 在scene:create()函数中,并在声明screenGroup变量之后,添加以下代码:

local background = display.newImageRect(sceneGroup, "images/background.png", 475, 713)
background.x = display.contentCenterX
background.y = display.contentCenterY

第4步

接下来,我们需要添加代表高速公路的三个车道。 为此,我们使用一个表来保存通道并创建一个运行3次的for循环。 将此代码段放在背景图形之后:

local lanes = {}
for i=1,3 do        
    lanes[i] = display.newImageRect(sceneGroup, "images/lane.png", 79, 713)
    lanes[i].x = (display.contentCenterX - 79*2) + (i*80)
    lanes[i].y = display.contentCenterY          
end

为了确保通道始终居中,我使用一些数学方法将通道放置在x轴上。 无论游戏运行在什么设备上,这都能确保车道保持居中。

第5步

我们还将图像对象放置在屏幕顶部附近,从而为公路道奇添加徽标。

local logo = display.newImageRect(sceneGroup, "images/logo.png", 300, 150)
logo.x = display.contentCenterX
logo.y = 75

第6步

在添加按钮小部件之前,我们需要创建一个函数,该函数在触摸按钮时做出响应。 我们将函数命名为handleButtonEvent()然后使用composer.gotoScene()将玩家移至游戏场景。 我们只会在玩家将手指从按钮上移开时或在活动ended时做出响应。

local function handleButtonEvent( event )
    if ( "ended" == event.phase ) then
        composer.gotoScene("scene_game", "slideLeft")
    end
end

步骤7

添加功能后,我们可以添加按钮。 我们通过使用widget.newButton并将一些值传递给它来创建按钮。 我们指定按钮的宽度和高度,按钮的图像文件,要显示的文本,字体类型,字体大小和字体颜色。

我们还告诉Corona当按下按钮并将其放置在屏幕中间时要调用什么函数。 本教程的源文件包含注释,这些注释解释了用于设置按钮的每个值。

local btn_startPlaying = widget.newButton {
    width = 220,
    height = 100,
    defaultFile = "images/btn-blank.png",
    overFile = "images/btn-blank-over.png",       
    label = "Start Playing",
    font = system.defaultFontBold,
    fontSize = 32,
    labelColor = { default={ 0, 0, 0 }, over={ 0, 0, 0, 0.5 } },
    onEvent = handleButtonEvent
}
btn_startPlaying.x = display.contentCenterX
btn_startPlaying.y = display.contentCenterY
sceneGroup:insert(btn_startPlaying)

步骤8

要包装菜单场景,我们需要在游戏场景退出时将其删除。 当电晕在场景之间移动时,并不总是删除前一个场景。 如果没有这些限制,则游戏在播放一次后将始终处于游戏场景中。

要删除前一个场景,我们获取场景名称,并调用composer.removeScene()将其删除composer.removeScene()如果存在)。 将以下代码添加到scene:show()函数。

local prevScene = composer.getSceneName( "previous" )
if(prevScene) then 
    composer.removeScene(prevScene)
end

5.

现在,我们可以开始游戏场景了。 我们将使用与创建菜单场景相同的工作流程。 创建一个新文件scene_game.lua ,然后复制/粘贴Corona Labs Docs上可用的场景模板。 编写好代码后,在您喜欢的文本编辑器中打开scene_game.lua

第1步

为了使我们对游戏场景的编码更容易,我们将使用小部件库和物理库。 后者用于碰撞检测。 将以下代码添加到scene_game.lua

local widget = require( "widget" )
local physics = require("physics")
physics.start()
physics.setGravity(0,0)

在第一行和第二行,我们分别需要窗口小部件库和物理库。 然后,我们开始物理学并禁用重力。 我们的公路游戏不需要重力,相反,我们将使用transition.to()移动汽车。

第2步

scene:create()函数中,我们声明了将在游戏中使用的许多变量。 这些变量将负责玩家的赛车,车道,敌方赛车和玩家得分。 为了使内容更易于阅读,我添加了一些评论。

-- "scene:create()"
function scene:create( event )
    local lanes = {} -- create a table called lanes
    local playerCar -- a variable for the player car
    local laneID = 1 -- a variable for the land id
    local enemyCars = {} -- a table to hold the enemy cars
    local enemyCounter = 1 -- start the enemy counter at 1 to keep track of the enemy cars
    local sendEnemyFrequency = 2500 -- defines how often to send enemy cars in milliseconds
    local tmrToSendCars -- a variable to hold a reference to the timer of sending cars   
    local playerScore = 0 -- start the player score at 0
    local playerScoreText -- an object to hold the score text object
end

第三步

在变量声明下方,我们设置了游戏功能。 我们将在以后的步骤中实现每个功能。 在scene:create()函数的变量声明之后添加以下代码。

local function incrementScore()
end

local function moveCar(event)
end

local function sendEnemyCar()
end

local function onPlayAgainTouch()
end

local function onGlobalCollision(event)
end

第4步

在功能之后,我们添加背景和通道。 对于通道,我们在每个通道上附加一个事件侦听器,以使它们响应触摸事件。 触摸后,侦听器将调用moveCar()函数。

local background = display.newImageRect(sceneGroup, "images/background.png", 475, 713)
    background.x = display.contentCenterX
    background.y = display.contentCenterY

for i=1,3 do
    lanes[i] = display.newImageRect(sceneGroup, "images/lane.png", 79, 713)
        lanes[i].x = (display.contentCenterX - 79*2) + (i*80)
        lanes[i].y = display.contentCenterY
        lanes[i].id = i
        lanes[i]:addEventListener("touch", moveCar)
end

第5步

设置了背景和车道后,就该创建一个文本对象来保存玩家得分并创建玩家赛车了。 得分将在屏幕顶部,而赛车将位于最左侧的车道上。 此外,我们将使播放器汽车成为动态物理对象。

playerScoreText = display.newText(sceneGroup, "Score: "..playerScore, 0, 0, native.systemFont, 36)
    playerScoreText.x = display.contentCenterX
    playerScoreText.y = 25

playerCar = display.newImageRect(sceneGroup, "images/playerCar.png", 50, 100)
    playerCar.anchorY = 1
    playerCar.x = lanes[1].x
    playerCar.y = display.contentHeight
    physics.addBody(playerCar)
    playerCar.bodyType = "dynamic"

第6步

接下来,我们根据sendEnemyFrequency变量的值设置一个计时器,以派出一辆汽车,并为全局冲突创建一个运行时事件侦听器。

tmrToSendCars = timer.performWithDelay(sendEnemyFrequency, sendEnemyCar, 0)
Runtime:addEventListener( "collision", onGlobalCollision)

6.增加游戏功能

我们终于可以在游戏中添加功能了。 本节将为我们在上一节中声明的每个函数添加其他代码。 我们将开始使用incrementScore()和结束与onGlobalCollision()

incrementScore()

当敌方汽车经过玩家并完成过渡时,将调用此功能。 呼叫时,玩家得分将增加1 。 将以下实现添加到incrementScore()函数。

-- This function will increment the player score by 1. This function is called when the transition for the enemy car is complete and is off screen.
local function incrementScore()
    playerScore = playerScore + 1
    playerScoreText.text = "Score: "..playerScore
end

moveCar()

触摸车道时将调用moveCar()函数。 在活动ended阶段,我们获取车道标识符并将汽车移至正确的车道。 最后,我们返回true表示成功触摸事件。 将以下实现添加到moveCar()函数。

-- moveCar will respond to the touch event on the lanes
local function moveCar(event)
    if(event.phase == "ended") then 
		laneID = event.target.id -- grab the lane id which will be 1, 2, or 3
		transition.to(playerCar, {x=lanes[laneID].x,time=50}) -- move the player car to the appropriate lane
        return true -- to indicate a successful touch event, return true
	end
end

sendEnemyCar()

sendEnemyCar()函数创建敌方汽车,将汽车分配到车道,将物理物体附加到汽车上,并使用transition.to()将汽车发送到屏幕底部。 首先,让我们创建敌人的汽车对象。

enemyCars[enemyCounter] = display.newImageRect(sceneGroup, "images/enemyCar"..math.random(1,3)..".png", 50, 100)

接下来,我们设置敌方汽车的x和y位置。 我们还创建一条if-then语句,以将敌方汽车分配给玩家汽车在50%的时间所在的同一车道。 这将迫使玩家更频繁地移动,并使游戏更加有趣。

enemyCars[enemyCounter].x = lanes[math.random(1,#lanes)].x -- place the car on a random lane
  if(math.random(1,2) == 1) then enemyCars[enemyCounter].x = lanes[laneID].x; end -- 50% of the time, place the enemy car on the player car lane. 
enemyCars[enemyCounter].y = -125 -- place the enemy off screen at the top

我们还需要旋转敌车,使其面向下,并向敌车添加运动学的物理体类型。

enemyCars[enemyCounter]:scale(1,-1) -- rotate the cars so they are facing down
physics.addBody(enemyCars[enemyCounter]) -- add a physics body to enemy cars
enemyCars[enemyCounter].bodyType = "kinematic" -- make the bodies kinematic

设置好敌方汽车后,我们使用transition.to()函数将敌方汽车沿一条车道驶下。 过渡完成后,游戏将调用一个函数删除该对象。 我还将变量enemyCounter增加1,以跟踪游戏中敌方汽车的数量。

transition.to(enemyCars[enemyCounter], {y=display.contentHeight+enemyCars[enemyCounter].height+20, time=math.random(2250,3000), onComplete=function(self) display.remove(self); incrementScore(); end}) -- a transition that moves the enemy car towards the bottom of the screen. On completion, the enemy car object is removed from the game.

enemyCounter = enemyCounter + 1 -- increase enemy counter by one for tracking

最后,我们希望游戏随着时间的推移变得更快。 对于发送的所有其他汽车,游戏将重新创建计时器并将其设置为快200毫秒。

if(enemyCounter%2 == 0) then
    sendEnemyFrequency = sendEnemyFrequency - 200
    if(sendEnemyFrequency < 800) then sendEnemyFrequency = 800; end
    timer.cancel(tmrToSendCars)
    tmrToSendCars = timer.performWithDelay(sendEnemyFrequency, sendEnemyCar, 0)
end

onPlayAgainTouch()

最短的函数onPlayAgainTouch()使播放器返回主菜单。 这就是onPlayAgainTouch()函数的实现。

-- Allow the player to return to the menu
local function onPlayAgainTouch()
    composer.gotoScene("scene_menu", "fade") -- move player to menu
end

onGlobalCollision()

onGlobalCollision()函数用于检测屏幕上任何两个物理对象之间的碰撞。 在我们的游戏中,我们只有两种类型的物理对象:

  • 玩家车
  • 敌车

当这两个对象碰撞时,游戏将停止所有计时器,过渡和事件侦听器。 此外,游戏会在场景上方显示游戏,允许玩家再次玩。

第1步

首先,我们创建一个if-then语句来监听began阶段。

if(event.phase == "began") then

end

第2步

if-then语句中,我们停止游戏。 我们暂停所有转换,取消计时器,暂停物理操作(即使不需要,这也是一个很好的清理方法),并从所有三个通道中删除事件侦听器。 在if-then语句内添加以下代码:

transition.pause()
timer.cancel(tmrToSendCars)
physics.pause()

for i=1,3 do
    lanes[i]:removeEventListener("touch", moveCar)
end

第三步

游戏机制停止后,我们添加一个不透明的矩形和一个文本对象,上面写着“游戏结束!”。 。 这样可以很好地显示游戏已结束。

local gameOverBackground = display.newRect(sceneGroup, 0, 0, display.actualContentWidth, display.actualContentHeight)
    gameOverBackground.x = display.contentCenterX
    gameOverBackground.y = display.contentCenterY
    gameOverBackground:setFillColor(0)
    gameOverBackground.alpha = 0.5

local gameOverText = display.newText( sceneGroup, "Game Over!", 100, 200, native.systemFontBold, 36 )
    gameOverText.x = display.contentCenterX
    gameOverText.y = 150
    gameOverText:setFillColor( 1, 1, 1 )

第4步

为了包装全局碰撞功能,我们添加了“再次播放”按钮,该按钮将播放器送回菜单。

local playAgain = widget.newButton {
    width = 220,
    height = 100,
    defaultFile = "images/btn-blank.png",
    overFile = "images/btn-blank.png",       
    label = "Menu",
    font = system.defaultFontBold,
    fontSize = 32,
    labelColor = { default={ 0, 0, 0 }, over={ 0, 0, 0, 0.5 } },
    onEvent = onPlayAgainTouch
}
playAgain.x = display.contentCenterX
playAgain.y = gameOverText.y + 100
sceneGroup:insert(playAgain)

试驾

运行该应用程序以查看是否一切正常。 您应该可以玩游戏,应该从屏幕顶部弹出敌方汽车,并且成功躲避的每辆敌方汽车的分数都应该增加。

结论

感谢您阅读我的有关使用Corona SDK创建Highway Dodge的教程。 您可以从GitHub下载该游戏的源文件。 花一点时间思考如何进一步改善游戏。 如果您正在寻找建议,我建议您增加一条车道,增加更多的敌人类型,甚至增加一些酷炫的力量。





翻译自: https://code.tutsplus.com/tutorials/how-to-build-highway-dodge-with-the-corona-sdk--cms-22829

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值