I have an object and want that to appear after ten seconds.
The code is:
function powerup(e)
local rtran
reloj.x=math.random(10,300)
reloj.y=-70
rtran=transition.to(reloj,{time=math.random (130000,140000),y=9000, onComplete=powerup})
end
timer.performWithDelay(30000, powerup,0)
powerup()
function powerup(e)
local rtran
reloj.x=math.random(10,300)
reloj.y=-70
rtran=transition.to(reloj,{time=math.random (130000,140000),y=9000}) -- removed the onComplete
end
-- timer.performWithDelay(delay in milliseconds between function calls,function to call,how many times to call the function?)
-- 1 sec = 1000 milliseconds
timer.performWithDelay(1000, powerup,5)
The code above will call powerup function every 1 second for 5 times. Since you want timer.performWithDelay code to get executed after some time and not from beginning of application start, put it inside a function and call the function as shown below
local function launchAfterSomeTime()
timer.performWithDelay(1000, powerup,5)
end
-- here delay is the delay you want before
-- you call launchAfterSomeTime function
timer.performWithDelay(delay,launchAfterSomeTime,1)
Don't forget to cancel the timers on scene exit if you are using storyBoard or composer API's
Hope this resolves your issue, happy coding!
Related
I'm trying to disconnect a SceneTreeTimer to avoid a function being called on timeout
like this:
extends Node2D
onready var something = $Node2D
var timer
func abort():
timer.disconnect("timeout",something,"queue_free")
timer.emit_signal("timeout")
print("timer=>",timer)
func _ready():
timer=get_tree().create_timer(3)
timer.connect("timeout",something,"queue_free")
...
abort()
And while it does stop the timer from invoking the function
I'm still seeing the timer after aborting it, Output:
timer=>[SceneTreeTimer:1276]
Shouldn't it be something like this since it's time has elapsed?
timer=>[Deleted Object]
SceneTreeTimer unlike Node is a Reference.
If you have a look at the good old class diagram. You are going to see that some classes extend Node others Reference (including Resource) and other extend Object directly.
The classes that extend Reference are reference counted, they won't be deleted as long as you hold (a not WeakRef) reference to them.
While the classes that extend Node use explicit memory management, so they are deleted by calling free or queue_free on them.
Thus, drop the reference once you are no longer using the SceneTreeTimer:
func abort():
timer.disconnect("timeout",something,"queue_free")
timer.emit_signal("timeout")
timer = null
print("timer=>",timer) # null, duh
Godot will still emit the "timeout" signal, and when it does it releases its internal reference. We find this in "scene_tree.cpp" (source):
if (time_left < 0) {
E->get()->emit_signal("timeout");
timers.erase(E);
}
We can also experiment using a WeakRef to get a result similar to the one you expect. However, remember that since Godot is holding a reference internally the timer won't be deleted before its normal timeout.
extends Node2D
onready var something = $Node2D
var timer_ref:WeakRef
func abort():
var timer := timer_ref.get_ref() as SceneTreeTimer
timer.disconnect("timeout",something,"queue_free")
timer.emit_signal("timeout")
func _ready():
var timer := get_tree().create_timer(3)
# warning-ignore:return_value_discarded
timer.connect("timeout",something,"queue_free")
timer_ref = weakref(timer)
abort()
func _process(_delta: float) -> void:
print("timer=>", timer_ref.get_ref())
You should see it change from
timer=>[SceneTreeTimer:1234]
To
timer=>null
After 3 seconds, since that is the argument we gave to create_timer.
Trivia: Here you will get some number where I put "1234", that number is the instance id of the object. You can get it with get_instance_id and you can get the instance from the id with instance_from_id. We saw an example of instance_from_id in FauxBody2D.
You might also find it convenient to create an Autoload where you create, stop, and even pause your timers while keeping a API similar to create_timer, for example see Godot 4.0. how stop a auto call SceneTreeTimer?.
Addendum:
DON'T DO THIS
You might actually mess up with Godot. Since it is reference counted, and we can freely change the count, we can make it release the timer early:
var timer := timer_ref.get_ref() as SceneTreeTimer
timer.disconnect("timeout",something,"queue_free")
timer.emit_signal("timeout")
timer.unreference()
I tested this both on the debugger and on a release export, with Godot 3.5.1, and it didn't crash the game, not output any errors.
For clarity unreference is not the same as free, instead:
reference increases the count by one.
unreference decreases the count by one.
I'm calling unreference to cancel out the internal reference that Godot has.
We can confirm that the timer is being freed, either by using a weak reference or by looking at Godot's profiler. However, Godot has an internal list with references to the timers which are not being cleared properly.
I made this code to test out if the timer loop was being affected by the timers being released early by the above means.
extends Node2D
var can_fire := true
func _process(_delta: float) -> void:
var timer := get_tree().create_timer(60)
# warning-ignore:return_value_discarded
timer.unreference()
if can_fire:
can_fire = false
print("CREATED")
# warning-ignore:return_value_discarded
get_tree().create_timer(2).connect("timeout", self, "fire")
func fire() -> void:
print("FIRED")
can_fire = true
You might expect it to output FIRED each couple seconds. However, what I found out is that by using unreference on unrelated timers, we get the others to fire much faster.
My hypothesis is that Godot is keeping the dead reference in its internal list, then when another timer is allocated it takes the same memory. Then the timer counts faster because it appears multiple times in the list.
Removing unreference results in the expected behavior.
It does seem to exist still because calling "disconnect" function won't automatically free itself. Try doing timer.stop() instead.
what the function does is deviding the numertor with the denomirator and updates the app's text view accordingly after every second, the problem is that it doesn't update the screen its just simply shows the original number of the numerator that is 60.
what do I change in order to make this work?
fun division() {
val numerator = 60
var denominator = 4
repeat(4) {
Thread.sleep(1_000)
findViewById<TextView>(R.id.division_textview).setText("${numerator / denominator}")
denominator--
}
}
Because you are setting (basically overwritting) the text everytime it loops through, you will only see the value of the last increment which would be 60/1 and that's why you are only seeing 60 value. Try like this:
fun division() {
val numerator = 60
var denominator = 4
repeat(4) {
Thread.sleep(1_000)
findViewById<TextView>(R.id.division_textview).append("${numerator / denominator}\n")
denominator--
}
}
setText() was overwriting the text with the new one but append() is gonna keep the previous text.
This is that dang Codelab again isn't it? I knew it looked familiar... I already answered a similar question here - but basically, when you run division on the main thread (which you must be since you're messing with UI components), you're freezing the app because you're blocking the thread with Thread.sleep
The display can't actually update until your code has finished running, i.e. after you exit the division function, because it's all running on the same thread, and the display update pass comes later. So this is what's actually happening:
freeze the app for 1 second
set the text as the result of 60 / 4 - it won't actually redraw until later, after your code has finished, so there's no visual change
freeze the app for 1 second
set the text as the result of 60 / 3 - again you won't see anything happen yet, but now it's going to show 60 / 3 instead of 60 / 4, because you just updated the state of that TextView
etc.
The last text you set is the result of 60 / 1, and then your code finishes, so the system can finally get around to updating the display. So the first thing you see after the app stops freezing is 60 - it's not just the numerator, it's the last calculation from your loop.
If you want something to update while the app is running, there are lots of solutions like coroutines, CountdownTimers, posting runnables that execute at a specific time, etc. The answer I linked shows how to create a separate thread to run basically the same code on, so you can block it as much as you like without affecting the running of the app. The one thing you don't do is block the main thread like that Codelab example does. It's a bad Codelab
You can use delay and then call from a coroutine:
private suspend fun division() {
val numerator = 60
var denominator = 4
repeat(4) {
delay(1000)
findViewById<TextView>(R.id.division_textview).text = "${numerator / denominator}"
denominator--
}
}
Then from your Activity/Fragment:
lifecycleScope.launch {
division()
}
I'm making a shooting game with solar 2d, everything was working fine but after some time I feel that the games frame rate is dropping, but I did steps to delete my laser when the task finishes
local function fireLaser()
audio.play( fire sound )
newLaser = display.newImageRect( mainGroup, objectSheet, 5, 14, 40 )
physics.addBody( newLaser, "dynamic", { isSensor=true } )
newLaser.isBullet = true
newLaser.myName = "laser"
newLaser.x = ship.x
newLaser.y = ship.y
newLaser:toBack()
transition.to( newLaser, { y=400, time=500,
onComplete = function()display.remove( newLaser ) end
} )
end
I think what is happening, that onComplete calls the display.remove( newLaser ) after 600ms but the function again called but in less than 600ms , say 400ms, so display.remove( newLaser ) dump the first object which is called on first clicked and remove the second one or say latest one, but if the player continuously clicking the fire laser button, and each click has a difference of less than 600 ms, then nothing would be removed. Please Help me as soon as possible.
If you are only using newLaser inside of fireLaser you should define it as a local variable.
This will seem like a insignificant change, but when you do
onComplete = function() display.remove(newLaser) end
you are creating a enclosed function.
When a function is written enclosed in another function, it has full access to local variables from the enclosing function; this feature is called lexical scoping. Although that may sound obvious, it is not. Lexical scoping, plus first-class functions, is a powerful concept in a programming language, but few languages support that concept. - Programming in Lua: 6.1 – Closures
This does not work when newLaser is global because each call to fireLaser is acting on the same global variable of newLaser rather than a unique local variable.
I have written an application to show GPU/CPU/RAM loads in electron.js! It was all ok until I started implementing gauges to graphically display temperatures. This section is shown below, I have also included a screenshot of task manager showing hundreds of command and powershell windows!
function getGPUtempHome(){
let stinker = si.graphics();
stinker.then(function(tempGPU){
GPUtempHome = tempGPU.controllers[0].temperatureGpu;
console.log(GPUtempHome);
document.getElementById("GPUtemps").innerHTML = GPUtempHome+'°';
document.documentElement.style.setProperty('--GPUTEMP', GPUtempHome*1.8 + 'deg');
});
setInterval( function() {getGPUtempHome();}, 5000 );
}
function getRAMhome(){
let stinker3 = si.mem();
stinker3.then(function(RAM){
RAMUSAGE = Math.round(((RAM.used/RAM.total)*100));
console.log(RAMUSAGE);
document.getElementById("RAMloads").innerHTML = RAMUSAGE+'%';
document.documentElement.style.setProperty('--RAMLOAD', RAMUSAGE*1.8 + 'deg');
});
setInterval( function() {getRAMhome();}, 5000 );
}
The code above fetches RAM load or GPU temperature every 5 seconds, it then updates a HTML/CSS gauge.
If writing a program like this is unviable in electron.js are there any other better options out there, I am open to playing around with new languages/libraries.
Remember, setInterval() sets a recurring timer, so your code is basically saying "Every five seconds create another timer for every five seconds." After ten seconds you will have 2 timers. After 20 you now have 8. After 60 seconds you have 4,096 of them. Every 5 seconds the number of timers doubles.
That sounds like a problem, doesn't it?
What you want to do is set one timer, once, per function:
function getRAMhome(){
let stinker3 = si.mem();
stinker3.then(function(RAM){
RAMUSAGE = Math.round(((RAM.used/RAM.total)*100));
console.log(RAMUSAGE);
document.getElementById("RAMloads").innerHTML = RAMUSAGE+'%';
document.documentElement.style.setProperty('--RAMLOAD', RAMUSAGE*1.8 + 'deg');
});
}
// Set timer outside of the function
setInterval(getRAMhome, 5000);
It's a common problem to confuse setInterval() which sets a repeating timer with setTimeout() which sets a one-shot timer that needs to be re-engaged. You're treating the former like the latter, with disastrous consequences.
The worldserver source code is full of Update methods that take as input a diff integer value:
How does it work?
And how is this linked to the "Update time diff" from the .server info command?
To fully understand how this works, it's necessary to have a look at the main World run process.
WorldRunnable::run()
File: src/server/worldserver/WorldThread/WorldRunnable.cpp
The method void WorldRunnable::run() is the "Main heartbeat for the World". This method runs the whole world process.
Inside it, there is a while loop that runs as long as the world is supposed to keep running:
void WorldRunnable::run()
{
uint32 realCurrTime = 0;
uint32 realPrevTime = getMSTime();
///- While we have not World::m_stopEvent, update the world
while (!World::IsStopped())
{
++World::m_worldLoopCounter;
realCurrTime = getMSTime();
uint32 diff = getMSTimeDiff(realPrevTime, realCurrTime);
sWorld->Update( diff );
realPrevTime = realCurrTime;
uint32 executionTimeDiff = getMSTimeDiff(realCurrTime, getMSTime());
devDiffTracker.Update(executionTimeDiff);
avgDiffTracker.Update(executionTimeDiff > WORLD_SLEEP_CONST ? executionTimeDiff : WORLD_SLEEP_CONST);
// ... some more code here
}
// at this point the world process is terminating
// ... some more code here
What this loop really does is basically:
1) calculate the elapsed time (in milliseconds) since the previous iteration, this will be the diff
2) call the sWorld->Update( diff ); function, that contains all the world process logic (see below) and passing the diff to it
3) calculate how much time it took to run sWorld->Update( diff ); and update the devDiffTracker and its average avgDiffTracker. These values will be displayed by the .server info command.
World::Update(uint32 diff)
File: src/server/game/World/World.cpp
The World::Update(uint32 diff) function gets constantly called by the main worldserver loop process and every time it takes in input the amount diff of elapsed time since the last call.
This function is responsible for constantly updating the world, this is where all the magic happens.
Timers
There are a set of timers (defined in World.h that are being updated within the World::Update function:
/// Timers for different object refresh rates
enum WorldTimers
{
WUPDATE_AUCTIONS,
WUPDATE_WEATHERS,
WUPDATE_UPTIME,
WUPDATE_CORPSES,
WUPDATE_EVENTS,
WUPDATE_CLEANDB,
WUPDATE_AUTOBROADCAST,
WUPDATE_MAILBOXQUEUE,
WUPDATE_PINGDB,
WUPDATE_5_SECS,
WUPDATE_COUNT
};
For example, WUPDATE_AUTOBROADCAST is responsible for the period global messages defined in the acore_auth.autobroadcast table.
Tasks
The World::Update function also takes care of many timed-tasks, for example:
/// Handle daily quests reset time
if (m_gameTime > m_NextDailyQuestReset)
ResetDailyQuests();
Calling Update(diff) functions of Managers
In AzerothCore there are singleton classes called Managers (Mgr) that handle specific parts of the game. For example BattlegroundMgr handles the Battlegrounds (BGs).
Those classes have their own Update(uint32 diff) functions and they are called by World::Update that passes down the diff to them, for example:
sBattlegroundMgr->Update(diff);
sOutdoorPvPMgr->Update(diff);
sBattlefieldMgr->Update(diff);
/// ... there are more!
OnWorldUpdate hook
Last but not least, it calls sScriptMgr->OnWorldUpdate(diff);.
This is part of the AzerothCore Module System, and defines a hook that can be used by third-part modules to attach custom logic to the World::Update function.