#1
|
|||
|
|||
Semi-circle array containing target and distractor objects
Hi,
I wonder if someone can help me, I am trying to set up a semi-circle array of positions on the left hand side of the screen, depending on how many distractors are selected (e.g. either 2, 4, 6 or 8) each position should contain one target object and the rest distractors, these should be randomised. I then want the target position to be a hotspot. But at this stage I'm having trouble just getting an array of positions where I want them with the correct objects in them. Any help would be hugely appreciated. Thank you. Code:
import viz import viztask import random viz.go() Z_dist = -5 #viz.move(0,0,Z_dist) viz.MainView.move(0.5,0,-10) # Add distractor and target objects ballsize = [2.0,2.0,2.0,1.0,1.0,1.0] # Distractor ball distractor = viz.add('soccerball.ive') distractor.setScale(ballsize[0],ballsize[1],2) distractor.addAction(vizact.spin(0,1,0,100)) # Target Ball target = viz.add('ball.wrl') target.setScale(ballsize[3],ballsize[4],1) target.addAction(vizact.spin(0,1,0,100)) # Set up zones for the objects to appear on the screen choice = ['2', '4', '6', '8'] select = viz.choose('How many distractors?', choice) #make a list with the objects in it objects = [distractor,target] # keep 2 positions in an array pos = [[-1.0,0.0,Z_dist],[-1.0,0.5,Z_dist],[-2.0,1.0,Z_dist],[-1.0,1.5,Z_dist],[-1.0,2.0,Z_dist],[-1.0,2.5,Z_dist],[-1.0,3.0,Z_dist],[-1.0,3.5,Z_dist]] rand_positions = [] def sceneOn(num): global rand_positions positions = [0,1,2,3,4,5,6,7] if select == 0: #set objects to 2 different random positions rand_positions = random.sample(positions,2) objects[0].setPosition(pos[rand_positions[0]]) objects[1].setPosition(pos[rand_positions[1]]) if select == 1: #set objects to 4 different random positions rand_positions = random.sample(positions,4) objects[0].setPosition(pos[rand_positions[0]]) objects[0].setPosition(pos[rand_positions[1]]) objects[0].setPosition(pos[rand_positions[2]]) objects[1].setPosition(pos[rand_positions[3]]) if select == 2: #set objects to 4 different random positions rand_positions = random.sample(positions,6) objects[0].setPosition(pos[rand_positions[0]]) objects[0].setPosition(pos[rand_positions[1]]) objects[0].setPosition(pos[rand_positions[2]]) objects[0].setPosition(pos[rand_positions[3]]) objects[0].setPosition(pos[rand_positions[4]]) objects[1].setPosition(pos[rand_positions[5]]) if select == 3: rand_positions = random.sample(positions,8) objects[0].setPosition(pos[rand_positions[0]]) objects[0].setPosition(pos[rand_positions[1]]) objects[0].setPosition(pos[rand_positions[2]]) objects[0].setPosition(pos[rand_positions[3]]) objects[0].setPosition(pos[rand_positions[4]]) objects[0].setPosition(pos[rand_positions[5]]) objects[0].setPosition(pos[rand_positions[6]]) objects[1].setPosition(pos[rand_positions[7]]) sceneOn(1) |
#2
|
|||
|
|||
Your script was only creating 2 object, even when more than 2 distractors were selected. I modified your script to dynamically create the objects based on the number of distractors. I also modified the sceneOn function to be more general in positioning the objects.
I'm still not sure what you mean by placing the objects in a semi-circle. The list of positions you have pretty much places all the objects in a vertical line. Anyway, here's the modified script: Code:
import viz import viztask import random viz.go() Z_dist = -5 #viz.move(0,0,Z_dist) viz.MainView.move(0.5,0,-10) # Add distractor and target objects ballsize = [2.0,2.0,2.0,1.0,1.0,1.0] # Set up zones for the objects to appear on the screen choice = ['2', '4', '6', '8'] select = viz.choose('How many distractors?', choice) numDistractors = int(choice[select]) #make a list with the objects in it objects = [] # Distractor ball for x in range(numDistractors-1): distractor = viz.add('soccerball.ive') distractor.setScale(ballsize[0],ballsize[1],2) distractor.addAction(vizact.spin(0,1,0,100)) objects.append(distractor) # Target Ball target = viz.add('ball.wrl') target.setScale(ballsize[3],ballsize[4],1) target.addAction(vizact.spin(0,1,0,100)) objects.append(target) # keep 2 positions in an array pos = [[-1.0,0.0,Z_dist],[-1.0,0.5,Z_dist],[-2.0,1.0,Z_dist],[-1.0,1.5,Z_dist],[-1.0,2.0,Z_dist],[-1.0,2.5,Z_dist],[-1.0,3.0,Z_dist],[-1.0,3.5,Z_dist]] def sceneOn(num): # Get random sample of positions rand_positions = random.sample(pos,numDistractors) # Apply positions to objects for p,o in zip(rand_positions,objects): o.setPosition(p) sceneOn(1) |
#3
|
|||
|
|||
Thanks very much for your reply. I have been working hard on this code and it is now completely different from when I posted my initial question. Please see below.
I am having some problems which I would really appreciate help with: 1. how do I stop the avatar going out of the screen? 2. when the avatar's right arm hits the target, I want the avatar to do something e.g. dance, if the avatars right arm hits a distractor then it should something else, e.g. ball should change colour - I have tried setting this up using collisions and hotspots and can't get either to work? 3. I still haven't managed to get the objects in a semi-circle so that they are all equidistant from the avatar start position Any help would be huegly appreciated. Sorry the code is such a mess, any help with tidying it up would also be greatly appreciated. Thank you. Code:
import viz import viztask import random import vizjoy viz.go() def createlabel(): global trialNumber, time, xPosition #Create background quad for labels viz.startlayer(viz.QUADS) viz.vertexcolor(0,0.2,0) viz.vertex(0,0,0) viz.vertex(0,0.05,0) viz.vertex(0.20,0.05,0) viz.vertex(0.205,0,0) InfoQuad = viz.endlayer(viz.SCREEN) InfoQuad.draworder(30) InfoQuad.disable(viz.DEPTH_WRITE) InfoQuad.alpha(0.5) InfoQuad.translate(1-0.20,0) #Create label for trial number trialNumber = InfoQuad.add(viz.TEXT3D,'0') trialNumber.scale(0.3,0.3,1) trialNumber.translate(0.01,0.02) trialNumber.font('times.ttf') trialNumber.color(viz.GREEN) trialNumber.draworder(31) trialNumber.disable(viz.LIGHTING) trialNumber.alignment(viz.TEXT_LEFT_CENTER) #Create label for nv time = InfoQuad.add(viz.TEXT3D,'0') time.scale(0.3,0.3,1) time.translate(0.04,0.02) time.font('times.ttf') time.color(viz.GREEN) time.draworder(31) time.disable(viz.LIGHTING) time.alignment(viz.TEXT_LEFT_CENTER) #Create label for reversals xPosition = InfoQuad.add(viz.TEXT3D,'0') xPosition.scale(0.3,0.3,1) xPosition.translate(0.08,0.02) xPosition.font('times.ttf') xPosition.color(viz.GREEN) xPosition.draworder(31) xPosition.disable(viz.LIGHTING) xPosition.alignment(viz.TEXT_LEFT_CENTER) createlabel() joystick = vizjoy.add() viz.mouse(viz.OFF) viz.mouse.setTrap(viz.ON) #viz.mouse.setVisible(viz.OFF) Z_dist = -5 viz.MainView.move(0.5,0,-10) filename = viz.input('Input data file name') file = filename + 'T1StaticObjects' + '.txt' print 'Filename: ', file #viz.window.setSize(-1) # set to full size # Add distractor and target objects ballsize = [2.0,2.0,2.0] # Distractor ball distractor = viz.add('soccerball.ive') distractorClone1 = distractor.clone() #Copy the object distractorClone1.setScale(ballsize[0],ballsize[1],2) distractorClone1.addAction(vizact.spin(0,1,0,100)) distractorClone2 = distractor.clone() #Copy the object distractorClone2.setScale(ballsize[0],ballsize[1],2) distractorClone2.addAction(vizact.spin(0,1,0,100)) distractorClone3 = distractor.clone() #Copy the object distractorClone3.setScale(ballsize[0],ballsize[1],2) distractorClone3.addAction(vizact.spin(0,1,0,100)) distractorClone4 = distractor.clone() #Copy the object distractorClone4.setScale(ballsize[0],ballsize[1],2) distractorClone4.addAction(vizact.spin(0,1,0,100)) distractorClone5 = distractor.clone() #Copy the object distractorClone5.setScale(ballsize[0],ballsize[1],2) distractorClone5.addAction(vizact.spin(0,1,0,100)) # Target Ball target = viz.add('soccerball.ive') target.setScale(ballsize[0],ballsize[1],2) target.addAction(vizact.spin(0,-1,0,100)) pos = [[-1.5,1.5,Z_dist],[-1.5,2.5,Z_dist]] pos1 = [[-1.5,0.75,Z_dist],[-1.5,1.5,Z_dist],[-1.5,2.25,Z_dist],[-1.5,3.0,Z_dist]] pos2 = [[-1.5,0.5,Z_dist],[-1.5,1.0,Z_dist],[-1.5,1.5,Z_dist],[-1.5,2.0,Z_dist],[-1.5,2.5,Z_dist],[-1.5,3.0,Z_dist]] objects = [target,distractorClone1,distractorClone2,distractorClone3,distractorClone4,distractorClone5] # Set up zones for the objects to appear on the screen choice = ['1', '3', '5'] select = viz.choose('How many distractors?', choice) def sceneOn(): global target_position,rand_pos,Rotation if select == 0: # set objects to 2 random positions rand_pos = random.sample(pos,2) objects[0].setPosition(rand_pos[0]) objects[1].setPosition(rand_pos[1]) target_position = rand_pos[0] print 'target position:', target_position if select == 1: #set objects to 4 different random positions rand_pos = random.sample(pos1,4) objects[0].setPosition(rand_pos[0]) objects[1].setPosition(rand_pos[1]) objects[2].setPosition(rand_pos[2]) objects[3].setPosition(rand_pos[3]) target_position = rand_pos[0] print 'target position:', target_position if select == 2: #set objects to 6 different random positions rand_pos = random.sample(pos2,6) objects[0].setPosition(rand_pos[0]) objects[1].setPosition(rand_pos[1]) objects[2].setPosition(rand_pos[2]) objects[3].setPosition(rand_pos[3]) objects[4].setPosition(rand_pos[4]) objects[5].setPosition(rand_pos[5]) target_position = rand_pos[0] print 'target position:', target_position # Set up male and female avatars choice2 = ['male', 'female'] select2 = viz.choose('Gender of participant?', choice2) if select2 == 0: avatar = viz.add('vcc_male.cfg') if select2 == 1: avatar = viz.add('vcc_female.cfg') avatar.lookat(-10, 0, -10) avatar.state(1) import time def position_loop(): global pos_inc, x, y, Rotation, start_position, target_position, rand_pos tinc = 1/500 pos_inc = [0,0] start_position = (3.0, 1.0,Z_dist) start_time = time.time() elapsed_time = time.time() - start_time total_reps = 10 def position_timer(num): global pos_inc, start_position, target_position,Rotation position = joystick.getPosition() Rotation = joystick.getRotation() pos_inc[0] = pos_inc[0] + position[0]/50 pos_inc[1] = pos_inc[1] + position[1]/50 x = start_position[0]+pos_inc[0] y = start_position[1]+pos_inc[1] avatar.setPosition(x,y,Z_dist) if Rotation > 1: elapsed_time = time.time() - start_time #print 'Elapsed Time: ', elapsed_time, 'X Position: ', x, 'Y Position: ', y #Y',"%.2f, %.2f, %.2f" % (elapsed_time,x,y) SaveData(select, select2, elapsed_time, x, y) viz.callback(viz.TIMER_EVENT,position_timer) viz.starttimer(1,tinc,viz.FOREVER) def experiment(): global pos_inc, x, y, Rotation, start_position, target_position, select, select2, elapsed_time,rand_pos #updatelabel(0,0,0) total_reps = 10 for i in range (total_reps): print total_reps yield viztask.waitKeyDown(' ') position_loop() #Ready = viz.ask('Are You Ready?') #yield viztask.waitKeyDown(' ') yield viztask.waitMouseDown(viz.MOUSEBUTTON_LEFT) avatar.lookat(-10, 0, -5) sceneOn() avatar.state(2) armBone = avatar.getBone('Bip01 R UpperArm') # Don't move the bone with built-in animations armBone.lock() # Raise arm armBone.setEuler(0, 0, -70) #updatelabel(tr,round(x,1), round(elapsed_time),1) #def updatelabel(tr,x,elapsed_time): # global trialNumber, time, xPosition # trialNumber.message(str(tr)) # time.message(str(elapsed_time)) # xPosition.message(str(x)) import vizinfo # Define a function that saves data file = open(filename + 'T1StaticObjects', 'w') def SaveData(a,b,c,d,e): # Create the output string out = str(a) + '\t' + str(b) + '\t' + str(c) + '\t' + str(d) + '\t' + str(e) + '\n' out_headings = 'Distractor Number' + '\t' + 'Avatar' + '\t' + 'Elapsed Time' + '\t' + 'x Position' + '\t' + 'y Position' + '\t' if a == 0: file.write (out_headings) # Write the string to the output file file.write(out) # Makes sure the file data is really written to the harddrive file.flush() viztask.schedule(experiment()) |
#4
|
|||
|
|||
Sorry, forgot to mention there is also a ball in position 0,0 which I can't seem to get rid of.
Thanks again. |
|
|