Jump to content

Lua Leadwerks 5 Tutorial - Adding prompt for usable objects in fps controller


In this tutorial will be used Tile, Camera:Pick() and Entity:GetDistance

FPSPlayer component of FPS Template will be used as a base to modify

Algorithm:

1. Create a Tile with text prompt

2. In Update function of component check if player look at usable object at close distance

3. if the check is passed then show prompt at center of screen

Result will looks like that:

LuaFPSUsePrompt.thumb.png.cc129a76a1c97bad348dc3b02814c2d4.png

Let's implement this Algorithm:

1. Add new component variable, for example after:

FPSPlayer.movement = Vec3(0)

New code line:

FPSPlayer.usePromtTile = nil

Now in FPSPlayer:Load() function after:

    if not self.camera then
        self.camera = CreateCamera(world)
        self.camera:Listen()

Add:

local font = LoadFont("Fonts/arial.ttf")
self.usePromtTile = CreateTile(self.camera, font, "Press E", 20, TEXT_CENTER, 1.5)

This overload used (more short one for text currently not available when tutorial is written): 

CreateTile(Camera camera, Font font, string text, number fontsize, number alignment, number linespacing)

Tile is something like mini GUI widget which can be used to show text or rectangles without creating Interface.

 

2 and 3. Inside of FPSPlayer:Update() in  "if window then" scope before its end (after 392th line) add:

        --to decide later if we want to show or hide prompt tile
        local doHideTile = true
        --cx and cy are screen center coordinates which were created above
        local pickInfo = self.camera:Pick(framebuffer, cx, cy, 0, true)
        if pickInfo.success and pickInfo.entity and pickInfo.entity:GetDistance(self.entity) < 2.0 then
            --iterate all components of picked entity
            for _, component in ipairs(pickInfo.entity.components) do
                --find out if component of picked entity have Use function and it's enabled
                if component.Use and type(component.Use) == "function" and component:GetEnabled() then
                    --move tile to center of screen
                    self.usePromtTile:SetPosition(cx, cy)
                    doHideTile = false
                    --stop iterating once we found usable object
                    break
                end
            end
        end
       self.usePromtTile:SetHidden(doHideTile)

Result file: FPSPlayer.lua

  • Like 4
  • Thanks 2

9 Comments


Recommended Comments

Qulex3

Posted

            for _, component in ipairs(pickInfo.entity.components) do
                --find out if component of picked entity have Use function and it's enabled
                if component.Use and type(component.Use) == "function" and component:GetEnabled() then
                    --move tile to center of screen
                    self.usePromtTile:SetPosition(cx, cy)
                    doHideTile = false
                    --stop iterating once we found usable object
                    break
                end
            end

How can I adapt these codes to C++?
 

Dreikblack

Posted

15 minutes ago, Qulex3 said:

How can I adapt these codes to C++?

//to decide later if we want to show or hide prompt tile
bool doHideTile = true;
//cx and cy are screen center coordinates which were created above
auto pickInfo = camera->Pick(window->GetFramebuffer(), cx, cy, 0, true, PlayerFilter, GetEntity());
if (pickInfo.success && pickInfo.entity && pickInfo.entity->GetDistance(GetEntity()) < 2.0) {
	//iterate all components of picked entity
	for (auto const& component : pickInfo.entity->components) {
		auto baseCompoent = component->As<BaseComponent>();
		if (baseCompoent && baseCompoent->GetEnabled()) {
			usePromtTile->SetPosition(cx, cy);
			doHideTile = false;
			break;
		}
	}
}
usePromtTile->SetHidden(doHideTile);

Also add somewhere in player class for avoiding picking player entity:

static bool PlayerFilter(std::shared_ptr<Entity> entity, std::shared_ptr<Object> extra) {
	if (entity == extra->As<Entity>()) {
		return false;
	}
	return true;
}

 

Qulex3

Posted

not working, I'm sure I paste the codes in the right place.  and i tried it on the sliding door component, because has Use() function.
 

burgelkat

Posted

it works , but what is , if its an Pivot with script that loads a model that i can use. then the tile is not visible. How can i fix that? 

 

i try this : 

    local doHideTile = true
    local pickInfo = self.camera:Pick(framebuffer, cx, cy, 0, true)
    if pickInfo.success and pickInfo.entity and pickInfo.entity:GetDistance(self.entity) < 3.0 then
        local ent = pickInfo.entity
        while ent do
            if ent.components then
                for _, component in ipairs(ent.components) do
                    if component.Use and type(component.Use) == "function" and component:GetEnabled() then
                        self.usePromtTile:SetPosition(cx, cy)
                        doHideTile = false
                        break
                    end
                 end
            end
            if not doHideTile then break end
            ent = ent:GetParent()
        end
    end

    if self.usePromtTile then
        self.usePromtTile:SetHidden(doHideTile)
    end

but dont work

Dreikblack

Posted

6 minutes ago, burgelkat said:

it works , but what is , if its an Pivot with script that loads a model that i can use. then the tile is not visible. How can i fix that? 

Depends how exactly it structured. Is your pivot is usable and it's load a model as a child or pivot loads another model that have own component with Use() function?

burgelkat

Posted

it have his own component with Use() function. I tryed also to put the push button script(as example) at pivot but does not work too . so i think on pivot its not working maybe?

Dreikblack

Posted

Maybe this model does not have a collider? Also make sure pick mode is correct for model and pivot.

Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...