I apologize for not posting this sooner - current situation has really thrown a wrench in things. Here is code that was done by David. It works beautifully on line. It doesn’t lock pieces in place, but it does do a very nice drag and drop. I’ll do the python first then JS.
Note: This is David Bridge’s Code, so I have cited him as the author of the code on my experiment.
In Begin Experiment Tab:
def createPiece(piece, pos, name):
return visual.ImageStim(win, image=piece.image, name=name, size=piece.size, pos=pos)
def drawPicked(picked):
for each in picked:
each.draw()
def movePicked(picked, mouse, grabbed):
if grabbed is not None and mouse.isPressedIn(grabbed):
grabbed.pos = mouse.getPos()
return grabbed
else:
for piece in picked:
if mouse.isPressedIn(piece) and grabbed is None:
return piece
def createGrid(rows, size, pos, names):
inc = (size/rows)
rowStart = pos[0] - size/2
colStart = pos[1] + size/2
row, col = rowStart + inc/2, colStart - inc/2
counter = 0
grid = []
for i in range(rows):
for j in range(rows):
grid.append(visual.Rect(win, name=names[counter], units='height', size = [size/rows, size/rows], pos= [row,col], lineColor= [-1.000,0.184,0.184]))
row += inc
counter += 1
col -= inc
row = rowStart + inc/2
return grid
def drawGrid(grid):
for i in grid:
i.draw()
def checkAnswer(grid, pieces):
# Get names of pieces that were picked
picNames = [pic.image for pic in pieces]
correctPieces = []
for cell in grid:
# Check if piece has been picked
if cell.name in picNames:
for name in range(0, len(picNames)):
if cell.name == picNames[name]:
if cell.contains(pieces[name].pos):
correctPieces.append(True)
break # Piece found, go to next cell
else:
return False # Correct piece not picked
return len(correctPieces) == len(grid)
In Begin Routine Tab:
continueRoutine = True
pieces = [p1a, p2a, p3a, p4a, p5a, p6a]
answers = [a1,a2,a3,a4,a5,a6,a7,a8,a9]
picked = []
newPiece = None
movingPiece = None
grid = createGrid(nRows1, size, polygon.pos, answers)
polygon.setFillColor(None)
In Each Frame Tab:
for piece in pieces:
if mouse.isPressedIn(piece) and newPiece == None:
newPiece = createPiece(piece, mouse.getPos(), piece.image)
picked.append(newPiece)
if newPiece is not None and mouse.getPressed()[0] == 0:
newPiece = None
movingPiece = movePicked(picked, mouse, movingPiece)
drawGrid(grid)
drawPicked(picked)
JS in Begin Experiment Tab:
createPiece = function(piece, pos, name){
return new visual.ImageStim({win : psychoJS.window,
image: piece.image,
name: name,
size: piece.size,
pos: pos})
}
drawPicked = function(picked, draw) {
if (picked.length > 0) {
for(let each of picked) {
each.autoDraw = draw;
}
}
}
movePicked = function(picked, mouse, grabbed) {
if (grabbed != 'undefined' && mouse.getPressed()[0] === 1) {
grabbed.pos = mouse.getPos();
return grabbed
} else {
for (let piece of picked) {
if (piece.contains(mouse) && mouse.getPressed()[0] === 1 && grabbed === 'undefined'){
piece.pos = mouse.getPos();
return piece;
}
}
return 'undefined'
}
}
createGrid = function(rows, size, pos, names) {
var inc = (size/rows);
var rowStart = pos[0] - size/2;
var colStart = pos[1] + size/2;
var row = rowStart + inc/2;
var col = colStart - inc/2;
var counter = 0;
var grid = [];
for (let i = 0; i < rows; i++) {
for (let j = 0; j < rows; j++) {
grid.push(new visual.Rect({win : psychoJS.window,
name: names[counter],
units: 'height',
lineColor: new util.Color([0,0,0]),
size: [size/rows, size/rows],
pos: [row,col]}))
row += inc
counter += 1
}
col -= inc
row = rowStart + inc/2
}
return grid
}
drawGrid = function(grid, draw) {
for (let i of grid) {
i.autoDraw = draw;
}
}
checkAnswer = function(grid, pieces) {
var picNames = pieces.map((pic) => pic.name)
var correctPieces = []
for (let cell of grid) {
if (picNames.includes(cell.name)) {
for (let name = 0; name < picNames.length; name++) {
if (cell.name === picNames[name]) {
if (cell.contains(pieces[name])) {
correctPieces.push(true)
break
}
}
}
} else {
return false
}
}
return correctPieces.length === grid.length
}
picNameDict = {p1a: "pcetl.png",
p2a: "pcetr.png",
p3a: "pcered.png",
p4a: "pcebl.png",
p5a: "pcebr.png",
p6a: "pcewte.png",
p1b: "pcetl.png",
p2b: "pcetr.png",
p3b: "pcered.png",
p4b: "pcebl.png",
p5b: "pcebr.png",
p6b: "pcewte.png",
}
In Begin Routine Tab:
pieces = [p1a, p2a, p3a, p4a, p5a, p6a]
answers = [a1,a2,a3,a4,a5,a6,a7,a8,a9]
picked = []
newPiece = 'undefined'
movingPiece = 'undefined'
grid = createGrid(nRows1, size, polygon.pos, answers)
In Each Frame Tab:
for (let piece of pieces) {
if (piece.contains(mouse) && mouse.getPressed()[0] === 1 && newPiece === 'undefined') {
newPiece = createPiece(piece, mouse.getPos(), picNameDict[piece.name])
picked.push(newPiece)
}
}
if (newPiece !== 'undefined' && mouse.getPressed()[0] === 0) {
newPiece = 'undefined'
}
movingPiece = movePicked(picked, mouse, movingPiece)
drawGrid(grid, true)
drawPicked(picked, true)
if (t > .5 && nextButton.contains(mouse) && mouse.getPressed()[0] === 1) {
continueRoutine = false
}
In End Routine Tab:
piece = drawPicked(picked, false, piece)
drawGrid(grid, false)
nextButton.setAutoDraw(false)
Good Luck!