Views
Tutorial:PhysicsCollisionCallbacks (Русский)
Contents |
Предисловие
Если у вас слабое представление о love.physics, вам нужно сначала ознакомиться с вводным руководством по использованию физики.
В этом руководстве мы создадим столкновение между двумя объектами, которое вызывается определенной callback-функцией (колбеком), заданной в World:setCallbacks.
Руководство
Создание main.lua
Начнем с создания main.lua с тремя функциями: love.load, love.update, and love.draw
end
function love.update(dt)
end
function love.draw()
end
Настройка мира
Сейчас, когда фреймворк уже настроен, настроим физический мир в love.load с newWorld. Мы также будем использовать World:update.
-- Помещаем новый "мир" в переменную "world"
world = love.physics.newWorld(0, 200, true) -- Гравитация установлена равной 0 по оси X и 200 по оси Y
end
function love.update(dt)
-- Никогда не забывайте обновлять мир каждый кадр
world:update(dt)
end
Теперь нам нужно создать мяс и землю. Чтобы это сделать нам потребуются newBody, newCircleShape и newRectangleShape. Тела к формам мы будем прикреплять с поощью newFixture.
... -- не пишите это, это просто обозначение, в какой функции, в каком месте должен быть этот код
ball = {}
ball.b = love.physics.newBody(world, 400,200, "dynamic") -- устанавливаем x,y координаты (400,200) и позволяем двигаться и задевать другие объекты ("dynamic")
ball.b:setMass(10) -- делаем довольно легким
ball.s = love.physics.newCircleShape(50) -- устанвливаем радиус 50
ball.f = love.physics.newFixture(ball.b, ball.s) -- прикрепляем тело к форме
ball.f:setRestitution(0.4) -- делаем упругим
ball.f:setUserData("Ball") -- устанавливаем имя, которое будем использовать для достпуа к объекту позже
static = {}
static.b = love.physics.newBody(world, 400,400, "static") -- "static" делает объект неподвижным
static.s = love.physics.newRectangleShape(200,50) -- устанавливаем размер 200,50 (x,y)
static.f = love.physics.newFixture(static.b, static.s)
static.f:setUserData("Block")
end
Объекты уже созданы, но вы все еще не видите их. Давайте нарисуем их.
love.graphics.circle("line", ball.b:getX(),ball.b:getY(), ball.s:getRadius(), 20)
love.graphics.polygon("line", static.b:getWorldPoints(static.s:getPoints()))
end
Теперь мы можем увидеть мяч, падающий вниз на прямоугольник
World Callbacks
Но что если нам нужно больше информации о сталкновении этих объектов? Теперь мы будем использовать World:setCallbacks для дальнейшего анализа их столкновений.
Первое, что мы сделаем, это установим колбеки для нашего мира с World:setCallbacks. Есть четыре колбека для столкновения: beginContact, endContact, preSolve и postSolve.
- beginContact вызывается когда две привязки (fixtures) начинают перекрывать друг друга (два объекта сталкиваются).
- endContact вызывается когда две привязки (fixtures) перестаются перекрывать друг друга (два объекта разъединяются).
- preSolve вызывается непосредственно перед завершение кадра для текущего столкновения
- postSolve вызывается непосредственно после завершения кадра для текущего столкновения
... -- добавить к остальному love.load
world = love.physics.newWorld(0, 200, true)
-- Названия этих колбеков могут быть такими, как вы захотите:
world:setCallbacks(beginContact, endContact, preSolve, postSolve)
text = "" -- мы будем испольовать позже эту переменную для размещения информации на экране
persisting = 0 -- мы будем использовать это, чтобы сохранить состояние неоднократных вызовов колбека
Теперь объявим эти функции.
end
function endContact(a, b, coll)
end
function preSolve(a, b, coll)
end
function postSolve(a, b, coll)
end
Эти функции происходят каждрый раз, когда происходит какое-то из действий при столкновении. Они принимают две привязки (fixtures) и объект столкновения (collision object). Эти параметры так же могут быть названы как вам захочется. В этом руководстве мы назовем их a, b и coll.
- a - первая привязкка (fixture) в столкновении (привязка от первого объекта между его телом и формой).
- b - вторая привязка в столкновении.
- coll - создаваемый контакт-объект (контакт).
Допустим, мы хотим напечатать информацию на экран каждый раз, когда колбек вызван. Нам всего лишь нужно изменить переменную text, которую мы добавили в love.load() ранее, добавляя строку каждый раз, когда происходит столкновение. Нам также нужно немного кода, чтобы поддерживать вывод (лог) чистым.
Список функций, которые вы можете использовать с контактами может быть найден на странице Contact.
... -- добавить к остальному love.update
if string.len(text) > 768 then -- очистка, когда 'text' становится слишком длинным
text = ""
end
end
function love.draw()
... -- добавить к остальному love.draw
love.graphics.print(text, 10, 10)
end
function beginContact(a, b, coll)
x,y = coll:getNormal()
text = text.."\n"..a:getUserData().." colliding with "..b:getUserData().." with a vector normal of: "..x..", "..y
end
function endContact(a, b, coll)
persisting = 0 -- сбрасываем, когда они перестают соприкасаться
text = text.."\n"..a:getUserData().." uncolliding with "..b:getUserData()
end
function preSolve(a, b, coll)
if persisting == 0 then -- только говорит, когда они впервые начинают касаться
text.."\n"..a:getUserData().." touching "..b:getUserData()
elseif persisting < 20 then -- затем просто начинается вести отсчет
text = text.." "..persisting
end
persisting = persisting + 1 -- отслеживает как много обновлений они соприкасались
end
function postSolve(a, b, coll)
-- мы не будем ничего делать с этой функцией
end
Теперь вы знаете как использовать колбеки физического мира (world callbacks)!
Чтобы лучше понять как мир себя ведет и видеть когда колбеки вызываются, добавим элементы управления, позволяющие подкидывать, толкать мяч:
world:update(dt)
if love.keyboard.isDown("right") then
ball.b:applyForce(1000, 0)
elseif love.keyboard.isDown("left") then
ball.b:applyForce(-1000, 0)
end
if love.keyboard.isDown("up") then
ball.b:applyForce(0, -5000)
elseif love.keyboard.isDown("down") then
ball.b:applyForce(0, 1000)
end
if string.len(text) > 768 then -- очищаем когда 'text' станет слишком длинным
text = ""
end
end
Завершение
Скриншоты
main.lua
world = love.physics.newWorld(0, 200, true)
world:setCallbacks(beginContact, endContact, preSolve, postSolve)
ball = {}
ball.b = love.physics.newBody(world, 400,200, "dynamic")
ball.b:setMass(10)
ball.s = love.physics.newCircleShape(50)
ball.f = love.physics.newFixture(ball.b, ball.s)
ball.f:setRestitution(0.4) -- делаем упругим
ball.f:setUserData("Ball")
static = {}
static.b = love.physics.newBody(world, 400,400, "static")
static.s = love.physics.newRectangleShape(200,50)
static.f = love.physics.newFixture(static.b, static.s)
static.f:setUserData("Block")
text = "" -- будем использовать эту переменную для вывода на экран
persisting = 0 -- будем использовать, чтобы сохранить состояние неоднократных вызовов колбека
end
function love.update(dt)
world:update(dt)
if love.keyboard.isDown("right") then
ball.b:applyForce(1000, 0)
elseif love.keyboard.isDown("left") then
ball.b:applyForce(-1000, 0)
end
if love.keyboard.isDown("up") then
ball.b:applyForce(0, -5000)
elseif love.keyboard.isDown("down") then
ball.b:applyForce(0, 1000)
end
if string.len(text) > 768 then -- очищаем 'text' становится слишком длинным
text = ""
end
end
function love.draw()
love.graphics.circle("line", ball.b:getX(),ball.b:getY(), ball.s:getRadius(), 20)
love.graphics.polygon("line", static.b:getWorldPoints(static.s:getPoints()))
love.graphics.print(text, 10, 10)
end
function beginContact(a, b, coll)
x,y = coll:getNormal()
text = text.."\n"..a:getUserData().." colliding with "..b:getUserData().." with a vector normal of: "..x..", "..y
end
function endContact(a, b, coll)
persisting = 0
text = text.."\n"..a:getUserData().." uncolliding with "..b:getUserData()
end
function preSolve(a, b, coll)
if persisting == 0 then -- только говорит, когда они впервые начинают касаться
text = text.."\n"..a:getUserData().." touching "..b:getUserData()
elseif persisting < 20 then -- затем просто начинается вести отсчет
text = text.." "..persisting
end
persisting = persisting + 1 -- отслеживает как много обновлений они соприкасались
end
function postSolve(a, b, coll)
end
Другие языки
Dansk –
Deutsch –
English –
Español –
Français –
Indonesia –
Italiano –
Lietuviškai –
Magyar –
Nederlands –
Polski –
Português –
Română –
Slovenský –
Suomi –
Svenska –
Türkçe –
Česky –
Ελληνικά –
Български –
Русский –
Српски –
Українська –
עברית –
ไทย –
日本語 –
正體中文 –
简体中文 –
Tiếng Việt –
한국어
More info