Capricorn 76
Raycasting example.
Raycasting can be performed using either the graphics or physics engines.
We cast a ray into the ScriptENGINE world and find out what is hit.
Great for line-of-sight calculations, or mouse-selecting entities.

---------------------------
---------------------------
-- Raycasting example
-- Copyright (c) 2007-09 Capricorn 76 Pty. Ltd.
--
-- Raycasting can be performed using either the graphics or physics engines.
-- We cast a ray into the ScriptENGINE world and find out what is hit.
-- Great for line-of-sight calculations, or mouse-selecting entities.
--
-- The graphics engine raycasts graphical entities (things we can see).
-- The physics engine raycasts physical entities (things with a mass).
--
-- The physics engine returns a more detailed result than the graphics engine.
--
-- NOTE:
-- The ./Demos/runDemo.e76script is a utility script used to run all the examples.
-- It loads the world, calls the OnWorldLoad(), OnWorldUnload() functions, and runs the graphics engine loop, waiting for the user to press escape.
---------------------------
---------------------------

local subMouse;

---------------------------
-- runDemo.e76script calls this function when the world is loaded
---------------------------
function OnWorldLoad(worldName)
    --print('OnWorldLoad');

    ---------------------------
    -- The SDK world editor creates a worldIds.e76script when the world is saved. It contains all the entity ids.
    -- We load the IDs so that we can refer to the world entities using friendly names.
    ---------------------------
    IApp:loadScript(IWorld:getNameLong() .. '/worldIds');
    IWorld:setActiveCameraId(idCamera_cam1);

    ---------------------------
    -- Load this example's GUI
    ---------------------------
    OnWorldLoadGui();

    ---------------------------
    -- Expand the physical world bounds a bit.
    -- This is the zone within which the physics engine simulates its entities.
    -- It defaults to a zone that just surrounds the world entities.
    -- But because the boxes are going to be flying about, we expand it.
    ---------------------------
    IPhysics:expandBounds('-100 -100 -100', '100 100 100');

    ---------------------------
    -- Subscribe to the mouse button events.
    -- The graphics engine will call our callback function
    -- whenever the user clicks a mouse button.
    -- We can handle these mouse clicks to perform a raycast.
    ---------------------------
    subMouse = IEvents:subscribeMouseButton('OnMouseButton');
end

---------------------------
-- Load example's GUI
---------------------------
function OnWorldLoadGui()
    IGraphics:loadGui('help');
end

---------------------------
-- runDemo.e76script calls this function when the world is unloaded
---------------------------
function OnWorldUnload(worldName)
    --print('OnWorldUnload');

    ---------------------------
    -- Unsubscribe to events.
    -- We will no longer be notified of any mouse button clicks.
    ---------------------------
    IEvents:unsubscribe(subMouse);
    ISound:unload('shoot');
end

---------------------------
-- Mouse button event handler.
-- The graphics engine will call this function whenever
-- the user clicks a mouse button.
---------------------------
function OnMouseButton(eventType, mouseX, mouseY, mouseWheel, userData)

    ---------------------------
    -- If the user clicked the left-mouse button then do a raycast and see what we hit.
    -- We filter what entities we are interested in. We only want units. Not things like waypoints, agents, etc.
    -- You can raycast in any direction, from any starting position. But we're going to use the mouse position and use the mouse raycast function.
    ---------------------------
    if (IMouse:leftButtonClicked(eventType)) then
        result = IPhysics:rayCastMousePositionFilter(IWorld:getUnitTypeId());

        ---------------------------
        -- Did we hit something?
        ---------------------------
        if (result) then

            boxId           = result['entity'];
            intersection    = result['intersection'];

            -- Calculate a force vector. This is just a vector from our position to the intersection point.
            ourPosition     = IWorld:getEntityPosition(IWorld:getActiveCameraId());

            forceVector = IMisc:vectorSubtract(intersection, ourPosition);

            -- Normalise the vector. This makes its magnitude = 1 (ie. we scale it, still points in the same direction)
            forceVector = IMisc:vectorNormalise(forceVector);

            -- Rescale it to a larger force
            forceVector = IMisc:vectorMultiply(forceVector, 5);

            -- Apply the force to the entity at the intersection point
            intersectionOffset = IMisc:vectorSubtract(intersection, IWorld:getEntityPosition(boxId));
            IPhysics:addEntityImpulseForceOffset(boxId, forceVector, intersectionOffset);

            -- Play a sound just for fun
            if (not(ISound:soundExists('shoot'))) then
                if (ISound:load('shoot', '../Resources/sfx.wav', false)) then   -- This sound is stereo, and therefore is played in 2D by the engine (nb: use mono sounds for 3D)
                    ISound:setVolume('shoot', 1);
                end
            end

            if (ISound:soundExists('shoot')) then
                ISound:play('shoot');
            end
        end
    end

end

Copyright © 2006-23 Sep 2009 Capricorn 76 Pty. Ltd. (created on Wed Sep 23 16:49:12 2009)