Cara Membangun Highway Dodge Dengan Corona SDK
Indonesian (Bahasa Indonesia) translation by Dzu Al-Faqqar (you can also view the original English article)
Pengantar
Dalam tutorial ini, Anda belajar cara membuat, Highway Dodge, gim yang sederhana namun membuat ketagihan. Highway Dodge mudah diambil dan dimainkan, tetapi ini memberikan kualitas adiktif dari game populer lainnya di App Store.
Highway Dodge dimulai dengan menempatkan pemain di mobil balap di jalan raya. Selama permainan, pemain harus menghindari lalu lintas yang mendekat di jalan raya dengan mengetuk salah satu dari tiga jalur yang tersedia. Untuk setiap mobil yang mengelak, pemain menerima satu poin dan permainan berakhir untuk pemain ketika mobil yang datang menabrak mobil balap. Seiring waktu, mobil yang melaju keluar lebih cepat dan lebih cepat untuk memberikan tantangan nyata kepada pemain.
Persyaratan
Game ini dibangun menggunakan Lua dan Corona SDK. Minimal, Anda harus memiliki akun dengan Corona Labs dan Corona SDK diinstal. Anda dapat mengambil Corona SDK secara gratis di situs web Corona Labs. Untuk tutorial ini, saya menggunakan build 2015.2731 dari Corona SDK.
1. Mengatur Highway Dodge
Mari lompat masuk dan mulai Highway Dodge dengan membuat templat kosong. Buka Simulator Corona dan pilih Proyek Baru dari menu File. Setelah jendela Buat Proyek Baru terbuka, masukkan Highway Dodge sebagai nama proyek, pilih templat kosong, dan atur lebar ke 400 dan tinggi ke 600. Biarkan orientasi default diatur ke Tegak.



Setelah menyiapkan proyek Anda, unduh gambar untuk Highway Dodge. Buat folder baru di proyek baru Anda, beri nama gambar, dan tambahkan gambar ke folder ini. Proyek Anda sekarang akan terlihat seperti ini:



