Difference between revisions of "An Event in Time"

From The Official Visionaire Studio: Adventure Game Engine Wiki
m
m
 
(9 intermediate revisions by the same user not shown)
Line 39: Line 39:
 
Did you know that you can edit animation frames via [[File:Anim_editframev2.png|16px|link=]] & assign sounds & actions to each individual animation frame? This is actually a really great method for precision timing based events as they are tied to animation frames instead of the frames per second (fps) that your game is running on each players device. It's much more accurate than using the pause action part.
 
Did you know that you can edit animation frames via [[File:Anim_editframev2.png|16px|link=]] & assign sounds & actions to each individual animation frame? This is actually a really great method for precision timing based events as they are tied to animation frames instead of the frames per second (fps) that your game is running on each players device. It's much more accurate than using the pause action part.
  
[[File:Vs_anim_frame_actions.png|800px]]
+
[[File:Vs_anim_frame_actions.png|1070px]]
  
  
 
== Wait Actions ==
 
== Wait Actions ==
  
Some action parts have an additional option called '''wait''', which enabled will tell the engine to pause the action list until the action or animation has finished. These wait options are optional & can also be very useful for controlling the timing of when certain events should occur.
+
Some action parts have an additional option called '''wait''', which when enabled will tell the engine to pause the action list until the action or animation has finished. These wait options are optional & can also be very useful for controlling the timing of when certain events should occur.
  
=== Play Animation and wait ===
+
=== Play Animation and Wait ===
  
 
This will start an animation & pause the action list that you execute this action in until the animation finishes, however you do need to be careful not to use this option on animations that are set to infinite loop as the action list will be paused indefinitely due to the animation never ending.
 
This will start an animation & pause the action list that you execute this action in until the animation finishes, however you do need to be careful not to use this option on animations that are set to infinite loop as the action list will be paused indefinitely due to the animation never ending.
Line 125: Line 125:
 
=== Animations are also Loops ===
 
=== Animations are also Loops ===
  
