Show HN: I made a pretty relaxing puzzle game
rotaboxes.com
rotaboxes.com
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.
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!
Alternatively, just count three consecutive clicks that are close in time as one.
Consistent across platforms, consistent "ideal" count, clever-ish game name
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.
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.
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.
A better option would be Ctrl-left-click for the other direction.
Maybe create a casual/competitive toggle?
Anyways good job OP :)
And while you are at it follow it by watching Tales from the loop, most relaxing TV show I've seen in years.
Otherwise, neat lil game. I got a nice picture of a kitty cat. :)
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.
[...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. 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 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 ;-) for(let i=0; i<clicks; i++){ e.click() };https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
Array(length) creates an array that has a length but no elements (or weird, "empty" elements). The square brackets create a new array [...Array(length)] which will have undefined elements instead, as trying to access an "empty" element returns undefined.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guid...
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
(In python there is the "*" operator which should be equivalent: [1, 2, *arr].
Array(clicks) instantiate an array of length 'clicks', with its elements undefined.
Then "[...Array(clicks)]" takes the above array instance and spreads it as content in another array.
Seems redundant and they could've just used Array(clicks).
Not undefined elements but no elements, or "empty" elements.
> they could've just used Array(clicks).
No, because the following forEach call does nothing for such an array. You need to fill the array first with Array(clicks).fill() or shorter, [...Array(clicks)]
document.querySelectorAll("#game > div > div").forEach(e => e.style.transform="rotate(0deg)")
Works too.(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.)
Perhaps an option to hide the ideal clicks. If I was upset and using this to calm down (which I totally will!) it would just infuriate my messed up brain. But that's just me.
Well done!
Would be interesting if you combined it with DALLE-2. Either with a prompt at the top that generates the picture on the fly or just by curating some DALLE-2 pictures and using them for the puzzles (and maybe the prompt to generate it could be revealed as a reward).
This would be a lot less annoying, and involve fewer clicks, if you just had left click rotate one way and right click rotate the other way.
That app also implements the solution here, of having a toggle that swaps the effect of press and long-press. I use that... sometimes. Rarely. But more often than I attempt to long-press.
Cell phones have a bad UI paradigm and therefore using software on a cell phone is generally more painful and annoying than using software on a computer. But that's not a reason to force painful, annoying UI into the computer too.
[1] https://www.chiark.greenend.org.uk/~sgtatham/puzzles/ https://f-droid.org/en/packages/name.boyle.chris.sgtpuzzles/
I can't remember the name but I think it came as a CD with some encyclopedia for kids or something like this. You unlocked a memory of me solving the puzzle of a picture of a shark :D
Other than that, I enjoyed it.
Tiles still in wrong position ............ 24?
Shameless plug for a multiplayer puzzle game I created a year ago https://flipcards.online of which your game reminded me. Although mine has nothing relaxing as it favours competition. But rotating tiles of images is clearly checked.
I really like what Chris has done with Liveblocks.io on his multiplayer Wordle: https://github.com/CTNicholas/wordle-wars
The cat one was enjoyable though!
Some pictures were hard to distinguish they still needed to be turned (like 95% mountain and a sliver of something else).
I’d consider making the background already in place - i find rotating the cat the most enjoyable. Lining up a cloud or shoreline starts to feel tedious to me.
I was slightly annoyed at the dog puzzle, while i tried to rotate the boxes which contained just grass and a lot of bokeh. I guess picking the right pictures is really important.
blurdle.cc
Otherwise fun little game.
Enjoyed the game though, nice and simple. And no hug of death yet, well done!
It looks like it's always the same picture? It would be nice if you could play this with a random picture.
also, as everyone probably, right-click to rotate counterclockwise came intuitively real quick in thoughts...
You could do a hex tile version as well
23 Nov 22 31/29 clicks rotabox.es/29
The expected (in statistical sense) number of rotations needed is 32 but it could be as low as 24.
Now that I think it better that means the shuffle was fixed.