Millisecond Forums

changing picture.erase condition dynamically; reduce flicker between trials

https://forums.millisecond.com/Topic41466.aspx

By jmaram - 7/31/2025

Hello!

I’m building a visual task where multiple objects fall from the top of the screen, and a player-controlled avatar can move left or right to collect them. Currently, I am dynamically changing the position of each object for each trial as it falls down, rather than using the animation attribute on the picture element to pre-define the falling paths. Because of this, I am experiencing "flickering" as each trial refreshes and as the objects "move" to their new position.  

To reduce screen flicker between trials, I’ve been using erase = false for the stimuli. However, I also see there are duplicates of the images that get created when the object needs to "move." Ideally, I want to have the stimuli to not flicker when at rest, and set erase=true and move to its new position when its supposed to without duplicates. 

I have attached the files with the script titled "picture trial.iqjs" . Please press 1 or 2 on the keyboard to move the avatar left or right.

Thank you!


By Dave - 7/31/2025

jmaram - 7/31/2025
Hello!

I’m building a visual task where multiple objects fall from the top of the screen, and a player-controlled avatar can move left or right to collect them. Currently, I am dynamically changing the position of each object for each trial as it falls down, rather than using the animation attribute on the picture element to pre-define the falling paths. Because of this, I am experiencing "flickering" as each trial refreshes and as the objects "move" to their new position.  

To reduce screen flicker between trials, I’ve been using erase = false for the stimuli. However, I also see there are duplicates of the images that get created when the object needs to "move." Ideally, I want to have the stimuli to not flicker when at rest, and set erase=true and move to its new position when its supposed to without duplicates. 

I have attached the files with the script titled "picture trial.iqjs" . Please press 1 or 2 on the keyboard to move the avatar left or right.

Thank you!



You need to set /erase=false for all stimuli and additionally use clearScreen as the first thing in /stimulusFrames to clear the screen of remnants from the preceding trial.
By Dave - 7/31/2025

Dave - 7/31/2025
jmaram - 7/31/2025
Hello!

I’m building a visual task where multiple objects fall from the top of the screen, and a player-controlled avatar can move left or right to collect them. Currently, I am dynamically changing the position of each object for each trial as it falls down, rather than using the animation attribute on the picture element to pre-define the falling paths. Because of this, I am experiencing "flickering" as each trial refreshes and as the objects "move" to their new position.  

To reduce screen flicker between trials, I’ve been using erase = false for the stimuli. However, I also see there are duplicates of the images that get created when the object needs to "move." Ideally, I want to have the stimuli to not flicker when at rest, and set erase=true and move to its new position when its supposed to without duplicates. 

I have attached the files with the script titled "picture trial.iqjs" . Please press 1 or 2 on the keyboard to move the avatar left or right.

Thank you!



You need to set /erase=false for all stimuli and additionally use clearScreen as the first thing in /stimulusFrames to clear the screen of remnants from the preceding trial.

Revised to not flcker.


_______________________________________________________________________________________
output file
<data>
/ columns = (date, time, subject, group, blockcode, blocknum, trialcode,trialNum,latency, script.elapsedTime, response, values.trial_type,values.stimuli_x, values.stimuli_y, values.stimulus_direction,values.avatar_x, values.avatar_direction,values.berries_collected,
values.berry_x, values.berry_y
//values.berry2_x, values.berry2_y
)
</data>
______________________________________________________________________________________
<defaults>
/ canvasaspectratio = (4,3)
/ minimumversion = "6.5.2.0"
/ fontstyle = ("Hei", 3%, false, false, false, false, 5, 1)
/ txbgcolor = white
/ txcolor = black
/ screencolor = white
</defaults>
_______________________________________________________________________________________

<block RunExp>
/ onBlockBegin = {
    values.berries_collected = 0;
}
/ trials = [1-9=InitialTrial;]
</block>

<values>
/ trial_type = 1    // 1 = predator. 2 = neutral
/ avatar_x = 5        //50%
/ avatar_step = 1
/ stimuli_x = 5        //50%
/ stimuli_step = 0
/ stimuli_y = 1        //10%
/ stimuli_speed = 2
/ avatar_direction = 0 // -1 = left, 1 = right
/ stimulus_direction = 0
/ random_direction_probability = 50

// berries
/ num_berries = 3 // randomized each block

/ berry_x = 1
/ berry_y = 1
/ berry1_speed = 1

/ berry2_x = 1
/ berry2_y = 1
/ berry2_speed = 1

/ berry3_x = 1
/ berry3_y = 1
/ berry3_speed = 1

/ berries_collected = 0

/ frame_counter = 0
</values>

