Keep It Up explainer

Keep It Up

The aim of this puzzle: Create a game where you tap the circle to keep it up in the air.
Walkthrough of the solution: You know that you’ll be tapping the circle, so that means you will need to use circle.on('click',...); Then, you have to figure out what function to run when you click on the circle. There’s no function button, but there is an arrow function button () => {} which means you can make the function right inside of the .on('click') command. Now, you need to fill out the function with all the rules of the game.

To make the circle start falling, you need a transition, and it will move down to a 'cy' of 165. That gives you: circle.transition().attr('cy', 165); The speed it falls can be controlled by setting the .duration() value (try something around 2000ms). You also want to change the easing so that it falls the way gravity would move it – accelerating toward the ground. The final part of this command is to remove the circle if it completes the transition (hits the floor). Putting this all together, you get: circle.transition().duration(2000).attr('cy', 165).ease(d3.easeQuadIn).remove();

You can switch around the order of duration, attr, ease, and remove but make sure these all come after the .transition(). If you run the code, you’ll see the balloon fall when you tap on it, but if you tap again, it freezes and then starts falling from the same spot – you need to add a command to reset the position of the circle before the “falling” command that you made. The circle should be reset to the top of the screen which is a 'cy' of 35, and also a random horizontal position. That means 'cx' should be set to pickRandom(position) by using an .attr() Make sure to put the circle.attr('cy', 35).attr('cx', pickRandom(position)) command before the “falling” transition command, because the transition ends with removing the circle which would be “game over”. Let’s try the code again.

You’ll see that 'cx' is moving, but 'cy' still isn’t resetting! That’s because the 'cy' attribute is busy – it’s still animating the transition that started running when you clicked the ballon last time (a new transition will stop the old one, but an attr on its own will be ignored if there’s a transition running). To overcome this, you need to use .interrupt() before the “reset” command.

There is a way to combine all of the calls in the function into one long chained call – you just need to be careful about the order that things happen.

Key Points

  • The .interrupt() has to be before the .attr('cy',...)
  • The .transition() has to be after the interrupt and the “reset” .attr()s
  • The duration, attr, ease, and remove for the falling motion have to be after the transition

Sample code solution:
(Tap below to reveal)

This is the final card in this course (woohoo!) – to test your knowledge there is no sample solution code

JavaScript Concepts: Code Block (Arrow Function), Calling Functions, Call Nesting, E S6
Grasshopper Concepts: pickRandom()
D3 Concepts: .attr(‘cy’,), .attr(‘cy’,), attr(‘fill’,), attr(‘r’,), .append(), .duration(), .ease(), .interrupt(), .on(‘click’,), .transition(), .remove()
Additional Code: There is hidden code that runs before the puzzle’s code that defines the position variable and creates the grey floor.


Here it says the max cy should be 200 but the app says to set it to 165. Please update for consistency, thanks for the cool app.

Updated. Thanks for catching that!
– Frankie

1 Like

You’re welcome. :ok_hand:

1 Like

Hey support team!
I got the animation to look and behave just like the example solution but the app tells me to put .transition right after circle. But if I do that my code breaks. I put .interrupt behind circle and .transition right before .duration and that does exactly what I want.
Can you please help me?

1 Like

Hey @Max,

Thanks for reaching out!

Mmm — not sure exactly whats going wrong here. Would you be able to share a screenshot of your code so we can try to replicate the issue you’re seeing?

H :slight_smile:


Hey Heather!
My code looks like this:

Ah, your solution is correct and should solve — the problem is on our end. We’re looking for three expressions inside the function. One to adjust the time, one to interrupt the transition and move the balloon to the top of the screen, and one to define the falling transition. You’ve combined the last two into one expression.

If you seperate out the interrupt expression and the falling transition the puzzle will solve. We’re actively working on fixing this issue, so thanks for flagging it!

Also — congrats on making it so far through the Grasshopper app; that’s really impressive!!


Thanks for the quick answer! Now it works like a charm.

1 Like

Having trouble. I have some keys not functioning as they should so I can finish the code. I am unable to put the part in “time=time-100.” I’ve tried everything I can think of to hopefully get it to allow me to have the “str” key available but nothing works. Here is a screenshot of where I’m stuck.

1 Like

Hey @Miagi18,

To simplify this puzzle, and focus on assessing the concepts you’ve learned, we removed the need to use a time variable. Rather than the balloon falling faster each time it’s duration is set static at 2000 milliseconds (i.e. .duration(2000)).

You look to have everything else correct — you just need to remove the variable declaring time, and the reference to time inside the function, then set .duration(2000) rather than .duration(time).

It does look like we missed the need to reference the duration of 2000 inside the function — we’re updating that now so thanks for posting this!

Heather :slight_smile:

Thank you very much! That definitely fixes my problem!


I found a bug i guess (im not english maybe i dont understand it right)…
Thanks for letting me know and thanks for this cool apps! 5/5

Ok i just had to put 2000 and delete the var time :sweat_smile:

1 Like

I have been using the steps from the grasshopper Support. But I got stucked at this paragraph. {
You’ll see that ‘cx’ is moving, but ‘cy’ still isn’t resetting! That’s because the ‘cy’ attribute is busy – it’s still animating the transition that started running when you clicked the ballon last time (a new transition will stop the old one, but an attr on its own will be ignored if there’s a transition running.) To overcome this, you need to use .interrupt() before the “reset” comman}. But what did it mean by “reset”. Which is the reset in my code.

Hope you help me.

Hey @Barbarians,

You are very close to finishing this — you’re just missing an .interrupt and the ordering in your function is a back to front.

The first line of code inside your function should interrupt the falling transition. This means whenever you tap the ‘balloon’ it stops failing. On this same line of code you can add the ‘reset’, which is simply moving the ‘balloon’ back to the top of the screen. The code should look something like circle.interrupt().attr('cy', 35).attr('cx', pickRandom(position).

After that, should be the falling transition (which you currently have correct).

And that’s it!

Let me know if you have more questions,
H :slight_smile:

Hii, can you please help me out? I’m stuck with this…the code runs like a charm but doesn’t seem to get accepted by the app as the correct code…what am I doing wrong?

I have the solution bellow and it’s working exactly as in example but still i can’t finish this level
Please someone give me a clue

Hey @Alin-Manuel_Chiovean,

The .interrupt() should be the first thing that happens to the circle, so that its falling motion is interrupted as soon as it is tapped. Try adding .interrupt() before the positioning of the circle at the top of the screen, rather than in the transition chain.

Hope this helps a little!
H :slight_smile:

This task is strange. It considers solution that doesn’t work as correct and the code that works the same as example is incorrect. Quite disappointing. :pensive: