I modified the box stacking demo to include raycasting.
I added comments to all the parts which are there to support the raycasting:
sync on : sync rate 60
set display mode desktop width(), desktop height(), 32, 1
b2SetScale 100, 180.0/3.1415926535, 1, 10000
b2SetScreenTransform 0, 0, 1, 0
global world as integer
world = b2CreateWorld(0, 2000, 1)
load image "box.png",1,1
load image "crate.jpg",2,1
centerX = screen width()/2
groundBody = CreateStaticBox(centerX, screen height()-30, 998, 38, 1)
boxSize = 30
boxScale# = boxSize/110.0
for i = 1 to 15
x = screen width()/2 - 19*50/2
y = screen height()-50-i*(boxSize+1) + boxSize/2
for j = 1 to 20
boxBody = CreateDynamicBox(x, y, boxSize, boxSize, 2, boxScale#)
inc x, 50
next j
next i
mouseJoint = 0
ink 0,0
drawShapes = 1
drawJoints = 1
drawAABBs = 0
drawPairs = 0
drawCenters = 1
drawDebug = 0
` Some globals for storing information about the ray cast
global rayCastFixture as integer
global rayCastX as float
global rayCastY as float
global rayCastNX as float
global rayCastNY as float
` Tell Box2D to use the function "RayCastCallback" as the raycast callback
b2SetRayCastCallback get ptr to function("RayCastCallback")
do
b2SetDebugDraw drawShapes, drawJoints, drawAABBs, drawPairs, drawCenters
` Reset global variables
rayCastFixture = 0
rayCastX = mousex()
rayCastY = mousey()
` Cast a ray from 0, 0 to the mouse position
b2RayCastWorld world, 0, 0, mousex(), mousey()
` Draw the line of the ray-cast
line 0, 0, rayCastX, rayCastY
` If there was a hit, draw the normal
if rayCastFixture then line rayCastX, rayCastY, rayCastX+rayCastNX*30.0, rayCastY+rayCastNY*30.0
oldi$ = i$
i$ = inkey$()
if oldi$ = ""
select i$
case " "
drawDebug = 1-drawDebug
endcase
case "1"
drawShapes = 1-drawShapes
endcase
case "2"
drawJoints = 1-drawJoints
endcase
case "3"
drawAABBs = 1-drawAABBs
endcase
case "4"
drawPairs = 1-drawPairs
endcase
case "5"
drawCenters = 1-drawCenters
endcase
endselect
endif
omc = msc
msc = mouseclick()
msd = msc-omc
msx = mousex()
msy = mousey()
if msd = 1
fixture = b2PickFixture(world, msx, msy, 1)
if fixture
body = b2GetFixtureBody(fixture)
mouseJoint = b2CreateMouseJoint(world, groundBody, body, msx, msy, 1)
b2SetMouseJointMaxForce mouseJoint, b2GetBodyMass(body)*500000
endif
endif
b2StepWorld world, 1.0/60.0
b2DrawWorld world, drawDebug
if mouseJoint
b2SetMouseJointTarget mouseJoint, msx, msy
line b2GetJointAnchorAX(mouseJoint), b2GetJointAnchorAY(mouseJoint), b2GetJointAnchorBX(mouseJoint), b2GetJointAnchorBY(mouseJoint)
if msc = 0
b2DeleteJoint mouseJoint
mouseJoint = 0
endif
endif
print "Screen FPS: ", screen fps()
print "Body Count: ", b2GetWorldBodyCount(world)
print "Space - Show debug info"
if drawDebug
print "[1] - Toggle shapes"
print "[2] - Toggle joints"
print "[3] - Toggle AABBs"
print "[4] - Toggle pairs"
print "[5] - Toggle centres"
endif
sync
cls 0xFFFFFFFF
loop
global pickedFixture as integer
global pickX as float
global pickY as float
function CreateStaticBox(x, y, w, h, imageId)
shape = b2CreatePolygonShapeAsBox(w, h)
body = b2CreateBody(world, b2BodyType_Static(), x, y)
fixture = b2CreateFixture(body, shape, 1)
b2SetBodyImage body, imageId
endfunction body
function CreateDynamicBox(x, y, w, h, imageId, imageScale#)
shape = b2CreatePolygonShapeAsBox(w, h)
body = b2CreateBody(world, b2BodyType_Dynamic(), x, y)
fixture = b2CreateFixture(body, shape, 1)
b2SetBodyImage body, imageId, imageScale#
endfunction body
` This function will be called for every fixture intersecting the ray
` in no particular order
function RayCastCallback(fixture, x#, y#, nx#, ny#, f#)
` f# is how far along the ray this fixture is.
` The return value of this function is an amount
` by which to shorten the ray. If f# is a half
` (half-way along the ray) it will be returned
` and the ray will be shortened by a half. This
` means that each fixture passed must be closer
` than the previous one.
rayCastFixture = fixture
` MUST FIX: Currently X and Y are not scaled by the linear scale factor set using
` b2SetScale, so must be scaled manually (in this case by 100).
rayCastX = x#*100
rayCastY = y#*100
rayCastNX = nx#
rayCastNY = ny#
endfunction f#
As you can see, the use of callbacks makes it slightly complicated, but it's necessary in order to keep both the functionality and the performance.
I tried to explain the use of 'f#' in the callback as best I could, but if you're confused I could draw a diagram or something.
[b]