<expressions>
/ berry_start_y = parameters.berry_radius
/ berry_end_y = 100 - parameters.berry_radius
</expressions>

<parameters>
/ berry_radius = 4
/ totalfallduration = 2000
/ berrystepduration = 500
</parameters>


<list avatar_xposition>
/ items = (0%, 10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%, 90%)
</list>
<list stimuli_xposition>
/ items = (0%,10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%, 90%)
</list>
<list stimuli_yposition>
/ items = (
    0%,2.5%,5%,7.5%,10%,12.5%,15%,17.5%,20%,22.5%,25%,27.5%,30%,32.5%,35%,37.5%,40%,42.5%,45%,47.5%,
    50%,52.5%,55%,57.5%,60%,62.5%,65%,67.5%,70%,72.5%,75%,77.5%,80%,82.5%,85%,87.5%,90%,92.5%,95%,97.5%)
</list>
<list berry_xposition>
/ items = (0%,10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%, 90%)
</list>
<list berry_yposition>
/ items = (
    0%,2.5%,5%,7.5%,10%,12.5%,15%,17.5%,20%,22.5%,25%,27.5%,30%,32.5%,35%,37.5%,40%,42.5%,45%,47.5%,
    50%,52.5%,55%,57.5%,60%,62.5%,65%,67.5%,70%,72.5%,75%,77.5%,80%,82.5%,85%,87.5%,90%,92.5%,95%,97.5%)
</list>



<list trial_type>
/ items = (0,1)
/ itemProbabilities = (0.6,0.4)
/ poolSize = 100 // HOW MANY TRIALS ?
</list>



// set up all pictures for types of trials

<picture avatar>
/ items = ("Beaver.png")
/ position = (list.avatar_xposition.item(values.avatar_x), 93%)
/ size = (5%,5%)
/ erase = false
</picture>

<picture berry_tree>
/ items = ("Berry_Tree.png")
/ position = (50%, 10%)
/ size = (100%,50%)
/ erase = false
</picture>

<picture berry>
/ items = ("berry.png")
/ position = (list.berry_xposition.item(values.berry_x), list.berry_yposition.item(values.berry_y))
/ size = (4%, 4%)
/ animation = path(50, 1,
list.berry_xposition.item(values.berry_x), list.berry_yposition.item(values.berry_y),
list.berry_xposition.item(values.berry_x), list.berry_yposition.item(values.berry_y + values.berry1_speed))
/ erase = false
</picture>

<picture berry2>
/ items = ("berry.png")
/ position = (list.berry_xposition.item(values.berry2_x), list.berry_yposition.item(values.berry2_y))
/ size = (4%, 4%)
/ erase = false
</picture>

<picture berry3>
/ items = ("berry.png")
/ position = (list.berry_xposition.item(values.berry3_x), list.berry_yposition.item(values.berry3_y))
/ size = (4%, 4%)
/ erase = false
</picture>

<text total_score>
/ items = ("Berries collected: <% values.berries_collected %>")
/ position = (10%, 10%)
/ txcolor = black
/ erase = false
</text>


<picture stimuli>
/ items = (
"threat.png",
"neutral_char.png")
/ position = (list.stimuli_xposition.item(values.stimuli_x), list.stimuli_yposition.item(values.stimuli_y))
/ size = (5%,5%)
/ select = values.trial_type
/ erase = false
// animation = path(50, 1,
// list.stimuli_xposition.item(values.stimuli_x), list.stimuli_yposition.item(values.stimuli_y),
// list.stimuli_xposition.item(values.stimuli_x + values.stimuli_step), list.stimuli_yposition.item(values.stimuli_y + values.stimuli_speed))
</picture>

<list signal_duration>
/ items = (2000, 3000, 4000)
/ selectionmode = random
</list>

<text signal_message>
/ items = ("Predator approaching!","Character arriving!")
/ fontStyle = ("Hei", 4%, false, false, false, false, 5, 0)
/ position = (50%, 50%)
/ txcolor = black
/ select = values.trial_type
/ erase = false
</text>

<trial InitialTrial>
/ timeout = 1000
/ onTrialBegin = {
values.num_berries = round(rand(1, 3));

values.avatar_x = round(rand(0,8));
values.avatar_direction = 0;

values.trial_type = list.trial_type.nextValue; // 0 = predator, 1 = neutral
values.stimuli_x = round(rand(0,8));
values.stimuli_y = 1;        // TODO: set the value of where the y position is for predator (distal or near post-encounter)
    values.stimuli_speed = 3;    // TODO change speed ?

values.berry_x = round(rand(1, 8));
values.berry_y = 1;
values.berry1_speed = 1;        // TODO possibly make it faster later

}
/ stimulusFrames = [1=clearScreen] // clear the screen while you're at it
/ branch = {
return trial.Signal;
}
/ validresponse = ()
/ inputdevice = keyboard
/ responseinterrupt = no // "no" is not a setting that exists
</trial>

