How to connect LoveFrames components to changes made in love.update - lua

I'm building a Love2D project and using LoveFrames as the UI library. I'm having trouble hooking components into changes that happen in love.update closure. For example, if a count variable is updated in love.update, I want the updated count to show in a frame's title.
So below are snippets that show what I'm trying to achieve.
main.lua
local loveframes =  require("libraries.loveframes")
local Home = require("screens.Home")
availablePlayersCount = 0
function love.load()   
Home(loveframes)
end
Home.lua
function HomeScreen(loveframes)
local frame = loveframes.Create("frame")
frame:SetName(availablePlayersCount) -- This should update with respect to updates made in love.update
frame:SetState("homestate")
loveframes.SetState("homestate")
end

Related

Running "RecomputeTargetPath()" causes Garry's Mod to crash

So I have been coding a nextbot in Gmod for a while now and have found a bug that causes Gmod to crash every time the function is run. here is the function:
function ENT:RecomputeTargetPath(path_target)
if self.testmode then
PrintMessage(HUD_PRINTTALK, 'recomputing target path')
end
self.path = Path("Chase")
if (CurTime() - self.LastPathingInfraction < 5) then
return
end
local targetPos = path_target:GetPos()
-- Run toward the position below the ENTity we're targetting, since we can't fly.
trace.start = targetPos
trace.filter = self:GetEnemy()
local tr = util.TraceEntity(trace, self:GetEnemy())
-- Of course, we sure that there IS a "below the target."
if (tr.Hit and util.IsInWorld(tr.HitPos)) then
targetPos = tr.HitPos
end
local rTime = SysTime()
self.path:Compute(self, targetPos)
if (SysTime() - rTime > 0.005) then
self.LastPathingInfraction = CurTime()
end
end
When this function is run, it recomputes the target path for the nextbot to make it move differently.
It's used in the context of an if that looks like this or something very close:
if (CurTime() - self.LastPathRecompute > 0.1) then
self.LastPathRecompute = CurTime()
self:RecomputeTargetPath(self:GetEnemy():GetPos())
end
As far as I know, all variables in the if are called before each.
As far as I know, all variables in the if are called before each.
I tried recalling them but that didn't work at all... I don't know what is happening.
Also, side note, the function gets called multiple times per second based on the player's movement.
I've also added debug prints to every line of the code to see where the issue was and the bug fixed itself when I added them but when I removed them the bug came back...
Any help?

StarterGui elements still appearing when set to invisible

I'm trying to use the PlayerAdded to make a screen gui disappear and make another one appear. It makes both guis appear though. I also am trying to make the player not spawn in when they join the game and that doesn't work either.
game.Player.CharacterAutoLoads = false
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
game.StarterGui.StartScreenFrame.Visible = true
game.StarterGui.PlayGui.Visible = false
end)
Take a look at the documentation for StarterGui.
When a Players’ character respawns, the contents of their PlayerGui is emptied. Children of the StarterGui are then copied (along with their descendants) into the
PlayerGui.
Stuff in the StarterGui acts as a template. The actual labels that show up on a player's screen are found in the player's PlayerGui. Your code is modifying the template, not the elements that are cloned to the PlayerGui.
Normally, to fix your problem, you would just need the correct paths to the UI elements. But you have a complicating factor, you've specified that game.Players.CharacterAutoLoads = false. This means that stuff in the StarterGui doesn't get cloned into the PlayerGui until the player's character spawns.
So I would recommend a few things :
Move your UI Elements into ReplicatedStorage, this will prevent UI element duplication when you eventually tell your character to spawn into the world.
Clone the elements into each player's UI manually. This will make the UI elements show up.
Configure the cloned elements. This way you can script the UI behaviors yourself.
And then update your Script like this :
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- get a reference to the UI templates
local startScreen = ReplicatedStorage.StartScreenFrame
local playScreen = ReplicatedStorage.PlayGui
-- disable character's auto loading
Players.CharacterAutoLoads = false
-- listen for when players first join the game
Players.PlayerAdded:Connect(function(player)
-- add the UI Elements to the PlayerGui
local startGui = startScreen:Clone()
startGui.Visible = true
startGui.Parent = player.PlayerGui
local playGui = playScreen:Clone()
playGui.Visible = false -- enable this later
playGui.Parent = player.PlayerGui
end)
Be aware that because you are manually placing UI Elements into the PlayerGui, you should be careful that when a Player dies and respawns, their PlayerGui will be cleared. You can avoid this by setting the ResetOnSpawn property to false on each ScreenGui.

How do I make this code function correctly?

I want to make a sort of Lobby system in Roblox Studio where if you have 4 people on a part you get sent to another place. I tried to set up a system for it, but it didn't work; can you help me through this?
I've tried making it so it says .Value at the end.
local TeleportService = game:GetService("TeleportService")
player_amount = script.Parent.Parent.Parent.Player_Count
local placeID_1 = 4119652438
local function onPartTouch(otherPart)
local player = game.Players:GetPlayerFromCharacter(otherPart.Parent)
if player then
player_amount.Value = player_amount.Value + 1
end
if player_amount == 4 then
TeleportService:Teleport(placeID_1, player)
end
end
script.Parent.Touched:Connect(onPartTouch)
I expected the output to be 0 then if one person steps on it, it would update the sign to say 1. But it only stays at 0.
This is not a viable solution as .Touched fires every frame the player touches a part, and only when they move. I suggest creating a hitbox, as I have done here

