Hướng dẫn tạo một game Đà điểu chạy "Ostrich Runner" từ A đến Z với Corona

Thảo luận trong 'Tutorials và Thủ thuật lập trình' bắt đầu bởi Khúc Vương, 11/7/14.

  1. Administrator
    Khúc Vương
    Nhân viên CoronaViet
    Tham gia ngày:
    17/1/14
    Bài viết:
    477
    Đã được thích:
    130
    Trong bài hướng dẫn này, tôi sẽ hướng đẫn cho bạn tạo ra một trò chơi thể loại runner (chạy vô tận) với Corona SDK bằng cách xây dựng một trò chơi với tên Ostrich Runner. Bạn sẽ học thêm về di chuyển các đối tượng, thao tác vật lý, điều khiển cảm ứng, và phát hiện va chạm. Mục tiêu của trò chơi là điều khiển di chuyển của nhân vật và thu thập các item để nâng cao điểm số.

    [​IMG]

    Trong hướng dẫn này, chúng ta sẽ tập trung vào nền tảng iOS về mặt đồ họa. Đặc biệt là chúng ta sẽ phát triển cho iPhone và iPod Touch. Tuy nhiên, các code của hướng dẫn này cũng có thể được sử dụng trong nền tảng Android.

    1. App Configuration
    Thiết lập file config.lua và chép đoạn code sau vào đó:
    Mã (Lua):
    application =
    {
        content =
        {
            width = 320,
            height = 480,
            scale = "letterbox"
        },
    }
    2. Main.lua
    Mở trình soạn thảo Lua mà bạn thích. Bất kỳ trình soạn thảo văn bản đơn giản nào cũng cho phép bạn làm việc này trên đó, nhưng mình khuyến khích sử dụng một trình soạn thảo văn bản có thể làm nổi bật các cú pháp trong code như IntelliJ IDEA Community Edition mà Corona Việt đã đề cập tới trong các bài viết trước. Tạo một file mới và lưu nó là main.lua trong thư mục dự án của bạn.

    3. Ẩn thanh trạng thái
    Đoạn code này sẽ ẩn thanh trạng thái. Thanh trạng thái là thanh ở trên cùng của màn hình thiết bị, nó hiển thị thời gian, tín hiệu, và các chỉ số khác.
    Mã (Lua):
    display.setStatusBar(display.HiddenStatusBar)
    4. Import Physics
    Chúng ta sẽ sử dụng thư viện Physics để sử lý va chạm.
    Mã (Lua):
    local physics = require('physics')
    physics.start()
    5. Background

    [​IMG]

    Tạo một Background với một hình ảnh đơn giản:
    Mã (Lua):
    local bg = display.newImage('bg.png')
    6. Title view

    [​IMG]

    Đây là màn hình hiển thị chính. Đó là màn hình tương tác đầu tiên xuất hiện trong trò chơi chúng ta. Đây là các biến lưu trữ các thành phần của nó.
    Mã (Lua):
    local title
    local playBtn
    local creditsBtn
    local titleView
    7. Credits view
    Màn hình sẽ hiển thị về các thông tin bản quyền của trò chơi… Biến này sẽ được sử dụng để lưu trữ một tham chiếu đến giao diện credits screen:
    Mã (Lua):
    local creditsView
    8. Game background

    [​IMG]

    Đây là background của màn chơi, nó cũng có thêm các textfield điểm số.
    Mã (Lua):
    local gameBg
    9. Thông báo hướng dẫn
    [​IMG]

    Một thông báo hướng dẫn sẽ xuất hiện khi bắt đầu trò chơi, nó sẽ được Tweened ra sau 2 giây.
    Mã (Lua):
    local ins
    10. Character
    [​IMG]

    Hình ảnh nhân vật của chúng ta. Mục tiêu của trò chơi là di chuyển nó lên và xuống trong màn hình để thu thập các quả cherry.
    Mã (Lua):
    local ostrich
    11. Cherries
    [​IMG]
    Các hình ảnh quả Cherry. Ngoài ra còn có những quả bad cherry (là các quả cherry thúi) sẽ làm cho bạn thua cuộc trong trò chơi.
    Mã (Lua):
    local cherrys
    12. Pad
    [​IMG]
    Đây là hình ảnh pad. Tap vào chúng để di chuyển nhân vật.
    Mã (Lua):
    local up
    local down
    13. Alert
    [​IMG]

    Đây là cảnh báo sẽ được hiển thị khi nhân vật thu thập trúng bad cherry. Khi đó trò chơi sẽ kết thúc trò chơi.
    Mã (Lua):
    local alertView
    14. Sound
    Chúng ta sẽ cần thêm âm thanh để game hấp đẫn hơn, ví dụ ta có 3 âm thanh sau:
    Mã (Lua):
    local bgMusic = audio.loadStream('POL-purple-hills-short.mp3')
    local cherrySnd = audio.loadSound('cherry.mp3')
    local badCherrySnd = audio.loadSound('badCherry.mp3')
    15. Biến
    Đây là các biến chúng ta sẽ sử dụng nó trong game:
    Mã (Lua):
    local timerSrc –- thời gian cộng thêm các quả cherry
    local yPos = {108, 188, 268}- tọa độ y vị trí cho nhân vật
    local speed = 5- tốc độ quả cherry
    local speedTimer -- timer để đổi tốc độ quả cherry
     
    16. Khai báo hàm
    Khai báo các hàm cần dùng sau đây:
    Mã (Lua):
    local Main = {}
    local startButtonListeners = {}
    local showCredits = {}
    local hideCredits = {}
    local showGameView = {}
    local gameListeners = {}
    local startGame = {}
    local createCherry = {}
    local movePlayer = {}
    local increaseSpeed = {}
    local update = {}
    local onCollision = {}
    local alert = {}
    17. Cấu trúc Code
    Bây giờ tạo hàm Main (), hàm đầu tiên sẽ được gọi khi trò chơi của chúng ta bắt đầu:
    Mã (Lua):
    function Main()
        -- code...
    end
    17. Add title view
    Chúng ta bắt đầu bằng cách đặt Title View vào màn hình chính và gọi một hàm để thêm tap listener vào các nút.
    Mã (Lua):
    function Main()
        titleBg = display.newImage('title.png', 113, 43)
        playBtn = display.newImage('playBtn.png', 219, 160)
        creditsBtn = display.newImage('creditsBtn.png', 205, 223)
        titleView = display.newGroup(bg, titleBg, playBtn, creditsBtn)

        startButtonListeners('add')
    end
    18. Start button listener
    Các hàm sau add thêm Listener vào các nút của TitleView.
    Mã (Lua):
    function startButtonListeners(action)
        if(action == 'add') then
            playBtn:addEventListener('tap', showGameView)
            creditsBtn:addEventListener('tap', showCredits)
        else
            playBtn:removeEventListener('tap', showGameView)
            creditsBtn:removeEventListener('tap', showCredits)
        end
    end
    19. Show Credits
    Màn hình Credits được hiển thị khi người sử dụng tap vào nút Credits. Thêm một tap listener vào Credits view để remove.
    Mã (Lua):
    function showCredits:tap(e)
        playBtn.isVisible = false
        creditsBtn.isVisible = false
        creditsView = display.newImage('credits.png', -130, display.contentHeight-140)
        transition.to(creditsView, {time = 300, x = 65, onComplete = function() creditsView:addEventListener('tap', hideCredits) end})
    end
    20. Hide Credits
    Khi người chơi tap vào màn hình credits, nó sẽ bị remove và đưa người chơi quay trở lại title view.
    Mã (Lua):
    function hideCredits:tap(e)
        playBtn.isVisible = true
        creditsBtn.isVisible = true
        transition.to(creditsView, {time = 300, y = display.contentHeight+creditsView.height, onComplete = function() creditsView:removeEventListener('tap', hideCredits) display.remove(creditsView) creditsView = nil end})
    end
    21. Show Game View
    Khi người chơi tap vào nút Start, màn hình title view sẽ bị remove và game sẽ hiện ra.
    Mã (Lua):
    function showGameView:tap(e)
        transition.to(titleView, {time = 300, x = -titleView.height, onComplete = function() startButtonListeners('rmv') display.remove(titleView) titleView = nil end})
    22. Thông báo hướng dẫn
    Các dòng sau sẽ thêm các thông báo hướng dẫn cho trò chơi.
    Mã (Lua):
    ins = display.newImage('ins.png', 187, 199)
    23. TextField điểm số
    Phần này tạo ra TextField hiển thị điểm số trên màn hình.
    Mã (Lua):
    scoreTF = display.newText('0', 258, 26.5, 'Marker Felt', 16)
    scoreTF:setTextColor(184, 165, 104)
    24. Ostrich (Đà điểu)
    Add nhân vật đà điểu của chúng ta vào phần chơi.
    Mã (Lua):
    ostrich = display.newImage('ostrich.png', 11, 180)
    25. Pad
    Đây là các hình ảnh dùng để điều khiển nhân vật trong game
    Mã (Lua):
    up = display.newImage('up.png', 418, 20)
    down = display.newImage('down.png', 418, 258)

    up.name = 'up'
    down.name = 'down'
    26. Physics
    Tiếp theo, chúng ta add Physics cho các đối tượng trong trò chơi. Chúng ta cũng tạo ra một bảng cho cherry và gọi hàm gameListeners.
    Mã (Lua):
    physics.addBody(ostrich)
        ostrich.isSensor = true
        cherrys = display.newGroup()
        gameListeners('add')
    end
    27. Game Listeners
    Hàm này bổ sung thêm các listener cần thiết để bắt đầu game logic.
    Mã (Lua):
    function gameListeners(action)
        if(action == 'add') then
            ins:addEventListener('tap', startGame)
            Runtime:addEventListener('enterFrame', update)
            up:addEventListener('tap', movePlayer)
            down:addEventListener('tap', movePlayer)
            speedTimer = timer.performWithDelay(5000, increaseSpeed, 5)
        else
            Runtime:removeEventListener('enterFrame', update)
            up:removeEventListener('tap', movePlayer)
            down:removeEventListener('tap', movePlayer)
            timer.cancel(timerSrc)
            timerSrc = nil
            timer.cancel(speedTimer)
            speedTimer = nil
        end
    end
    28. Start game
    Trong phần này, chúng ta sẽ remove thông báo hướng dẫn, bắt đầu play nhạc nền, và tạo ra một timer để thêm một Cherry vào màn hình mỗi 400 mili giây.
    Mã (Lua):
    function startGame()
        ins:removeEventListener('tap', startGame)
        display.remove(ins)
        audio.play(bgMusic, {loops = -1, channel = 1})

        timerSrc = timer.performWithDelay(400, createCherry, 0)
    end
    29. Tạo ra các quả Cherry
    Đoạn tiếp theo của code sẽ tạo ra một quả Cherry bình thường hay bad dựa trên một số ngẫu nhiên và thêm nó vào màn hình. Quả cherry cũng sẽ được add physics vào body để kiểm tra va chạm.
    Mã (Lua):
    function createCherry()
        local cherry
        local rnd = math.floor(math.random() * 4) + 1
        if(rnd == 4) then
            cherry = display.newImage('badCherry.png', display.contentWidth, yPos[math.floor(math.random() * 3)+1])
            cherry.name = 'bad'
        else
            cherry = display.newImage('cherry.png', display.contentWidth, yPos[math.floor(math.random() * 3)+1])
            cherry.name = 'cherry'
        end
        -- Cherry physics
        physics.addBody(cherry)
        cherry.isSensor = true
        cherry:addEventListener('collision', onCollision)
        cherrys:insert(cherry)
    end
    30. Move player
    Chúng ta thay đổi vị trí Y của chú đà điểu bằng cách sử dụng pad điều khiển mà chúng ta đã tạo ra trước đó.
    Mã (Lua):
    function movePlayer(e)
        if(e.target.name == 'up' and ostrich.y ~= 122) then
            ostrich.y = ostrich.y - 80
        elseif(e.target.name == 'down' and ostrich.y ~= 282) then
            ostrich.y = ostrich.y + 80
        end
    end
    31. Tăng tốc (Increase Speed)
    Timer sẽ tăng tốc độ mỗi 5 giây. Một icon sẽ được hiển thị để thông báo cho người chơi về sự thay đổi tốc độ của game.
    Mã (Lua):
    function increaseSpeed()
        speed = speed + 2
        -- Icon
        local icon = display.newImage('speed.png', 204, 124)
        transition.from(icon, {time = 200, alpha = 0.1, onComplete = function() timer.performWithDelay(500, function() transition.to(icon, {time = 200, alpha = 0.1, onComplete = function() display.remove(icon) icon = nil end}) end) end})
    end
    32. Hàm Update
    Hàm này xử lý các di chuyển của các quả cherry. Nó sử dụng biến tốc độ để xác định quả cherry di chuyển bao nhiêu điểm ảnh mỗi khung hình.
    Mã (Lua):
    function update()
        if (cherrys ~= nil) then
            for i = 1, cherrys.numChildren do
                cherrys[i].x = cherrys[i].x - speed
            end
        end
    end
    33. Collisions
    Bây giờ chúng ta kiểm tra xem quả Cherry va chạm với đà điểu bằng cách sử dụng đoạn code sau. Điểm số tăng lên khi va chạm với quả cherry bình thường, nếu va chạm với bad cherry thì alert sẽ được gọi. Trong cả hai trường hợp va chạm với cherry thì hình ảnh quả cherry sẽ bị remove và âm thanh tương ứng sẽ được play.
    Mã (Lua):
    function onCollision(e)
        e.target:removeEventListener('collision', onCollision)
        display.remove(e.target)

        if(e.target.name == 'cherry') then
            --Score
            scoreTF.text = tostring(tonumber(scoreTF.text) + 50)
            audio.play(cherrySnd)
        -- Bad cherry
        elseif(e.target.name == 'bad') then
            audio.play(badCherrySnd)
            alert()
        end
    end
    34. Alert
    Hàm alert sẽ tạo ra một màn hình thông báo, và sau đó kết thúc trò chơi.
    Mã (Lua):
    function alert()
        audio.stop(1)
        audio.dispose()
        bgMusic = nil
        gameListeners('rmv')
        alertView = display.newImage('alert.png', 160, 115)
        transition.from(alertView, {time = 300, xScale = 0.5, yScale = 0.5})

        local score = display.newText(scoreTF.text, (display.contentWidth * 0.5) - 12, (display.contentHeight * 0.5) + 5, 'Marker Felt', 18)
        score:setTextColor(184, 165, 104)

        -- Chờ 100 mili giây để stop physics
        timer.performWithDelay(1000, function() physics.stop() end, 1)
    end
    35. Call Main
    Cuối cùng gọi hàm main để hoàn thành code của chúng ta:
    Mã (Lua):
    Main()
    Thế là xong! Chúng ta đã hoàn thành một game đơn giản nhưng cũng khá khó chơi, đúng không nhỉ? Một bước cuối cùng nữa là ta chỉ việc test thôi, nếu đã ổn thỏa chúng ta sẽ làm thêm một số việc như tạo loading screen, icon, và build nó ra như mình đã hướng dẫn ở bài trước. Bạn có thể xem tại đây: Hướng dẫn: Tạo một game "Máy bay lên thẳng" từ A đến Z với Corona.
    Chúc các bạn thành công! nếu có vấn đề gì vui lòng thảo luận bên dưới.
    Last edited by a moderator: 16/7/14
    nhoxcon_pt and NhanHo like this.
  2. New Member
    hoangxuanbinhcntt
    Tham gia ngày:
    29/5/14
    Bài viết:
    28
    Đã được thích:
    3
    Có thể up images và sounds không @Khúc Vương ? Mình không biết trang nào để lấy mấy cái sound này cả.
    Thanks
  3. Member
    NhanHo
    Tham gia ngày:
    16/6/14
    Bài viết:
    33
    Đã được thích:
    8
  4. Administrator
    Khúc Vương
    Nhân viên CoronaViet
    Tham gia ngày:
    17/1/14
    Bài viết:
    477
    Đã được thích:
    130
    Nếu bạn có âm thanh riêng thì đổi tên âm thanh hoặc sửa lại code cũng dc, một số trang cũng cấp free âm thanh như bạn NhanHo vừa đưa đó bạn. Hình ảnh thì bạn cứ save về đặt tên cho dúng là dc, một số trang cũng cho hình ảnh free đc bảo hộ bản quyền creative commons đó bạn, search GG nhé :p
    hoangxuanbinhcntt thích bài này.
  5. New Member
    KieuOanh
    Tham gia ngày:
    10/4/15
    Bài viết:
    2
    Đã được thích:
    0
    Cho mình xin source code game được k ad?
  6. Administrator
    Khúc Vương
    Nhân viên CoronaViet
    Tham gia ngày:
    17/1/14
    Bài viết:
    477
    Đã được thích:
    130
    Hi, game được chia sẻ viết trên Graphics 1.0 bạn bên bật v1 trong config.lua nhé. Download

Chia sẻ trang này