<text debug_trial_type>
/ items = ("Trial type: <% values.trial_type %>")
/ position = (10%, 10%)
/ fontstyle = ("Arial", 2%, false, false, false, false, 5, 1)
/ erase = false
</text>



<trial Signal>
/ onTrialBegin = {    
    //picture.stimuli.erase = true; // NOT NEEDED
    //picture.avatar.erase = true; //NOT NEEDED
}
/ stimulustimes = [0 = clearScreen, signal_message]
/ timeout = 2000 // MAKE IT A DISTRIBUTION
/ branch = {
    return trial.Play;
}
/ validresponse = ()
/ inputdevice = keyboard
/ responseinterrupt = no // "no" is not a setting that exists
</trial>

<text debug_y>
/ items = ("Stimuli Y: <% values.stimuli_y %>")
/ position = (10%, 5%)
/ fontstyle = ("Arial", 2%, false, false, false, false, 5, 1)
/ erase = false
</text>


<trial Play>    // name it post_encounter?
/ timeout = 500    // TODO: randomize how long the trial lasts
/ onTrialBegin = {
    values.avatar_direction = 0;
    values.stimulus_direction = 0;
    values.frame_counter += 1;
    values.stimuli_step = 0;
    
}



/ stimulusFrames = [1=clearScreen,avatar,stimuli,total_score,berry;] // Clearing the screen is the first order of business

/ validresponse = (2,3)
/ inputdevice = keyboard
/ responseInterrupt = immediate

/ onTrialEnd = {
    
    // RECODE USING EXPRESSIONS . make an expression so that avatar_x_new is calculated, and the trial starts with that instead.
    // recode with old location, current_loc, new_loc ?
    
    // move avatar
        if (trial.Play.response == 2 && values.avatar_x > 0) {
            values.avatar_x -= 1;
            values.avatar_direction = -1;
            //picture.avatar.erase = true; // NOT NEEDED
        } else if (trial.Play.response == 3 && values.avatar_x < 9) {
            values.avatar_x += 1;
            values.avatar_direction = 1;
            //picture.avatar.erase = true; // NOT NEEDED
        }
    if (trial.Play.response != 0 || values.frame_counter % 5 == 0) {    // only if response is made or if counter is even
        
        if (values.trial_type == 0) { // predator moves towards avatar
            if (values.stimuli_x < values.avatar_x && values.stimuli_x < 9) {
                values.stimuli_step=1;
            } else if (values.stimuli_x > values.avatar_x && values.stimuli_x > 0) {
                values.stimuli_step=-1;
            }    values.stimuli_x += values.stimuli_step;
        } else if (values.trial_type == 1) { // neutral character moves randomly
            if (round(rand(1, 2)) == 1 && values.stimuli_x > 0) {
                values.stimuli_step=-1;
            } else if (values.stimuli_x < 9) {
                values.stimuli_step=1;
            }
            values.stimuli_x += values.stimuli_step;
            
        }
    }
    
    if (trial.Play.response == 0){    // to help stop flickering ?
        //picture.avatar.erase = false; // NOT NEEDED
        //picture.stimuli.erase = false; <--- HELP
    }
        
        // predator/character move downward
if (values.stimuli_y + values.stimuli_speed < 39) {

if (trial.Play.response != 0 || values.frame_counter % 5 == 0) {
values.stimuli_y += values.stimuli_speed;
                //picture.stimuli.erase = true; // NOT NEEDED
            }
    } else { // stimulus reached bottom
values.stimuli_y = 39;
// if (values.trial_type == 0 && values.stimuli_x == values.avatar_x)
            // TODO: Set color for predator if caught, grey if neutral
}
    
    
        // falling berry
        if (values.berry_y + values.berry1_speed < 39) {    
            values.berry_y += values.berry1_speed;
        } else    {    // if berry reaches bottom of screen
            if (values.berry_x == values.avatar_x){        // if berry is right above avatar
                values.berries_collected += 1;
            }
            values.berry_y = 0; // either reset to top or later change to multiple berries
            values.berry_x = round(rand(1, 9));
        }
        
}

/ branch = {
    if (values.stimuli_y == 39) {return trial.Indication;}
else return trial.Play;
}
</trial>

<trial Indication>
/ timeout = 3000
/ stimulusTimes = [100 = indication;]
</trial>

<text indication>
/ items = ("Indication period. Character will freeze or change color.")
</text>

// what does indication period look like
// how do characters change color?
By jmaram - 8/1/2025


Thank you so much Dave!