Twine Version: 2.3.9
Story Format: Sugarcube 2.31.1
Hello! I’m not too shabby with HTML and CSS, but new to Twine and Javascript.
The Goal
I’d like to make a drag-and-drop puzzle in my Twine game. For context, the game is a class project that’s supposed to teach students about quantum mechanics. The puzzle is an equation (a series of droppables) that the students have to drag and drop the correct terms (a series of draggables) into. Upon dragging the correct terms in, either text appears with a link to the next passage (pictured in concept art), OR are immediately taken to the next passage - whichever way is easier to code.
Concept Art:
-
Player must drag the terms into the correct places to build the equation.
-
Once terms are in correct spots, a “Well done!” message appears which links to the next passage.
The Problem
I’ve got most of the code worked out except for the part about checking the answer, if you will. To be more precise, I need JavaScript to “check” that all of the droppables have draggables dropped on them, and if so, proceed to the next passage. I’d ideally have extra “incorrect” terms/draggables that don’t get accepted into any of the droppables (not pictured in concept art) so the answer to the puzzle isn’t as obvious. I don’t think I need JS to actually check the identity of the draggables since each droppable only accepts a particular draggable already - so just “checking” that all droppables have accepted “something” will work for my purposes. I’m not quite sure how to go about that or if it’s possible.
Possible Solutions/Research I’ve Done So Far
There was a post with a similar goal here on Intfiction, but it doesn’t look like it went anywhere. There was also a post on Reddit, but their puzzle was concerned with collisions. I personally couldn’t extrapolate anything from it. Perhaps someone with more experience can.
I haven’t had any luck finding anything else on Twine/Reddit forums, but I’ve found this (something about a checkFinish() function) and this post (something about utilizing classes) from a Hype forum site that help - I think - but I don’t have enough experience with JavaScript to interpret the answers much less implement them. Any insight from a more experienced Java Script coder as how to move forward would be very appreciated!
The Set Up
To start, I loaded jQuery UI into Twine by following HiEv’s lovely tutorial on integrating jQuery UI with Twine to create draggable/droppable divs. There was something wrong with loading jQuery UI in this way (it kept spitting an error at me), so instead of the JavaScript HiEv uses, I did what greyelf suggested in this forum; I copied/pasted text from the jquery-ui.min.js file into my Story JavaScript and text from the jquery-ui.min.css file into my Story StyleSheet. HiEv’s scripts from within the HTML work just fine!
I also downloaded Bootstrap 4.5.3 and copied/pasted the text from the bootstrap-grid.css file into my Story Stylesheet. (I’m more comfortable with this notation!)
The file is below for you to import into Twine if you’d like.
.zip file: draggable_puzzle_test.zip (173.1 KB)
The Puzzle Code So Far
Everything works beautifully so far using this code in my puzzle’s passage:
<div class="row">
<div id="droppable-1" class="droppable ui-widget-header col-md-3">
Put draggable #1 here.
</div>
<div id="equal" class="col-md-1">
=
</div>
<div id="droppable-2" class="droppable ui-widget-header col-md-3">
Put draggable #2 here.
</div>
<div id="droppable-3" class="droppable ui-widget-header col-md-3">
Put draggable #3 here.
</div>
<div id="droppable-4" class="droppable ui-widget-header col-md-2">
Put draggable #4 here.
</div>
</div>
<div id="draggable-1" class="draggable ui-widget-content" style="width: 150px; height: 150px; padding: 0.5em;">
Drag me around #1.
</div>
<div id="draggable-2" class="draggable ui-widget-content" style="width: 150px; height: 150px; padding: 0.5em;">
Drag me around #2.
</div>
<div id="draggable-3" class="draggable ui-widget-content" style="width: 150px; height: 150px; padding: 0.5em;">
Drag me around #3.
</div>
<div id="draggable-4" class="draggable ui-widget-content" style="width: 150px; height: 150px; padding: 0.5em;">
Drag me around #4.
</div>
<script>
$( function() {
$( ".draggable" ).draggable({
containment: "document",
cursor: "move",
cursorAt: { top: 75, left: 75 },
snap: ".droppable"
});
$( "#droppable-1" ).droppable({
accept: "#draggable-1",
classes: {
"ui-droppable-hover": "ui-state-hover"
},
drop: function( event, ui ) {
$( this )
.addClass( "ui-state-highlight" )
.html( "Dropped!" )
}
});
$( "#droppable-2" ).droppable({
accept: "#draggable-2",
classes: {
"ui-droppable-hover": "ui-state-hover"
},
drop: function( event, ui ) {
$( this )
.addClass( "ui-state-highlight" )
.html( "Dropped!" )
}
});
$( "#droppable-3" ).droppable({
accept: "#draggable-3",
classes: {
"ui-droppable-hover": "ui-state-hover"
},
drop: function( event, ui ) {
$( this )
.addClass( "ui-state-highlight" )
.html( "Dropped!" )
}
});
$( "#droppable-4" ).droppable({
accept: "#draggable-4",
classes: {
"ui-droppable-hover": "ui-state-hover"
},
drop: function( event, ui ) {
$( this )
.addClass( "ui-state-highlight" )
.html( "Dropped!" );
}
});
} );
</script>
<<script>>
$(document).one(":passagerender", function(event) {
// Passage is about to be displayed.
$(event.content).find(".draggable").draggable(); // Make "draggable" elements draggable.
$(event.content).find(".droppable").droppable(); // Make "droppable" elements droppable.
});
<</script>>
When put into my Twine passage, it looks like a very bare-bone skeleton of my concept art (demo below.)
TL;DR:
How do I get Javascript to “check for the correct answer” (check all of the droppables have draggables dropped on them) and then display a link to the next passage (or immediately take the player to the next passage, whichever is easier to code)? I feel like someone must have tried accomplishing something similar before.
Thank you very much in advance.