Difference between revisions of "World:rayCast"
m (→Casting a ray over some random shapes.: getMicroTime no longer exists) |
m (→Casting a ray over some random shapes.) |
||
Line 43: | Line 43: | ||
function createStuff() | function createStuff() | ||
-- Cleaning up the previous stuff. | -- Cleaning up the previous stuff. | ||
− | for i = | + | for i = #Terrain.Stuff, 1, -1 do |
Terrain.Stuff[i].Fixture:destroy() | Terrain.Stuff[i].Fixture:destroy() | ||
Terrain.Stuff[i] = nil | Terrain.Stuff[i] = nil | ||
Line 118: | Line 118: | ||
-- Drawing the terrain. | -- Drawing the terrain. | ||
love.graphics.setColor(255, 255, 255) | love.graphics.setColor(255, 255, 255) | ||
− | for i | + | for i, v in ipairs(Terrain.Stuff) do |
− | if | + | if v.Shape:getType() == "polygon" then |
− | love.graphics.polygon("line", Terrain.Body:getWorldPoints( | + | love.graphics.polygon("line", Terrain.Body:getWorldPoints( v.Shape:getPoints() )) |
− | elseif | + | elseif v.Shape:getType() == "edge" then |
− | love.graphics.line(Terrain.Body:getWorldPoints( | + | love.graphics.line(Terrain.Body:getWorldPoints( v.Shape:getPoints() )) |
else | else | ||
− | local x, y = Terrain.Body:getWorldPoints( | + | local x, y = Terrain.Body:getWorldPoints(v.x, v.y) |
− | love.graphics.circle("line", x, y, | + | love.graphics.circle("line", x, y, v.Shape:getRadius()) |
end | end | ||
end | end | ||
Line 136: | Line 136: | ||
-- Drawing the intersection points and normal vectors if there were any. | -- Drawing the intersection points and normal vectors if there were any. | ||
− | for i | + | for i, hit in ipairs(Ray.hitList) do |
− | |||
love.graphics.setColor(255, 0, 0) | love.graphics.setColor(255, 0, 0) | ||
love.graphics.print(i, hit.x, hit.y) -- Prints the hit order besides the point. | love.graphics.print(i, hit.x, hit.y) -- Prints the hit order besides the point. |
Revision as of 19:40, 22 April 2015
Available since LÖVE 0.8.0 |
This method is not supported in earlier versions. |
Casts a ray and calls a function with the fixtures that intersect it. You cannot make any assumptions about the order of the callbacks.
Each time the function gets called, 6 arguments get passed to it. The first is the fixture intersecting the ray. The second and third are the coordinates of the intersection point. The fourth and fifth is the surface normal vector of the shape edge. The sixth argument is the position of the intersection on the ray as a number from 0 to 1 (or even higher if the ray length was changed with the return value).
The ray can be controlled with the return value. A positive value sets a new ray length where 1 is the default value. A value of 0 terminates the ray. If the callback function returns -1, the intersection gets ignored as if it didn't happen.
function callback(fixture, x, y, xn, yn, fraction)
return 1
end
Contents
Function
Synopsis
World:rayCast( x1, y1, x2, y2, callback )
Arguments
number x1
- The x position of the starting point of the ray.
number y1
- The y position of the starting point of the ray.
number x2
- The x position of the end point of the ray.
number y2
- The y position of the end point of the ray.
function callback
- This function gets six arguments and should return a number.
Returns
Nothing.
Notes
There is a bug in LÖVE 0.8.0 where the normal vector passed to the callback function gets scaled by love.physics.getMeter.
Examples
Casting a ray over some random shapes.
function worldRayCastCallback(fixture, x, y, xn, yn, fraction)
local hit = {}
hit.fixture = fixture
hit.x, hit.y = x, y
hit.xn, hit.yn = xn, yn
hit.fraction = fraction
table.insert(Ray.hitList, hit)
return 1 -- Continues with ray cast through all shapes.
end
function createStuff()
-- Cleaning up the previous stuff.
for i = #Terrain.Stuff, 1, -1 do
Terrain.Stuff[i].Fixture:destroy()
Terrain.Stuff[i] = nil
end
-- Generates some random shapes.
for i = 1, 30 do
local p = {}
p.x, p.y = math.random(100, 700), math.random(100, 500)
local shapetype = math.random(3)
if shapetype == 1 then
local w, h, r = math.random() * 10 + 40, math.random() * 10 + 40, math.random() * math.pi * 2
p.Shape = love.physics.newRectangleShape(p.x, p.y, w, h, r)
elseif shapetype == 2 then
local a = math.random() * math.pi * 2
local x2, y2 = p.x + math.cos(a) * (math.random() * 30 + 20), p.y + math.sin(a) * (math.random() * 30 + 20)
p.Shape = love.physics.newEdgeShape(p.x, p.y, x2, y2)
else
local r = math.random() * 40 + 10
p.Shape = love.physics.newCircleShape(p.x, p.y, r)
end
p.Fixture = love.physics.newFixture(Terrain.Body, p.Shape)
Terrain.Stuff[i] = p
end
end
function love.keypressed()
createStuff()
end
function love.load()
-- Setting this to 1 to avoid all current scaling bugs.
love.physics.setMeter(1)
-- Start out with the same random stuff each start.
math.randomseed(0xfacef00d)
World = love.physics.newWorld()
Terrain = {}
Terrain.Body = love.physics.newBody(World, 0, 0, "static")
Terrain.Stuff = {}
createStuff()
Ray = {
x1 = 0,
y1 = 0,
x2 = 0,
y2 = 0,
hitList = {}
}
end
function love.update(dt)
local now = love.timer.getTime()
World:update(dt)
-- Clear fixture hit list.
Ray.hitList = {}
-- Calculate ray position.
local pos = (math.sin(now/4) + 1.2) * 0.4
Ray.x2, Ray.y2 = math.cos(pos * (math.pi/2)) * 1000, math.sin(pos * (math.pi/2)) * 1000
-- Cast the ray and populate the hitList table.
World:rayCast(Ray.x1, Ray.y1, Ray.x2, Ray.y2, worldRayCastCallback)
end
function love.draw()
-- Drawing the terrain.
love.graphics.setColor(255, 255, 255)
for i, v in ipairs(Terrain.Stuff) do
if v.Shape:getType() == "polygon" then
love.graphics.polygon("line", Terrain.Body:getWorldPoints( v.Shape:getPoints() ))
elseif v.Shape:getType() == "edge" then
love.graphics.line(Terrain.Body:getWorldPoints( v.Shape:getPoints() ))
else
local x, y = Terrain.Body:getWorldPoints(v.x, v.y)
love.graphics.circle("line", x, y, v.Shape:getRadius())
end
end
-- Drawing the ray.
love.graphics.setLineWidth(3)
love.graphics.setColor(255, 255, 255, 100)
love.graphics.line(Ray.x1, Ray.y1, Ray.x2, Ray.y2)
love.graphics.setLineWidth(1)
-- Drawing the intersection points and normal vectors if there were any.
for i, hit in ipairs(Ray.hitList) do
love.graphics.setColor(255, 0, 0)
love.graphics.print(i, hit.x, hit.y) -- Prints the hit order besides the point.
love.graphics.circle("line", hit.x, hit.y, 3)
love.graphics.setColor(0, 255, 0)
love.graphics.line(hit.x, hit.y, hit.x + hit.xn * 25, hit.y + hit.yn * 25)
end
end
See Also
Other Languages
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