Readit News logoReadit News
Posted by u/trizoza 3 years ago
Show HN: I made a pretty relaxing puzzle gamerotaboxes.com...
I had the concept in my head for some time and firstly just prototyped it using only HTML & CSS. Sent it to a few friends and they liked it so I made it into its own website and added few 'competitive' features like click counter and share button.
vesinisa · 3 years ago
It's nice but could you make it so that the rotation direction can additionally be toggled by holding down shift while clicking? I find it very irritating to always move the mouse to the bottom right corner to select the rotation direction - especially since "every click counts".

Other than that, I first thought that some of the tiles should start with correct orientation but soon realized that would make this puzzle just really easy, because our brains are just excellent at seeing the correct image from just a few correctly oriented tiles I think.

MikeTheGreat · 3 years ago
Shift-click is a great idea.

I also like the idea of right-clicking to rotate the other way (so click always rotates one way, right-click the opposite)

I ignored the ideal clicks thing and really enjoyed slowly revealing today's picture of the lounging cat. Very relaxing indeed!

mistermegabyte · 3 years ago
Awesome game. I agree that left click to rotate left and right click to rotate right would be so much more convenient.
geros · 3 years ago
Change cursor to match rotation icon.
Aardwolf · 3 years ago
Shift click wouldn't work on mobile. Imho, just make 3 rotations in a row count as 1
the_cat_kittles · 3 years ago
another option be to have clicking the left side of the tile turn it counter clockwise and right side clockwise
quickthrower2 · 3 years ago
Another option: clockwise only rotation. Then adjust the ideal number of clicks accordingly
hnfong · 3 years ago
Implement right click for the other direction?
Someone · 3 years ago
An alternative is to change the scoring system, and count consecutive clicks on the same tile as ‘one’

Alternatively, just count three consecutive clicks that are close in time as one.

trizoza · 3 years ago
Nice suggestion! How should that behave on mobile? Any idea on how to best tackle it?
woogley · 3 years ago
I think you should lean into this problem and just call the game "clockwise"

Consistent across platforms, consistent "ideal" count, clever-ish game name

bbx · 3 years ago
I would have suggested having 2 zones per tile: one to rotate left, one to rotate right. But the tap zone is quite small already, so it's prone to errors.

One slower but more UX-friendly option would be to allow long-press on a tile, it would zoom in, and you can pick left or right with each button.

Double tap is also an option but you need to remove the ability to select the content of the page.

didsomeonesay · 3 years ago
Maybe you could try swipe left/right or rotating gestures that snap to 90 degree increments.

That is, rotating with one finger by holding and dragging either in circle or straight line.

Better not the two finger rotation known from map apps.

bambax · 3 years ago
Or: pull down for rotate CCW, pull up for rotate CW. Just sum up event.movementY to calculate rotations.

Cons: A little slower than simply clicking, maybe, and makes it easier to overshoot. Need to count rotations instead of clicks.

Pros: Quite intuitive (that's how dials work in most DAWs for instance) and would work well on mobile, even if the tile size is small.

w-m · 3 years ago
Click left half of square for ccw rotation, click right half of square for cw rotation.
tcmb · 3 years ago
Short tap for CW, hold for CCW
kiru_io · 3 years ago
Not sure how easy it is to implement, but here is another idea: hold on the tile few seconds, then you have the choice to swipe left or right (has also some edge cases, when the elements are in the corner)
huhtenberg · 3 years ago
Tap-and-hold a tile, move finger outside of it and then rotate by moving finger around tile's center (like using a handle that you just extended from the tile).
dncornholio · 3 years ago
Double tap
dhc02 · 3 years ago
Long press?
m4lvin · 3 years ago
Or use scroll-up and scroll-down to rotate left/right?
l2silver · 3 years ago
I might just get rid of rotate all together
huhtenberg · 3 years ago
It's not uncommon for right-clicks to be blocked at the browser level.

A better option would be Ctrl-left-click for the other direction.

RadiozRadioz · 3 years ago
Who is blocking these? Paranoid corporates?
vesinisa · 3 years ago
Right click is often blocked, but Shift+Click is not.
sph · 3 years ago
Blocked by whom?
CobrastanJorji · 3 years ago
I like how well this specific picture works for this puzzle. The coastline lines up perfectly with a square border. The cat's face is sideways. The two steps are the same color, so the rotation could be in one of two possible positions. It makes it just tricky enough to make the right answer not immediately obvious, but it's not so hard that there's any chance for being frustrated. Plus, it's a kitty.
rouxz · 3 years ago
"Relaxing" and at the same time counting number of clicks right next to Ideal number of clicks doesn't work very well for me :(
JrProgrammer · 3 years ago
I agree. I liked the idea but seeing an ideal number just puts pressure on something that shouldn't be.

Maybe create a casual/competitive toggle?

Anyways good job OP :)

Markoff · 3 years ago
Try Prune, the most relaxing game I played in years.

http://www.prunegame.com

And while you are at it follow it by watching Tales from the loop, most relaxing TV show I've seen in years.

TrueGeek · 3 years ago
Thanks for recommending Tales From the Loop. What a beautiful show.
cheapliquor · 3 years ago
Right - I only noticed the "ideal" number of clicks after I had finished the puzzle. That kinda diminished the "relaxing" aspect and made me want to go back and start speedrunning.

Otherwise, neat lil game. I got a nice picture of a kitty cat. :)

