Forum Discussion
Button Listener to move a character
Hello everyone
I've dealing with a problem, I started a project, it is supposed to be an Escape Room, and most of the things I need for it are already available on Storyline.
But I've been stuck on the movement of the character, it is a simple 2D movement, right and left, inside the room.
The problem is:
I already got it to move on a click, but it is just on that click, I want it to move as long as I keep the button pressed.
This is the last JavaScript I tried to make it move:
const button = object('5yfHufFxicy');
function moveWhilePressed() {
button[i].addEventListener("mousedown",() =>{
const player = GetPlayer();
player.GetVar("MousePressed");
const currentX = player.GetVar("MoveX");
player.SetVar("MoveX", currentX +1);
setTimeout(moveWhilePressed, 100);
const objects = [
object('6EPGwyDzEfX'),
];
const positions = objects.map(obj => ({ x: obj.x}));
objects.forEach((obj, i) => {
obj.x = positions[i].x+currentX;
});
});
}
moveWhilePressed();
Not sure if I'm wrong on the EventListener, before I added it, the character moved, but the moment I clicked, it kept moving without the button pressed.
I tried using Variables, but the result was the same, the character kept moving.
There are a few issues here. First, the object returned by the newer JavaScript API (e.g., object('5yfHufFxicy')) does not reference the actual DOM element. It only exposes a limited set of properties and methods, so you can’t attach event listeners to it directly.
A more appropriate way to target the real DOM element would be using attributes like data-model-id or data-acc-text. However, in this case, that approach isn't necessary.
Since we already have a Storyline trigger that runs when the button state is Down, we can use that to handle the action (e.g., movement) instead of relying on event listeners. This makes the setup simpler and more reliable, as we can focus entirely on controlling the character's movement through Storyline logic and variable-based triggers.
In the updated file, there are now two buttons (Left and Right) that move the character in the corresponding direction when their state is set to Down. To keep the logic consistent, I created two Boolean variables: isLeftPressed and isRightPressed. These variables track whether the character should move left or right.
When neither button is in the Down state, the character’s movement is paused. As soon as either button is pressed again, the movement resumes in the appropriate direction.
Example code executed when the Right button is in the Down state (starts moving the character to the right):const character = object('6EPGwyDzEfX'); if (getVar("isRightPressed")) { window.characterMoveInterval = setInterval(() => { const currentX = character.x; const newX = currentX + 2; gsap.set(character, { x: newX }); }, 50); }
Stop the character movement when a button is not in Down state:
clearInterval(window.characterMoveInterval);
4 Replies
- KeairaStill-3bfCommunity Member
Nedim Thank you so much for your thorough response. I don't have use for this code yet, but I'm learning javascript. This explanation was fantastic! and helped me understand the logic of movement more.
- NedimCommunity Member
There are a few issues here. First, the object returned by the newer JavaScript API (e.g., object('5yfHufFxicy')) does not reference the actual DOM element. It only exposes a limited set of properties and methods, so you can’t attach event listeners to it directly.
A more appropriate way to target the real DOM element would be using attributes like data-model-id or data-acc-text. However, in this case, that approach isn't necessary.
Since we already have a Storyline trigger that runs when the button state is Down, we can use that to handle the action (e.g., movement) instead of relying on event listeners. This makes the setup simpler and more reliable, as we can focus entirely on controlling the character's movement through Storyline logic and variable-based triggers.
In the updated file, there are now two buttons (Left and Right) that move the character in the corresponding direction when their state is set to Down. To keep the logic consistent, I created two Boolean variables: isLeftPressed and isRightPressed. These variables track whether the character should move left or right.
When neither button is in the Down state, the character’s movement is paused. As soon as either button is pressed again, the movement resumes in the appropriate direction.
Example code executed when the Right button is in the Down state (starts moving the character to the right):const character = object('6EPGwyDzEfX'); if (getVar("isRightPressed")) { window.characterMoveInterval = setInterval(() => { const currentX = character.x; const newX = currentX + 2; gsap.set(character, { x: newX }); }, 50); }
Stop the character movement when a button is not in Down state:
clearInterval(window.characterMoveInterval);
- CajaPopularM704Community Member
Thanks a lot, Nedim.
It worked wonders, I even added background objects, grouped them, and applied the code to the groups so it made a parallax effect.
My only doubt is, will the clearInterval() code work if I want the object to stop so it doesn't leave the slide?
I already created two variables, one that matches the width of the slide and another one that follows character.x, I want to know if clearInterval() will stop the object even if I'm still keeping the button pressed, or if I need another code for that.
- NedimCommunity Member
I probably should’ve seen the “character walking off the slide” issue coming! :) I guess I was being a bit too lazy leaving that part out. Just kidding, of course.
We can improve our existing script to handle the case where the character reaches the edge of the slide. By integrating character.width and slideWidth() directly into the movement logic, we can detect when the character is about to reach the edge of the slide. When that happens, we automatically call clearInterval() to stop the movement.
To make it cleaner visually, we also subtract a small buffer (e.g., 5px) so the character doesn’t appear to be squished right up against the edge. And as a little bonus, when the character hits the wall, we switch its state so it appears to turn around.
A code example when the right button is in Down state:const character = object('6EPGwyDzEfX'); if (getVar("isRightPressed")) { window.characterMoveInterval = setInterval(() => { const newX = character.x + 2; if (newX + character.width <= slideWidth()) { gsap.set(character, { x: newX }); } else { clearInterval(window.characterMoveInterval); } }, 50); }
To detect when the character reaches the left edge of the slide, the logic is similar to the right edge. The character keeps moving left as long as the new position is greater than 0. Once it hits that threshold, we stop the movement.
A code example when the left button is in Down state:const character = object('6EPGwyDzEfX'); if (getVar("isLeftPressed")) { window.characterMoveInterval = setInterval(() => { const newX = character.x - 2; if (newX > 0) { gsap.set(character, { x: newX }); } else { clearInterval(window.characterMoveInterval); } }, 50); }
If the character is too close to either edge, we can add a small buffer to both conditions to prevent it from touching the exact edge of the slide. For example:
if (newX + character.width <= slideWidth() - 5) or if (newX > 5)
Hope this helps.
Related Content
- 5 months ago