2. Pengaturan Proyek
Dengan proyek ini diatur, mari kita lihat dua file penting, build.settings dan config.lua.
Build.Settings
File ini menangani sifat waktu membangun permainan. Ini menyimpan informasi pada orientasi Anda app, ikon informasi, pengaturan iOS dan Android pengaturan. Pengaturan default memadai untuk permainan kami.
config.Lua
File konfigurasi ini mengontrol sifat runtime permainan. Ini termasuk lebar
, tinggi
, skala
, fps
(frame per detik), dan imageSuffix
. Kita perlu melihat properti ini imageSuffix
. Properti imageSuffix
digunakan untuk pilihan gambar dinamis. Singkatnya, ia memberitahu app untuk menggunakan gambar beresolusi tinggi pada perangkat resolusi yang lebih tinggi.
Saya telah memberikan gambar beresolusi tinggi di folder gambar sehingga kita perlu memperbarui config.lua sesuai. File config.lua proyek Anda akan terlihat seperti di bawah ini. Saya telah menghilangkan bagian pemberitahuan push, yang dikomentari.
1 |
application = { |
2 |
content = { |
3 |
width = 400, |
4 |
height = 600, |
5 |
scale = "letterBox", |
6 |
fps = 30, |
7 |
|
8 |
imageSuffix = { |
9 |
["@2x"] = 2, |
10 |
},
|
11 |
},
|
12 |
}
|
3. peluncuran Point
Dengan proyek dan mengatur pilihan gambar dinamis, mari kita beralih ke main.lua. File ini adalah titik peluncuran setiap app dibangun dengan Corona SDK. Dalam permainan kami, itu akan terus tiga baris kode.
Langkah 1
Baris pertama menyembunyikan bilah status pada perangkat iOS. Buka main.lua dan tambahkan baris berikut setelah komentar --kode Anda di sini
.
1 |
display.setStatusBar( display.HiddenStatusBar ) |
Langkah 2
Berikutnya, kita mulai menggunakan komposer dengan mengharuskan perpustakaan ke dalam permainan kami. Kita melakukan ini dengan menambahkan baris berikut:
1 |
local composer = require( "composer" ) |
Langkah 3
Selanjutnya, kami menggunakan komposer untuk pindah ke adegan menu. Kita bergerak adegan dengan memanggil fungsi composer.gotoScene()
, melewati nilai "scene_menu"
sebagai parameter. Nilai "scene_menu"
adalah nama dari adegan dan nama file yang kita buat di bagian berikutnya.
1 |
composer.gotoScene("scene_menu") |
Sepatah kata tentang komposer
Komposer adalah adegan resmi Manajemen Perpustakaan Corona. Komposer memungkinkan pengembang untuk dengan mudah membuat adegan dan transisi antara adegan. Dalam dua baris, saya bisa beralih dari adegan utama ke adegan menu. Jika Anda ingin membaca lebih lanjut tentang Komposer, kunjungi Panduan Perpustakaan Penggubah Corona yang tersedia di situs web Corona Labs Docs.
4. menu
Adegan menu permainan kita akan terdiri dari hanya beberapa elemen. Adegan akan terus latar belakang grafis, judul dan tombol start. Kita akan menggunakan Corona's built-in widget perpustakaan untuk membuat tombol start. Widget Perpustakaan memungkinkan kita untuk dengan cepat dan mudah membuat elemen antarmuka pengguna umum. Dalam permainan kami, kami akan menggunakannya untuk penciptaan tombol hanya.
Langkah 1
Dalam folder proyek Highway Dodge, membuat baru file, scene_menu.lua, dan membukanya dalam editor teks pilihan Anda. Daripada memulai dari awal, kita akan menggunakan template adegan yang tersedia di situs Corona Labs Docs. Dengan template mereka, kita akan mampu bergerak jauh lebih cepat. Kepala ke Corona Labs Docs dan copy/paste adegan template untuk scene_menu.lua.
Langkah 2
Menambahkan widget perpustakaan permainan kami dengan menambahkan baris berikut, tepat di bawah Perpustakaan komposer.
1 |
local widget = require( "widget" ) |
Langkah 3
Kami menambahkan latar belakang kami menggunakan grafis Anda download sebelumnya. Latar belakang harus diposisikan di tengah layar. Dalam fungsi adegan: create()
dan sesudah screenGroup
variabel dinyatakan, tambahkan kode berikut:
1 |
local background = display.newImageRect(sceneGroup, "images/background.png", 475, 713) |
2 |
background.x = display.contentCenterX |
3 |
background.y = display.contentCenterY |
Langkah 4
Selanjutnya, kita perlu menambahkan tiga jalur yang mewakili jalan. Kita melakukan ini dengan menggunakan tabel untuk menahan jalur dan menciptakan for
loop yang berjalan tiga kali. Tempatkan potongan ini setelah latar belakang grafis:
1 |
local lanes = {} |
2 |
for i=1,3 do |
3 |
lanes[i] = display.newImageRect(sceneGroup, "images/lane.png", 79, 713) |
4 |
lanes[i].x = (display.contentCenterX - 79*2) + (i*80) |
5 |
lanes[i].y = display.contentCenterY |
6 |
end
|
Untuk memastikan jalur selalu terpusat, saya telah menempatkan jalur pada sumbu x menggunakan sedikit matematika. Ini memastikan jalur tetap terpusat, terlepas dari perangkat mana permainan berjalan.
Langkah 5
Kita juga menambahkan logo kami untuk Highway Dodge dengan menempatkan objek image di dekat bagian atas layar.
1 |
local logo = display.newImageRect(sceneGroup, "images/logo.png", 300, 150) |
2 |
logo.x = display.contentCenterX |
3 |
logo.y = 75 |
Langkah 6
Sebelum kita dapat menambahkan widget tombol kami, kita perlu membuat sebuah fungsi yang merespon bila tombol disentuh. Kami akan nama fungsi handleButtonEvent()
dan pemain bergerak ke adegan permainan yang menggunakan composer.gotoScene()
. Kami hanya akan merespons ketika pemain telah mengangkat jari mereka dari tombol atau pada fase akhir
acara.
1 |
local function handleButtonEvent( event ) |
2 |
if ( "ended" == event.phase ) then |
3 |
composer.gotoScene("scene_game", "slideLeft") |
4 |
end
|
5 |
end
|
Langkah 7
Dengan fungsi ditambahkan, kita dapat menambahkan tombol. Kami membuat tombol dengan menggunakan widget.newButton
dan melewati beberapa nilai-nilai itu. Kita menentukan lebar dan tinggi dari tombol, file gambar untuk tombol, teks untuk ditampilkan, jenis font, ukuran font dan warna font.
Kami juga memberitahu Corona apa fungsi untuk panggilan ketika tombol ditekan dan posisi di tengah layar. Source file tutorial ini mencakup komentar yang menjelaskan nilai-nilai yang digunakan untuk mengatur tombol masing-masing.
1 |
local btn_startPlaying = widget.newButton { |
2 |
width = 220, |
3 |
height = 100, |
4 |
defaultFile = "images/btn-blank.png", |
5 |
overFile = "images/btn-blank-over.png", |
6 |
label = "Start Playing", |
7 |
font = system.defaultFontBold, |
8 |
fontSize = 32, |
9 |
labelColor = { default={ 0, 0, 0 }, over={ 0, 0, 0, 0.5 } }, |
10 |
onEvent = handleButtonEvent |
11 |
}
|
12 |
btn_startPlaying.x = display.contentCenterX |
13 |
btn_startPlaying.y = display.contentCenterY |
14 |
sceneGroup:insert(btn_startPlaying) |
Langkah 8
Membungkus adegan menu, kita perlu untuk menghapus adegan permainan ketika keluar. Ketika Corona bergerak antara adegan, itu tidak selalu akan menghapus adegan sebelumnya. Tanpa garis-garis ini, permainan akan selalu dalam permainan selama adegan setelah ia telah dimainkan sekali.
Untuk menghapus adegan sebelumnya, kami mendapatkan nama adegan dan memanggil composer.removeScene()
untuk menghapus jika ada. Tambahkan kode berikut untuk fungsi adegan: show()
.
1 |
local prevScene = composer.getSceneName( "previous" ) |
2 |
if(prevScene) then |
3 |
composer.removeScene(prevScene) |
4 |
end
|
5. Menciptakan Adegan Game
Kita sekarang dapat mulai bekerja pada adegan permainan. Kita akan menggunakan alur kerja sama kami digunakan untuk membuat adegan menu. Buat file baru, scene_game.lua dan copy/paste adegan template tersedia di Corona Labs Docs. Setelah Anda memiliki kode di tempat, buka scene_game.lua di editor teks favorit Anda.
Langkah 1
Untuk membuat coding adegan permainan yang lebih mudah bagi kita, kita akan menggunakan widget Perpustakaan dan Perpustakaan fisika. Yang kedua digunakan untuk deteksi tabrakan. Tambahkan kode berikut untuk scene_game.lua:
1 |
local widget = require( "widget" ) |
2 |
local physics = require("physics") |
3 |
physics.start() |
4 |
physics.setGravity(0,0) |
Pada baris pertama dan kedua, kami memerlukan widget Perpustakaan dan Perpustakaan fisika masing-masing. Kami kemudian mulai fisika dan menonaktifkan gravitasi. Kita tidak perlu gravitasi untuk permainan jalan kami, sebaliknya kita akan menggunakan transition.to()
untuk memindahkan mobil.
Langkah 2
Dalam fungsi scene: create()
, kami mendeklarasikan sejumlah variabel yang akan kami gunakan dalam game. Variabel-variabel ini akan bertanggung jawab untuk mobil pemain, jalur, mobil musuh, dan skor pemain. Untuk mempermudah membaca, saya menambahkan beberapa komentar.
1 |
-- "scene:create()" |
2 |
function scene:create( event ) |
3 |
local lanes = {} -- create a table called lanes |
4 |
local playerCar -- a variable for the player car |
5 |
local laneID = 1 -- a variable for the land id |
6 |
local enemyCars = {} -- a table to hold the enemy cars |
7 |
local enemyCounter = 1 -- start the enemy counter at 1 to keep track of the enemy cars |
8 |
local sendEnemyFrequency = 2500 -- defines how often to send enemy cars in milliseconds |
9 |
local tmrToSendCars -- a variable to hold a reference to the timer of sending cars |
10 |
local playerScore = 0 -- start the player score at 0 |
11 |
local playerScoreText -- an object to hold the score text object |
12 |
end
|
Langkah 3
Di bawah deklarasi variabel, kami mengatur fungsi untuk game. Kami akan mengimplementasikan setiap fungsi pada langkah selanjutnya. Tambahkan kode berikut setelah deklarasi variabel dalam adegan: create()
fungsi.
1 |
local function incrementScore() |
2 |
end
|
3 |
|
4 |
local function moveCar(event) |
5 |
end
|
6 |
|
7 |
local function sendEnemyCar() |
8 |
end
|
9 |
|
10 |
local function onPlayAgainTouch() |
11 |
end
|
12 |
|
13 |
local function onGlobalCollision(event) |
14 |
end
|
Langkah 4
Setelah fungsi, kami menambahkan latar belakang dan jalur. Untuk jalur, kami lampirkan pendengar acara ke setiap jalur untuk membuat mereka merespons acara sentuh. Saat disentuh, pendengar memanggil fungsi moveCar()
.
1 |
local background = display.newImageRect(sceneGroup, "images/background.png", 475, 713) |
2 |
background.x = display.contentCenterX |
3 |
background.y = display.contentCenterY |
4 |
|
5 |
for i=1,3 do |
6 |
lanes[i] = display.newImageRect(sceneGroup, "images/lane.png", 79, 713) |
7 |
lanes[i].x = (display.contentCenterX - 79*2) + (i*80) |
8 |
lanes[i].y = display.contentCenterY |
9 |
lanes[i].id = i |
10 |
lanes[i]:addEventListener("touch", moveCar) |
11 |
end
|
Langkah 5
Dengan latar belakang dan jalur yang diatur, saatnya untuk membuat objek teks untuk menahan skor pemain dan membuat mobil pemain. Skor akan berada di bagian atas layar dan mobil pemain akan diposisikan di jalur paling kiri. Selain itu, kami akan menjadikan mobil pemain sebagai objek fisika yang dinamis.
1 |
playerScoreText = display.newText(sceneGroup, "Score: "..playerScore, 0, 0, native.systemFont, 36) |
2 |
playerScoreText.x = display.contentCenterX |
3 |
playerScoreText.y = 25 |
4 |
|
5 |
playerCar = display.newImageRect(sceneGroup, "images/playerCar.png", 50, 100) |
6 |
playerCar.anchorY = 1 |
7 |
playerCar.x = lanes[1].x |
8 |
playerCar.y = display.contentHeight |
9 |
physics.addBody(playerCar) |
10 |
playerCar.bodyType = "dynamic" |
Langkah 6
Selanjutnya, kita menetapkan timer untuk mengirimkan mobil berdasarkan nilai variabel sendEnemyFrequency
dan membuat pendengar acara runtime untuk tabrakan global.
1 |
tmrToSendCars = timer.performWithDelay(sendEnemyFrequency, sendEnemyCar, 0) |
2 |
Runtime:addEventListener( "collision", onGlobalCollision) |
6. Menambahkan Fungsi Game
Kami akhirnya dapat menambahkan fungsionalitas ke game kami. Bagian ini akan menambahkan kode tambahan untuk setiap fungsi yang kami nyatakan di bagian sebelumnya. Kami akan memulai dengan incrementScore()
dan diakhiri dengan onGlobalCollision()
.
incrementScore()
Fungsi ini dipanggil ketika mobil musuh melewati pemain dan transisi selesai. Saat dipanggil, skor pemain meningkat sebesar 1. Tambahkan implementasi berikut ke fungsi incrementScore()
.
1 |
-- 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. |
2 |
local function incrementScore() |
3 |
playerScore = playerScore + 1 |
4 |
playerScoreText.text = "Score: "..playerScore |
5 |
end
|
moveCar()
The moveCar()
fungsi dipanggil ketika jalur menyentuh. Pada fase berakhir
acara, kita ambil pengenal lane dan memindahkan mobil ke jalur yang benar. Kami mengembalikan true
di bagian akhir untuk menunjukkan acara sentuhan yang sukses. Tambahkan implementasi berikut ke fungsi moveCar()
.
1 |
-- moveCar will respond to the touch event on the lanes |
2 |
local function moveCar(event) |
3 |
if(event.phase == "ended") then |
4 |
laneID = event.target.id -- grab the lane id which will be 1, 2, or 3 |
5 |
transition.to(playerCar, {x=lanes[laneID].x,time=50}) -- move the player car to the appropriate lane |
6 |
return true -- to indicate a successful touch event, return true |
7 |
end
|
8 |
end
|
sendEnemyCar()
Fungsi sendEnemyCar()
menciptakan mobil musuh, menugaskan mobil ke jalur, melampirkan badan fisika ke mobil, dan menggunakan transisi.to()
untuk mengirim mobil ke bagian bawah layar. Untuk memulai, mari kita membuat objek mobil musuh.
1 |
enemyCars[enemyCounter] = display.newImageRect(sceneGroup, "images/enemyCar"..math.random(1,3)..".png", 50, 100) |
Selanjutnya, kita atur lokasi x dan y dari mobil musuh. Kami juga membuat pernyataan jika-maka
untuk menetapkan mobil musuh ke jalur yang sama dengan mobil pemain di 50% dari waktu. Ini akan memaksa pemain untuk bergerak lebih sering dan membuat permainan lebih menyenangkan.
1 |
enemyCars[enemyCounter].x = lanes[math.random(1,#lanes)].x -- place the car on a random lane |
2 |
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. |
3 |
enemyCars[enemyCounter].y = -125 -- place the enemy off screen at the top |
Kita juga perlu memutar mobil musuh sehingga menghadap ke bawah dan menambahkan tipe tubuh fisika kinematik ke mobil musuh.
1 |
enemyCars[enemyCounter]:scale(1,-1) -- rotate the cars so they are facing down |
2 |
physics.addBody(enemyCars[enemyCounter]) -- add a physics body to enemy cars |
3 |
enemyCars[enemyCounter].bodyType = "kinematic" -- make the bodies kinematic |
Dengan mobil musuh diatur, kami menggunakan fungsi transisi.to()
mengirim mobil musuh ke salah satu jalur. Saat transisi selesai, game memanggil fungsi untuk menghapus objek. Saya juga menambah variabel enemyCounter
dengan 1 untuk melacak jumlah mobil musuh dalam permainan.
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. |
2 |
|
3 |
enemyCounter = enemyCounter + 1 -- increase enemy counter by one for tracking |
Akhirnya, kami ingin permainan untuk mendapatkan lebih cepat dari waktu ke waktu. Untuk setiap mobil lainnya yang dikirim, permainan akan menciptakan timer dan set itu harus 200ms lebih cepat.
1 |
if(enemyCounter%2 == 0) then |
2 |
sendEnemyFrequency = sendEnemyFrequency - 200 |
3 |
if(sendEnemyFrequency < 800) then sendEnemyFrequency = 800; end |
4 |
timer.cancel(tmrToSendCars) |
5 |
tmrToSendCars = timer.performWithDelay(sendEnemyFrequency, sendEnemyCar, 0) |
6 |
end
|
onPlayAgainTouch()
Fungsi terpendek, onPlayAgainTouch()
, mengembalikan pemutar ke menu utama. Inilah yang tampak seperti implementasi fungsi onPlayAgainTouch()
.
1 |
-- Allow the player to return to the menu |
2 |
local function onPlayAgainTouch() |
3 |
composer.gotoScene("scene_menu", "fade") -- move player to menu |
4 |
end
|
onGlobalCollision()
Fungsi onGlobalCollision()
digunakan untuk mendeteksi tabrakan antara dua objek fisika di layar. Dalam permainan kami, kami hanya memiliki dua jenis objek fisika:
- the player car
- mobil musuh
Ketika dua objek ini bertabrakan, game menghentikan semua timer, transisi, dan pendengar acara. Selain itu, game ini menampilkan game over scene yang memungkinkan pemain untuk bermain lagi.
Langkah 1
Pertama, kita membuat pernyataan if-then
yang mendengarkan fase dimulai
.
1 |
if(event.phase == "began") then |
2 |
|
3 |
end
|
Langkah 2
Dalam pernyataan if-then
, kami menghentikan game. Kami menjeda semua transisi, membatalkan penghitung waktu, menjeda fisika (bahkan jika itu tidak diperlukan, itu adalah panggilan pembersihan yang baik), dan menghapus pendengar acara dari ketiga jalur. Tambahkan kode berikut di dalam pernyataan if-then
:
1 |
transition.pause() |
2 |
timer.cancel(tmrToSendCars) |
3 |
physics.pause() |
4 |
|
5 |
for i=1,3 do |
6 |
lanes[i]:removeEventListener("touch", moveCar) |
7 |
end
|
Langkah 3
Setelah mekanik gim berhenti, kami menambahkan persegi panjang buram dan objek teks yang mengatakan "Game Over!" Ini memberikan indikasi visual yang baik bahwa permainan telah berakhir.
1 |
local gameOverBackground = display.newRect(sceneGroup, 0, 0, display.actualContentWidth, display.actualContentHeight) |
2 |
gameOverBackground.x = display.contentCenterX |
3 |
gameOverBackground.y = display.contentCenterY |
4 |
gameOverBackground:setFillColor(0) |
5 |
gameOverBackground.alpha = 0.5 |
6 |
|
7 |
local gameOverText = display.newText( sceneGroup, "Game Over!", 100, 200, native.systemFontBold, 36 ) |
8 |
gameOverText.x = display.contentCenterX |
9 |
gameOverText.y = 150 |
10 |
gameOverText:setFillColor( 1, 1, 1 ) |
Langkah 4
Untuk mengakhiri fungsi tabrakan global, kami menambahkan tombol putar lagi yang mengirim pemain kembali ke menu.
1 |
local playAgain = widget.newButton { |
2 |
width = 220, |
3 |
height = 100, |
4 |
defaultFile = "images/btn-blank.png", |
5 |
overFile = "images/btn-blank.png", |
6 |
label = "Menu", |
7 |
font = system.defaultFontBold, |
8 |
fontSize = 32, |
9 |
labelColor = { default={ 0, 0, 0 }, over={ 0, 0, 0, 0.5 } }, |
10 |
onEvent = onPlayAgainTouch |
11 |
}
|
12 |
playAgain.x = display.contentCenterX |
13 |
playAgain.y = gameOverText.y + 100 |
14 |
sceneGroup:insert(playAgain) |
Uji jalan
Jalankan aplikasi untuk melihat apakah semuanya berfungsi seperti yang diharapkan. Anda harus dapat memainkan permainan, mobil musuh akan muncul dari atas layar, dan skor Anda harus naik untuk setiap mobil musuh yang berhasil Anda hindari.
Kesimpulan
Terima kasih telah membaca tutorial saya tentang membuat Highway Dodge dengan Corona SDK. Anda dapat mengunduh file sumber untuk game ini dari GitHub. Luangkan waktu sejenak untuk memikirkan bagaimana Anda dapat lebih meningkatkan gim. Jika Anda mencari beberapa saran, saya akan merekomendasikan menambahkan jalur lain, menambahkan lebih banyak jenis musuh, dan bahkan menambahkan beberapa power up keren.