larsonnn · 3 years ago
So you are the one which needed to go back.
blurrybird · 3 years ago
Agreed, I needed to de-stress so I clicked through.

When I finished the back of my neck tension that I didn’t realise I had disappeared.

Most stressful thing I’ve done all week. Got 33/33 though so that’s neat.

boringg · 3 years ago
I'd agree get rid of any competitive features so that its relaxing but if you want to make it competitive toggle it on.
indigodaddy · 3 years ago
It could just reveal the # of click stats after completion
bambax · 3 years ago
Solver in 0 clicks:

    [...document.querySelectorAll("#game > div > div")].forEach(e => e.style.transform="rotate(0deg)")
It doesn't win the game, but can at least save the "preview" clicks.

eutectic · 3 years ago
An actual solver in Python:

    import numpy as np
    from mip import Model, xsum, minimize, BINARY

    def solve(tiles):
        rotations = [[[] for _ in row] for row in tiles]
        rot_vars = [[[] for _ in row] for row in tiles]
        model = Model("rotaboxes")
        for i, row in enumerate(tiles):
            for j, tile in enumerate(row):
                for _ in range(3):
                    tile = tile.transpose((1, 0, 2))[::-1]
                    rotations[i][j].append(tile)
                    rot_vars[i][j].append(model.add_var(var_type=BINARY))
                model += (xsum(rot_vars[i][j]) == 1)
        costs = []
        for i, row in enumerate(tiles):
            for j, tile in enumerate(row):
                for (di, dj) in [(0, 1), (1, 0)]:
                    if (i + di >= len(tiles)) or (j + dj >= len(tiles[0])):
                        continue
                    for r0, t0 in enumerate(rotations[i][j]):
                        for r1, t1 in enumerate(rotations[i + di][j + dj]):
                            if di:
                                a, b = t0[-1], t1[0]
                            else:
                                a, b = t0[:,-1], t1[:,0]
                            n = np.square(a - b).mean()
                            d = np.square(a[1:] - a[:1]).mean() + np.square(b[1:] - b[:1]).mean()
                            e = 2. * n / (d + 0.01)
                            v = model.add_var(var_type=BINARY)
                            model += (v >= rot_vars[i][j][r0] + rot_vars[i + di][j + dj][r1] - 1)
                            costs.append(e * v)
        model.objective = minimize(xsum(costs))
        model.optimize()
        solution = [[[r for v, r in zip(vs, rs) if v.x >= 0.99][0] for vs, rs in zip(row0, row1)] for row0, row1 in zip(rot_vars, rotations)]
        return solution

bambax · 3 years ago
Actual solver that does win the game:

    document.querySelectorAll("#game > div > div").forEach(e => {
        const rotation = e.style.transform.match(/(\d+)/)[0];
        const clicks = 4-(rotation/90)%4;
        [...Array(clicks)].forEach(i=>e.click());
    });
It could be optimized to change the rotation direction depending on whether the current rotation is smaller or larger than 180deg, but that's not really necessary since running the script only counts as one click, and generates negative "overspin" numbers ;-)

mahathu · 3 years ago
Instead of the array spread syntax, why not:

    for(let i=0; i<clicks; i++){ e.click() };

prox · 3 years ago
What does […Array mean in this context? Does it create an array?
kidsil · 3 years ago
Just wondering - why are you spreading the result to an array?

  document.querySelectorAll("#game > div > div").forEach(e => e.style.transform="rotate(0deg)")
Works too.

bambax · 3 years ago
You're right!

(But since querySelectorAll returns a NodeList and not a regular array, some methods are unavailable, so I just have this habit of making it an array. But for iteration that's indeed not needed.)

ComodoHacker · 3 years ago
Now you should count keystrokes for your type of solution.
bombcar · 3 years ago
This is nice. I just liked clicking to see the cat.
rwky · 3 years ago
That is one chilled out cat
trizoza · 3 years ago
Thanks! Glad you liked it!
drivers99 · 3 years ago
Some of the squares are basically a solid color (not so much the cat picture but the previous ones I checked). I like to do jigsaw puzzles and one good thing about them is even in fairly solid color areas, you get a good confirmation by pieces fitting together well. Something to think about when selecting photos.
trizoza · 3 years ago
Yeah, apologies for that. There is no.4 that's extremely difficult, especially on phones with not such great colours and there's one more that has 2 tricky squares. I'm trying to pick pictures that do not have solid squares for future.
prismatix · 3 years ago
Agreed. In Tabletop simulator Jigsaw Join the pieces fuse together when they're in the correct place. Maybe the white border could disappear between pieces in the correct place - although that might make it too easy if there's only one left.
jefozabuss · 3 years ago
Epilepsy warning: if you finish it you might have a page refresh bug where it constantly keeps refreshing (with flashing content) the page - for me it was solved by clearing localStorage (or just close the page I guess), I think this bug needs to be fixed ASAP.
trizoza · 3 years ago
Apologies for that. It was a bug I introduced that happens only in different timezones. Should be fixed now.
CleanCoder · 3 years ago
Can you elaborate on what you mean by "happens only in different timezones?" It sounds like an interesting bug to identify.
ranguna · 3 years ago
That didn't happen for me, either it was fixed in 20 mins or I don't know.
amarant · 3 years ago
Happened to me, chrome on Android. Likely there is some precondition required to trigger the bug other than winning the game, since it doesn't seem to happen to everyone
boudra · 3 years ago
Same here, on Firefox.
LLyaudet · 3 years ago
Me too.