Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

Changing the velocity of a part according to its impacted surface (like light)?

Asked by 8 years ago

Right now I have the stock Hyperlaser; I'm trying to make the shot, on impact with a surface, change its velocity according to the angle of the shot relative to the surface impact, without changing its velocity.

The simplest example would be how light reflects off a completely reflective surface; that' the effect I'm trying to get here. I've tried tons of different code snippets that reflect in strange and bizarre ways.

How could I do this?

1 answer

Log in to vote
0
Answered by
legosweat 334 Moderation Voter
8 years ago

This would be a good use of the Dot Product The dot product, also commonly known as the scalar product, is an operation preformed on vectors and returns a single number.

Example pulled from article:

local tool = script.Parent; -- the Tool
local handle = tool:WaitForChild("Handle"); -- does not continue without a Handle!

function reflect(input, normal) -- this vector reflector will reflect the laser 
    -- using dot method b/c vector3
    return -2 * input:Dot(normal) * normal + input; 
end;

function drawray(ray, parent) -- draws the ray of the laser
    local part = Instance.new("Part", parent or game.Workspace.CurrentCamera); -- do only you can see the lasers
    part.FormFactor = Enum.FormFactor.Custom;
    part.Material = Enum.Material.Neon; -- glowy effect c:
    part.Size = Vector3.new(.2, ray.Direction.magnitude, .2);
    part.CFrame = CFrame.new(ray.Origin + ray.Direction/2, ray.Origin + ray.Direction) * CFrame.Angles(math.pi/2,0,0);
    part.Anchored = true;
    part.CanCollide = false;
    part.BrickColor = BrickColor.new("Bright red");
    return part;
end;

function fire(from, to, bounce) -- function that fires the laser
    local bounce = bounce or 0;
    if bounce <= 5 then -- how many times can it reflect
        -- first ray is to calculate distance and normal
        local ray = Ray.new(from, (to - from).unit * 500);
        local hit, pos, normal = game.Workspace:FindPartOnRay(ray, tool.Parent);

        -- this is the actual ray we use and draw
        local ray2 = Ray.new(from, (pos - from));
        local part = drawray(ray2, tool);

        -- throw out the laser beam later
        game:GetService("Debris"):AddItem(part, 2);

        -- calculate the reflected ray
        local ref = reflect((pos - from), normal);
        if hit then
            local hum = hit.Parent:FindFirstChild("Humanoid");
            if hum then
                hum:TakeDamage(math.random(10, 15));
            end;
            -- shoot a ray in the reflected position
            fire(pos, pos + ref, bounce + 1);
        end;
    end
end;

script.Parent.Equipped:connect(function(mouse) -- connect the function to when the tool is equipped
    mouse.TargetFilter = game.Workspace;
    script.Parent.Activated:connect(function() -- whenever the player clicks with the tool out
        fire(handle.CFrame.p, mouse.Hit.p); -- call the function
    end);
end);
Ad

Answer this question