Vizard 7 » Tutorials & Examples » Flow control » Tasks » Tutorial: Creating a task
7.6

Tutorial: Creating a task

With viztask, you can pause the execution of a code while waiting for some event to occur. Task scheduling can be an extremely handy way to handle the flow of activity in a world.  

Start the script

If you have trouble getting the code in this tutorial to work, you can find the complete example script createTask.py in the \tutorials\flowControl directory.

 

In this example, we'll set up an interaction between two avatars, pausing for timers, keystrokes, and actions and animations. First, add some avatars, a room, and some text to your script:

import viz
import vizact

viz.setMultiSample(4)
viz.fov(60)
viz.go()

#Add a room.
dojo = viz.addChild('dojo.osgb')

#move the viewpoint
viz.MainView.move([0,0,-5])

#Add some avatars and place them in the room.
male = viz.addAvatar('vcc_male.cfg')
female = viz.addAvatar('vcc_female.cfg')
female.setPosition([-2,0,0])
female.setEuler([90,0,0])
male.setPosition([2,0,0])
male.setEuler([-90,0,0])

#Animate them.
male.state(1)
female.state(1)

#Add some text.
question_text = viz.addText('Hit spacebar to start', viz.SCREEN)
question_text.setScale([.4,.4,.4])
question_text.setPosition([.35,.75,0])
question_text.setBackdrop(viz.BACKDROP_OUTLINE)

Next, we'll import viztask and use it to schedule a function. By scheduling this function with <viztask>.schedule, we enable the ability to yield for a events or conditions. When you look at our function you can see a couple yield statements that let us yield first for a keystroke and then for one second to pass. The female avatar will wait to start dancing until you hit the spacebar and then the male will wait one second before walking over to her.  Run this script now and see how it goes.

#Import the viztask module.
import viztask
#Create a task.
def myTask():
    #Wait for a keypress.
    yield viztask.waitKeyDown( ' ' )
    #Animate the female.
    female.state( 5 )
    #Wait for a second.
    yield viztask.waitTime( 1 )
    #Make the male walk.
    male.addAction( vizact.walkTo( [-1,0,0] ) )
#Schedule the task.
viztask.schedule( myTask() )

Now we'll add a bit of code to get the male dancing once he reaches the female. The challenge here is that we don't want the male to start dancing until he's finished walking. To accomplish this, we'll use a yield statement to add the walking action to the male. The scheduler will wait until that action is finished before proceeding.  Replace the entire snippet of code that you just added and replace it with the code below. Try running the script again.

#Import the viztask module.
import viztask
#Create a task.
def myTask():
    #Wait for a keypress.
    yield viztask.waitKeyDown( ' ' )
    #Animate the female.
    female.state( 5 )
    #Wait for a second.
    yield viztask.waitTime( 1 )
    #Make the male walk and wait for him to finish the action.
    yield viztask.addAction( male,  vizact.walkTo( [-1,0,0] ) )
    #Make the male dance.
    male.state( 5 )
#Schedule the task.
viztask.schedule( myTask() )

We'll replace that chunk of code one more time and do several things with that modification. For one, we'll add a sub task within our task. The scheduler will call that task and wait for it to finish before proceeding. In this case we'll wait for the user to hit the 'n' key. We'll also change the script so that each task has a while True statement within it. This statement tells the scheduler to continue looping through that code until the function returns a value or is killed (with <viztask:Task>.kill ). That'll let us run through this series of events indefinitely and, in the case of the subtask, wait for the right feedback to continue. The other useful thing we've done with this modification is to use the data from an event within our function-- The viztask.waitKeyDown command returns a data object (viz.Data) with information about which key was pressed.  Try replacing the chunk of code we've been tweaking with the code below, then run it and see how it goes.

#Import the viztask module.
import viztask
#Create a task.
def myTask():
    #As long as the task is running . . .
    while True:
        question_text.message( 'Hit the spacebar to begin.' )
        #Wait for a keypress.
        yield viztask.waitKeyDown( ' ' )
        #Animate the female.
        female.state( 5 )
        #Wait for a second.
        yield viztask.waitTime( 1 )
        #Make the male walk and wait for him to finish the action.
        yield viztask.addAction( male,  vizact.walkTo( [-1,0,0] ) )
        #Make the male dance.
        male.state( 5 )
        #Wait for a sub task to finish.
        yield mySubTask()
        #Give the male a new animation.
        male.state(9)
        #Give the female a new animation and wait for it to finish.
        yield viztask.addAction( female, vizact.animation(6) )
        #Make the male run.
        male.addAction( vizact.walkTo( [2,0,-1],2.5,90,11 ) )

#Schedule the task.
viztask.schedule( myTask() )
def mySubTask():
    #Until this function returns a value or is killed. . .
    while True:
        #Set the text's message.
        question_text.message( 'Do they keep dancing? (y/n)' )
        #Wait for either 'y' or 'n' key to be pressed
        d = yield viztask.waitKeyDown( ['y','n'] )
        #If the keystroke is an 'n'. . .
        if d.key == 'n':
            question_text.message('')
            #End the task.
            return