Hướng dẫn tạo physics bodies bằng công cụ Physics Editor trong Corona

Thảo luận trong 'Tutorials và Thủ thuật lập trình' bắt đầu bởi linhle, 23/4/14.

  1. Administrator
    linhle
    Nhân viên CoronaViet
    Tham gia ngày:
    8/2/14
    Bài viết:
    183
    Đã được thích:
    130
    Trong một dự án game Corona có sử dụng sự kiện vật lý, thì vấn đề khó khăn và tốn nhiều thời gian nhất ở đây đó chính là tạo “bodies” cho các đối tượng vật lý. Đối với những người đang sử dụng phiên bản Corona Pro trở lên thì việc tạo physics bodies sẽ dễ dàng hơn thông qua hàm graphics.newOutline(), nhưng đối với những phiên bản thấp hơn thì điều này sẽ rất khó khăn.
    Hôm nay mình sẽ hướng dẫn các bạn cách tạo “physics bodies” cho ứng dụng làm từ Corona bằng công cụ Physics Editor. Công cụ Physics Editor là một phần mềm thương mại, tuy nhiên bạn vẫn có thể sử dụng phiên bản dùng thử, nhưng mỗi lần publish chỉ cho phép chứa 10 hình ảnh mà thôi.
    Khi bắt đầu sử dụng Physics Editor điều đầu tiên cần làm là chọn nền tảng để xuất ra (exporter) cho phù hợp với dự án game của bạn (đó là corona).

    [​IMG]

    Tiếp theo kéo thả (hoặc sử dụng nút Add Sprites để thêm) các đối tượng vào khung bên trái (Shapes) của công cụ Physics Editor.
    Lưu ý: chỉ nên thêm 10 đối tượng cho một lần publish nếu đang sử dụng phiên bản dùng thử.

    [​IMG]

    Mỗi một đối tượng sẽ có tên đối tượng vật lý giống như tên hiển thị trong khung bên trái, bạn vẫn có thể sửa lại tên này. Mặc định là tên của tập tin.
    Physics Editor cung cấp cho chúng ta 3 cách để vẽ shape bodies: Add circle, Add polygon và Shape tracer.
    - Cách 1: Add circle thường được áp dụng cho những đối tượng có dạng hình tròn.
    Corona SDK không cho phép thiết lập tâm của một hình tròn. Vì vậy, nếu bạn muốn sử dụng bodies là một vòng tròn thì bạn phải chắc chắn rằng hình ảnh đó là nằm ở giữa tâm tấm ảnh.
    Ví dụ: Vẽ shape bodies cho đối tượng “corona”. Bạn cần chọn vào đối tượng “corona” ở khung bên trái, sau đó chọn công cụ có biểu tượng hình tròn bên trên có tiêu đề là Add circle, tiếp theo dùng chuột để di chuyển shape đó đến vị trí bạn muốn, sử dụng tay cầm tròn nhỏ trên shape để điều chỉnh kích cỡ của shape.

    [​IMG]
    - Cách 2: Add polygon thường sử dụng cho những đối tượng có đường viền gấp khúc.
    Ví dụ: Vẽ shape bodies cho đối tượng “star”. Bạn cần chọn đối tượng “star” ở khung bên trái, sau đó chọn công cụ có biển tượng hình ngủ giác bên trên có tiêu đề là Add polygon một tam giác shape sẽ xuất hiện, bạn dùng chuột để kéo nó đến vị trí bạn muốn, bạn vẫn có thể thêm hoặc bỏ các điểm tùy chỉnh trên shape đó bằng cách nhấp đôi chuột hoặc nhấp phải rồi chọn add/remove vertexes tại vị trí bạn muốn thêm hoặc bỏ điểm tùy chỉnh đó.

    [​IMG]
    - Cách 3: Shape tracer thường được sử dụng cho các đối tượng có đường viền phức tạp. Nó sẽ rất dễ dàng và nhanh chóng.
    Ví dụ: Vẽ shape bodies cho đối tượng “iFunSoft”. Trước tiên bạn chọn đối tượng iFunSoft ở khung bên trái, sau đó chọn vào công cụ có biểu tượng hình chiếc đũa thần bên trên có tiêu đề là Shape tracer một cửa sổ shape tracer sẽ hiện lên trên đó sẽ có tùy chọn cho phép bạn chỉnh sửa số lượng điểm tùy chỉnh của shape và một số tùy chọn khác để có thể thay đổi cho phù hợp với đối tượng của bạn.

    [​IMG]

    [​IMG]

    Dung sai (tolerance) càng lớn thì số lượng điểm tùy chỉnh (vertexes) càng ít, điều này sẽ làm cho shape không còn chính xác với đường viền của đối tượng nữa, tuy nhiên nếu điểm tùy chỉnh được tạo ra quá nhiều cũng sẽ ảnh hưởng đến quá trình tính toán của ứng dụng. Vì thế bạn phải chọn một giá trị thích hợp cho các đối tượng của bạn.
    Lưu ý: Đối với những đối tượng có hình ảnh rời rạc như ví dụ này shape tracer sẽ không thể tạo được một shape có thể bao phủ hết đối tượng của bạn. Tuy nhiên bạn vẫn có thể sử dụng một phương pháp khác để làm được điều này đó là sử dụng nhiều shape bodies cho một đối tượng. Trên một đối tượng bạn có thể thêm nhiều shape bodies bằng cách nhấp vào các biểu tượng add circle, add polygon hoặc shape tracer một lần nữa, mỗi lần nhấp vào sẽ tạo ra được một shape bodies. Một số đối tượng đòi hỏi bạn phải tách những bộ phận trên một cơ thể ra để có thể phát hiện va chạm dễ dàng hơn, phương pháp thêm nhiều shape bodies sẽ được áp dụng trong trường hợp này.

    [​IMG]


    Bên cạnh đó Physics Editor cho phép chúng ta tùy chỉnh các thông số vật lý cho từng shape bodies thông qua khung Fixture parameters:

    [​IMG]
    - Identifier là tên của một shape bodies, bạn có thể nhận ra một phần cơ thể của đối tượng dễ dàng dựa vào thuộc tính này.
    - Density là khối lượng của một shape bodies.
    - Bounce là độ nhảy của một shape bodies khi gặp va chạm.
    - Friction là độ ma sát của một shape bodies.
    - Is Sensor là xác định shape bodies đó có được tham gia vào va chạm hay không, tuy nhiên bạn vẫn có thể phát hiện được va chạm từ sự kiện collision.
    - Group là nhóm va chạm, chỉ có những shape bodies cùng nhóm với nhau mới có thể xảy ra va chạm.
    - Bit’s name, Cat.Mask dùng để kiểm soát hành vi va chạm của các shape bodies. Cat. (Category) là giá trị của chính bản thân shape bodies đó, Mask là những gì Cat. có thể va chạm được. Bạn có thể đặt Bit’s name theo ý thích của bạn, tuy nhiên nó phải có sự thống nhất giữa các đối tượng với nhau.​
    Nếu bạn đã vẽ xong shape bodies cho các đối tượng thì bước tiếp theo là publish ra (nhấn nút publish hoặc publish as) để có thể đưa vào sử dụng trong dự án game của bạn. Đồng thời bạn nên lưu lại (Save) một tập tin .pes để có thể chỉnh sửa sau này.

    Sử dụng shape bodies làm từ Physics Editor
    Ví dụ:
    Trước tiên hãy đưa tập tin .lua mà bạn mới publish ra vào dự án game của bạn, ví dụ như myShape.lua.

    Mã (Lua):

        --Yêu cầu thư viện vật lý và bắt đầu mô phỏng vật lý
        local physics = require("physics")
        physics.start()

        --Lấy dữ liệu của đối tượng từ tập tin myShape.lua
        local scale = 1.0  --Tỉ lệ của shape bodies
        local physicsData = require("myShape").physicsData(scale)

        --Tạo đối tượng từ tập tin corona.png
        local corona = display.newImage("corona.png");
        corona.x = 100
        corona.y = 200
        corona.namePhysic = "corona"  --Tên của đối tượng vật lý
        --Để có thể truy xuất đến đối tượng vật lý mong muốn sử dụng hàm physicsData:get("tên đối tượng vật lý")
        physics.addBody(corona, "dynamic", physicsData:get (corona.namePhysic))

        --Tạo đối tượng từ tập tin iFunSoft.png
        local ifunsoft = display.newImage("ifunsoft.png");
        ifunsoft.x = 300
        ifunsoft.y = 400
        ifunsoft.namePhysic = "iFunSoft"  --Tên của đối tượng vật lý
        physics.addBody(ifunsoft, "dynamic", physicsData:get (corona.namePhysic))

        --Tạo đối tượng từ tập tin star.png
        local star = display.newImage("star.png");
        star.x = 200
        star.y = 600
        star.namePhysic = "star"  --Tên của đối tượng vật lý
        physics.addBody(star, "dynamic", physicsData:get (corona.namePhysic))

        --Tạo đối tượng nền đất
        local floor = display.newRect(0,0,480,30)
        floor.x = 240
        floor.y = 785
        floor.myName = "floor"
        physics.addBody(floor, "static")

        local function onLocalCollision(self, event)
            --Lấy tên shape bodies của bản thân đối tượng
            local selfFixtureId = physicsData:getFixtureId(self.namePhysic, event.selfElement)
            if event.other.namePhysic ~= nil then
                --Lấy tên shape bodies của đối tượng được va chạm
                local otherFixtureId = physicsData:getFixtureId(event.other.namePhysic, event.otherElement)
                --In ra dòng text phát hiện va chạm với đối tượng khác
                print(self.namePhysic .. ":" .. selfFixtureId .. " va chạm với " .. event.other.namePhysic .. ":" .. otherFixtureId)
       
            else
                --In ra dòng text va chạm với đối tượng không có trong myShape.lua
                print(self.namePhysic .. ":" .. selfFixtureId .. " va chạm với " .. event.other.myName)
            end
        end

        corona.collision = onLocalCollision
        corona:addEventListener("collision", corona)
        ifunsoft.collision = onLocalCollision
        ifunsoft:addEventListener("collision", ifunsoft)
        star.collision = onLocalCollision
        star:addEventListener("collision", star)

    Chúc bạn thành công!!!
    Last edited by a moderator: 16/7/14
    Võ Thanh Liêm thích bài này.
  2. New Member
    Võ Thanh Liêm
    Tham gia ngày:
    2/1/16
    Bài viết:
    18
    Đã được thích:
    3
    ad ơi cho em hỏi nếu muốn làm cho ảnh động thì sao vậy ad ?
  3. Administrator
    linhle
    Nhân viên CoronaViet
    Tham gia ngày:
    8/2/14
    Bài viết:
    183
    Đã được thích:
    130
    Bạn lấy 1 trong những tấm hình làm ảnh động rồi vẽ physics cho nó rồi sau đó addBody bình thường. Lưu ý nên vẽ biên của physics phỏng đoán theo các biên của ảnh động vì physics chúng ta không thể làm thay đổi theo từng ảnh động được.
  4. New Member
    khoimm92
    Tham gia ngày:
    19/9/16
    Bài viết:
    7
    Đã được thích:
    1
    Cho mình hỏi, apply shape ra, nó bị lệch so với hình chính thì phải làm sao, đã ai bị như thế chưa :|
    Last edited: 19/9/16
  5. Administrator
    linhle
    Nhân viên CoronaViet
    Tham gia ngày:
    8/2/14
    Bài viết:
    183
    Đã được thích:
    130
    Bạn vẽ shape hình tròn phải không bạn?
  6. New Member
    khoimm92
    Tham gia ngày:
    19/9/16
    Bài viết:
    7
    Đã được thích:
    1
    [​IMG]
    Đây bạn ơi
  7. Administrator
    linhle
    Nhân viên CoronaViet
    Tham gia ngày:
    8/2/14
    Bài viết:
    183
    Đã được thích:
    130
    Có thể bạn đã di chuyển group chứa đối tượng đó nên làm physic bị lệch đi. Chứ trước giờ mình trưa thấy tình trạng như vậy.
  8. New Member
    khoimm92
    Tham gia ngày:
    19/9/16
    Bài viết:
    7
    Đã được thích:
    1
    Mình nghĩ do dùng bản Physics editor crack nó lỗi. Mình vừa chuyển sang dùng Physics body editor thì lại ko bị thế.
    linhle thích bài này.
  9. New Member
    khoimm92
    Tham gia ngày:
    19/9/16
    Bài viết:
    7
    Đã được thích:
    1
    Cho mình hỏi nữa với. Mình scale object xong rồi tạo physics body thì shape nó không ăn theo, vẫn kích cỡ nguyên bản, các bạn có cách nào không?
  10. Administrator
    linhle
    Nhân viên CoronaViet
    Tham gia ngày:
    8/2/14
    Bài viết:
    183
    Đã được thích:
    130
    Bạn thay đoạn code ở phần chú thích "--appy scale factor" bằng đoạn code này nhé
    Mã (Lua):
    local sX = scaleX or 1.0
        local sY = scaleY or 1.0
        for bi,body in pairs(physics.data) do
            for fi,fixture in ipairs(body) do
                if(fixture.shape) then
                    for ci,coordinate in ipairs(fixture.shape) do
                        if (ci%2) == 0 then
                            fixture.shape[ci] = sY * coordinate
                        else
                            fixture.shape[ci] = sX * coordinate
                        end
                    end
                else
                    fixture.radius = ((sX+sY)*0.5) * fixture.radius
                end
            end
        end
    Đối số của hàm physicsData thay vì là biến scale thì bạn thay bằng 2 biến là scaleX và scaleY
    Khi đối tượng scale bao nhiêu thì truyền 2 thông số đó vào hàm physicsData để lấy ra được physic shape bạn muốn
    khoimm92 thích bài này.

Chia sẻ trang này