Yes, you heard me correctly, animations are also loops & can be treated as such. Think about it like this... you have an animation & you can control the amount of loops it does, the duration of each loop, the amount of frames it contains. By inserting actions or code into specific animation frames you now have a method of telling the game when to do something specific x amount of times; or indefinitely if the animation is set to loop infinitely. Checkout [[#Animation Frame Events|animation frame events]] to refresh your memory on how to edit animation frames & add actions/scripts to them.
+
Yes, you heard me correctly, animations are also loops & can be treated as such. Think about it like this... you have an animation & you can control the amount of loops it does, the duration of each loop, & the amount of frames it contains. By inserting actions or code into specific animation frames you now have a method of telling the game when to do something specific x amount of times; or indefinitely if the animation is set to loop infinitely. Checkout [[#Animation Frame Events|animation frame events]] to refresh your memory on how to edit animation frames & add actions/scripts to them.
 
<hr>
 
<hr>
 
{| class="ts"
 
{| class="ts"
Line 256: Line 256:
 
exampleLoop()
 
exampleLoop()
 
  if time == nil then time = getTime({flags=1, reset=true}) else time = getTime() end -- init or update time
 
  if time == nil then time = getTime({flags=1, reset=true}) else time = getTime() end -- init or update time
  if time >= 3000 then -- if time more than or equals time plus 3000ms then
+
  if time >= 3000 then -- if time more than or equals 3000ms then
 
   print("hello world!") -- print "hello world!" to the log
 
   print("hello world!") -- print "hello world!" to the log
 
   time = getTime({flags=1, reset=true}) -- reset time back to 0ms
 
   time = getTime({flags=1, reset=true}) -- reset time back to 0ms

Latest revision as of 16:16, 9 August 2023

On this page you will find a bunch of tips & tricks related to events, loops, & timing methods that you can use to control exactly when specific events &/or state changes (via values/conditions) should occur in your game projects.

Anyway, let's crack on...


Pause (static)

The simplest method for controlling time is to use the pause action part. The pause action part will prevent any action parts created after it from executing until the pause has finished.


Quick note: The pause action part allows you to specify the time in milliseconds, seconds, or minutes; however I highly recommend that you use milliseconds because it allows you to input precise time values.

Anyway, here's an example of the pause action part being used with some other action parts...

1. if condition "cond_example" is true
2. pause for 500 milliseconds
3. change condition "cond_example" to false
4. end if


Pause (dynamic)

The same action part above can also be used to create dynamic pauses, which can be really useful for making your game projects feel more alive & less like a broken record stuck in a never-ending loop.

To setup dynamic pauses you will need to create a value that you can link to the pause action part. The integer number belonging to values can be modified at any time via action parts or script; however we will only be covering action parts for now to keep things as simple as possible.

Anyway, let's just assume you have created a value somewhere inside of the Visionaire Studio editor & have called it "v_time". Right, let's see an example of what a dynamic pause would look like inside of an action block...

1. set random value "v_time" between 1000 and 5000
2. pause for "v_time" milliseconds
3. play animation "anim_example" and wait
4. jump to action part #1


Animation Frame Events

Did you know that you can edit animation frames via Anim editframev2.png & assign sounds & actions to each individual animation frame? This is actually a really great method for precision timing based events as they are tied to animation frames instead of the frames per second (fps) that your game is running on each players device. It's much more accurate than using the pause action part.

Vs anim frame actions.png


Wait Actions

Some action parts have an additional option called wait, which when enabled will tell the engine to pause the action list until the action or animation has finished. These wait options are optional & can also be very useful for controlling the timing of when certain events should occur.

Play Animation and Wait

This will start an animation & pause the action list that you execute this action in until the animation finishes, however you do need to be careful not to use this option on animations that are set to infinite loop as the action list will be paused indefinitely due to the animation never ending.


Wait until Animation is Finished

Same as above, but this action part is meant to be used on an already playing animation. & again be careful not to use this option on animations that are set to infinite loop as the action list will be paused indefinitely due to the animation never ending.


Wait until Sound is Finished

This action part will pause the action list that you execute this action in until the linked sound stops playing, however just like play animation and wait you need to be careful that you don't link to a sound that is looping as the action list will be infinitely due to the sound never ending.


Wait until Condition was Changed

This will pause the current action list until the condition is changed from whatever it currently is or until it's changed to the specified boolean state.


Quick note: There are 3 options available.
1. Changed: wait until condition is changed to the opposite of its current state.
2. True: wait until condition is changed to true.
3. False: wait until condition is changed to false.

Wait until Value was Changed (static)

This will pause the current action list until the specified value target is met.


Wait until Value was Changed (dynamic)

This will pause the current action list until the specified value meets the same target value as the secondary linked value. The reason this method is dynamic is because both values can be manipulated which means that the secondary value could be repurposed for multiple situations.


Quick note: There are multiple operators you can use for querying values, which allows a lot of freedom when it comes to querying values.
= equals.
!= does not equal.
<= less than or equal to.
< less than.
>= greater than or equal to.
> greater than.

Wait until Character Stops Speaking

Pauses the current action list until the specified character stops talking; or just continue executing the action parts if the character wasn't talking to begin with.


Wait until Character Stops

Pauses the current action list until the specified character stops walking; or just continue executing the action parts if the character wasn't walking to begin with.


Send Character to Position/Object and Wait

This is actually 2 different action parts. One will let you send the character to a specified position in the current scene & the other will let you tell the character to walk to the position defined in the specified object. Both have wait options & will pause the action list until the character reaches the position.


Quick note: The destination position isn't what the engine is listening out for, it's actually listening out for when the character stops walking so you may want to use these 2 action parts inside of cutscene wrappers to prevent the player from being able to interrupt the destination position/object by left clicking elsewhere in the scene.

Call/Quit Action and Wait

This action part allows you to call another existing action block. You can optionally tell the current action list to wait until the other action block you call finishes iterating through all the action parts/scripts listed inside of it - I don't know if you can chain this action through multiple action blocks, but maybe one of you want to try it out & let me (AFRLme) know?


Loops

This section is going to get a bit complicated as we are going to start delving into the scripting side of things, as well as some conventional & unconvential methods via action parts & animations.

Animations are also Loops

Yes, you heard me correctly, animations are also loops & can be treated as such. Think about it like this... you have an animation & you can control the amount of loops it does, the duration of each loop, & the amount of frames it contains. By inserting actions or code into specific animation frames you now have a method of telling the game when to do something specific x amount of times; or indefinitely if the animation is set to loop infinitely. Checkout animation frame events to refresh your memory on how to edit animation frames & add actions/scripts to them.


Quick note: The animation could contain images, a single image, blank animation frames, or animation frames linked to a transparent png/webp image file.

Jump to Action Part

The jump to action part action part is one of the methods that you can use for creating loops inside of the Visionaire Studio editor without having to resort to scripting. There are 2 ways that you can use the jump to x action part, which are...


Absolute

This is the option you would probably be using most of the time & it's the simplest method as you simply tell the engine to jump to x action part inside of the current action block. For example #1 would be the first action part in the list aka the top of the list.

Here's a quick example of what the action block might look like...

1. if condition "cond_example" is false
2. pause for 500 milliseconds
3. jump to action part #1 (jump back to first action part)
4. end if
5. display text "hello world" (if condition "cond_example" is true then this would be executed instead)

Relative

The relative mode is a bit more complicated as it involves jumping x amount of steps forwards or backwards & is more situation based.

Here's a little action block example of what it might look like in use...

1. pause for 500 milliseconds
2. if condition "cond_example" is true
3. jump 4 action parts forwards          (0)
4. else                                  (1)
5. jump to action part #1                (2)
6. end if                                (3)
7. display text "hello world"            (4)

The setDelay() Function

The setDelay() function is really useful for controlling when to execute lines of code or functions & it can also be used to create timed based loops.


Syntax

setDelay(delay, function)

Call Existing Function

setDelay(1000, "helloworld()") -- call function helloworld() after 1000ms (1 second)

Execute Custom Function

setDelay(1000, function()
 print("hello world!") -- print "hello world" to the log after 1000ms (1 second)
 -- you can insert any code you like between function() & end
end)

Looping Function with Delay

local i = 0 -- create variable i & set default value as 0

function example()
 i = i + 1 -- increment i by 1
 print(i) -- print the value of i to the log
 setDelay(1000, "example()") -- call the example() function again after 1000ms (1 second)
end

example() -- call the example() function to start the loop

Quick note #1: You might want to consider wrapping the setDelay() function inside of the delayed looping function with an if query to kill the loop when it's no longer needed.
Quick note #2: Taking the example above & what I just wrote in quick note #1 into consideration, you could easily create a looping function with a limited amount of loops by incrementing or decrementing a value each time the function is looped & then wrap the setDelay() function that recalls the function inside of an if query that checks if the value doesn't equal x so that it will automatically stop looping when the value reaches x.

mainLoop

The mainLoop event handler is the main scripting looping method that most people will probably learn about first. Unlike the delayed looping method with the setDelay() function, the mainLoop will loop constantly while it's registered, however you can control when the code inside of the mainLoop function is executed by wrapping your code in various if queries.

The mainLoop is one of the only event handlers that can have multiple functions registered to it per game project, & thus it can also be unregistered when you no longer need it.


registerEventHandler()

registerEventHandler("mainLoop", "exampleLoop") -- register exampleLoop() as a looping function & start looping

unregisterEventHandler()

unregisterEventHandler("mainLoop", "exampleLoop") -- unregister exampleLoop as a looping function & kill the loop

Basic Example

local i = 0 -- create variable i & set default value as 0

exampleLoop()
 i = i + 1 -- increment i by 1
 print(i) -- print the value of i to the log
end

registerEventHandler("mainLoop", "exampleLoop")

Tick Rate Example

local i = 0 -- create variable i & set default value as 0

exampleLoop()
 i = i + 1 -- increment i by 1
 if i == 10 then -- check if i equals 10
  print("hello world!") -- print "hello world!" to the log
  i = 0 -- reset i back to 0
 end
end

getTime() Example

local time = nil -- create variable time & set default value as nil

exampleLoop()
 if time == nil then time = getTime({flags=1, reset=true}) else time = getTime() end -- init or update time
 if time >= 3000 then -- if time more than or equals 3000ms then
  print("hello world!") -- print "hello world!" to the log
  time = getTime({flags=1, reset=true}) -- reset time back to 0ms
 end
end

registerEventHandler("mainLoop", "exampleLoop")

Quick note: Tick rate & getTime() are not very accurate in terms of controlling the delay as the mainLoop is based on system loop which is rarely consistent. In other words it could be 4ms one loop, or 33ms, etc. etc. in another loop, but it still has its uses for delays that don't need to be super precise.

While

The while loop will execute any code inside of it while the conditional argument is met. Here's a quick example...

local i = 0 -- create variable i & set default value as 0

while(i <= 10) do -- while i is less than or equal to 10 do
 print(i) -- print the value of i to the log
 i = i + 1 -- increment the value of i by 1
end

Quick note: For some reason Visionaire Studio doesn't really like the while loop & thus you should avoid using it if possible as it can potentially cause your game to crash depending on how it is used. In other words: use with caution!

Repeat Until

The repeat until loop will execute any code inside of it until the conditional argument is met. Here's a quick example...

local i = 0 -- create variable i & set default value as 0

repeat -- init repeat loop
 print(i) -- print the value of i to the log
 i = i + 1 -- increment the value of i by 1
until(i > 10) -- kill loop when i is greater than 10

Quick note: For some reason Visionaire Studio doesn't really like the repeat until loop & thus you should avoid using it if possible as it can potentially cause your game to crash depending on how it is used. In other words: use with caution!


Final Notes

I'm sure I am probably missing some timing & loop tricks, tips, & methods due to the existance of plugin action parts, the ilios scripting language, & the visual scripting system, however I think for now these will suffice unless anyone wants to share with me (AFRLme) some of your own tips & tricks for me to ammend to this page.


Resources

Name Description
N/A Sorry, there's no ved example & resource files available.