ROBLOX Studio function to call function for each door to open

I'm pretty new to ROBLOX development and don't really know how to make the objects talk just yet.
I have 16 cells all with an individual open and close button. Those work. I want to create a button that will open all doors at once.
function onClicked()
script.Parent.Parent.Door.Transparency = 1
script.Parent.Parent.Door.CanCollide= false
end
script.Parent.ClickDetector.MouseClick:connect(onClicked)
The above function is on each cell and works. I would like to loop through each one and fire it when I click a different button. I've been looking into getting each object with the same names but haven't been able to iterate through it.
The below code is my attempt to get it to fire off each one!
local part = workspace.OpenButton
local clickDetector = Instance.new("ClickDetector")
local function onMouseClick(player)
for _, child in pairs(workspace.PrisonCell:GetChildren()) do
print(child)
child:connect(child.Door.onClicked)
end
end
clickDetector.Parent = part
part.Parent = workspace
clickDetector.MouseClick:connect(onMouseClick)
Any help with this would be greatly appreciated!
You could do something similar to this to open all of the prison doors at once:
local part = workspace.OpenButton
local clickDetector = Instance.new("ClickDetector")
local function onMouseClick(player)
for _, child in pairs(workspace.PrisonCell:GetChildren()) do
child.Door.Transparency = 1
child.Door.CanCollide = false
end
end
clickDetector.Parent = part
part.Parent = workspace
clickDetector.MouseClick:connect(onMouseClick)
The downside to using the solution above is that if you want to change the door opening script, you would have to change it in both the individual cell buttons as well as this master button script. If you think this might be a problem in the future, I would consider writing a master script somewhere in ServerScriptService that uses BindableEvents for communcation with the button clicking scripts in order to keep the door opening function in one place.

using the ui library while iterating over a table in coronaSDK

In CoronaSDK, I'm trying to make a certain code that creates a lot of buttons and plays sounds for each of those buttons more "efficient" by first creating a table of strings and then creating the buttons and handlers by iterating over the table. I'm using the common "ui.lua" file to create buttons. However, I get (at least) two errors. The first is that the newButton fcn says it's expecting a table value for "default." Here's the code:
--create the array. Note that these names will be used for all the objects that refer to these things, so you must have a consistent naming convention
local instruments = {"snare","piano1", "piano2","guitar1","guitar2","softPiano"}
--set constants to be able to set the x value of the buttons
local h = display.contentWidth/6-25;
local multiplier = 1
--loop through each item in the array to: (a) load the sound, (b) create a btn press event, and (c) create the button
for k,v in pairs(instruments) do
--first, we use the value to make some reference strings
img = "images/"..v.."_btn.png"
sound = "media/"..v..".wav"
--now create the event listener
local playThis = function (event)
audio.play(sound)
end
--now create the button
local thisInstrument = ui.newButton{
default = img,
onPress = playThis
}
thisInstrument.x = h*multiplier
thisInstrument.y = display.contentHeight * .8
multiplier = multiplier + 1
end
When I change the value of default to a straight up string, the buttons are at least created and displayed as expected across the screen.
local thisInstrument = ui.newButton{
default = "images/snareDrum_btn.png",
onPress = playThis
}
Of course, the sound still doesn't play when I click a button. So, two questions: First, why won't a simple reference to default = img work? Second, how do I get the listener to work for each new button?
Ok, so I found the answer. I made a couple of stupid rookie mistakes. The reason the local variable wasn't working had nothing to do with my code. It was actually because I had misnamed a couple of the image files (doh!).
Second, the button listener wasn't working because (drumroll...) I had forgotten to load the audio files ahead of time (double doh!). I ended up deciding to place the playThis function outside the loop so that it wasn't being recreated unnecessarily. Instead, I set a "sound" property on the created buttons and used the event argument to figure out which button was pushed and play the corresponding sound.
Here's the final code (I've modularized it to make it more re-usable). Hopefully, this'll be a lesson for others in checking your entire environment before banging your head about your code.
--init globals
_H = display.contentHeight;
_W = display.contentWidth;
--test to see if I can more efficiently write code to do a repeated action by placing items inside an array and looping through the array
--import the ui file to create buttons
local ui = require("ui")
--create the array. Note that these names will be used for all the objects that refer to these things, so you must have a consistent naming convention
local instruments = {"snare","piano1", "piano2","guitar1","guitar2"}
--set constants to be able to set the x value of the buttons
local function doThis (event)
audio.play(event.target.property)
end
--loop through each item in the array to: (a) load the sound, (b) create a btn press event, and (c) create the button (the event must be created before the listener, else it has nothing to listen for)
local function makeBtns(btnList,btnImg,property,groupXPos,groupYPos)
--first, let's place all the buttons inside a button group, so we can move them together
local thisBtnGroup = display.newGroup();
for index,value in ipairs(btnList) do
--first, we use the value to make some reference strings
local img = "images/base_btn.png"
property = audio.loadSound("sounds/"..value..".wav")
--now create the button
local thisBtn = ui.newButton{
default = img,
onPress = doThis,
text = value,
size = 10
}
thisBtnGroup:insert(thisBtn)
thisBtn.x = (index -1) * thisBtn.width
thisBtn.property = property
end
thisBtnGroup.x = groupXPos; thisBtnGroup.y = groupYPos
return thisBtnGroup
end
local myBand = makeBtns(instruments,"images/base_btn.png","sound",_W/3,_H-50)

Resources