GithubHelp home page GithubHelp logo

gordonwoodhull / hexapipes Goto Github PK

View Code? Open in Web Editor NEW

This project forked from gereleth/hexapipes

0.0 0.0 0.0 11.6 MB

Hexagonal pipes puzzles

Home Page: https://hexapipes.vercel.app/hexagonal/5

License: MIT License

JavaScript 77.04% CSS 0.55% HTML 0.35% Svelte 22.06%

hexapipes's People

Contributors

adamburgess avatar gereleth avatar gordonwoodhull avatar joshwilsonvu avatar

Watchers

 avatar  avatar  avatar

hexapipes's Issues

Tile polygon clipping vs "the smudge"

This fork of hexapipes implements clipping of pipes to the tile polygon. Additionally, the arms are drawn 20% longer to compensate for iOS line cap rendering issues. The idea is, draw past the edge of the tile and then clip.

This was originally proposed as gereleth#101

Base hexapipes instead uses stroke-linejoin: round and extends the colored part out past the edge of the tile in order to "smudge" the subpixel line that will appear otherwise.

The smudge works better where it works, on the non-Penrose tiles and on operating systems besides iOS. The jury is still out on which is better for the cube grid.

Tile polygon clipping should be optional, and only enabled for Penrose and for iOS.

Penrose splines could be smoother

I used simple splines with the two control points set equal, because these are easy to understand. The spline is confined to a triangle formed by the three points, and tangent to two of its legs.

The points of the triangle are the center of the tile, the end of the “symbol”, and the point where the line between symbol arm ends on the two tiles intersects with the edge between them.

The final slope of the arm of one tile is the same as the starting slope of the arm on the next tile, but I think it would be smoother if the velocity of the spline going through the tile edge is the same on both sides.

IIUC this means the two control points should remain on the sides of the triangle, but their distance from the center point and edge point should be a constant. You can see this in vector drawing programs where the magnitude and direction of control points across an end point and into the next segment are mirrored.

"Arms" vs "tiles" rotation

This fork of hexapipes implements "arms" rotation, where the rotation is passed into grid.getPipesPath() and the grid is responsible for rotating the arms to match.

In base hexapipes, the entire tile is rotated and pipes don't need to be redrawn per tile.

Only PenroseGrid supports "arms" rotation, so other grids do not currently rotate their tiles when clicked.

"Arms" rotation should be refactored to be optional, and should only be applied to PenroseGrid. It could be useful for other grids where angles between arm positions are non-uniform.

Trihexagonal puzzle generation fails in this fork

Either I made a mistake when rebasing, or there are divergent assumptions in the code.

'Could not generate a puzzle with a unique solution. Maybe try again.'

This is the only grid that completely fails to appear... probably it is something stupid, and easy to fix once identified.

grid construction / initialization cleanup

The core hexapipes system assumes that a grid will be valid after construction.

This is a reasonable assumption for static grids, but works less well for the Penrose grid, which will be selected and generated randomly from an infinite space of possible grids.

To get it working, I split this grid into construction and initialization phases. This allows the grid to be replaced after construction of the grid object, but there is still an extra grid generated and then thrown away – actually two, because both the puzzle instance and the worker construct and then initialize their own grid objects!

This isn't too much of an efficiency concern, but it's messy, and it makes Penrose grids confusing to troubleshoot.

Compounding the problem, gridInfo in grids.js is initialized by constructing an example grid, and is instantiated on both the puzzle and the worker. So that means that a total of four Penrose grids get calculated and then thrown away on the Penrose pages, and two get thrown away on the other pages. An easy solution for this part is to make example grid construction lazy, and I've implemented this successfully in 86e8227, but it's a partial solution.

The correct solution would involve one of:

  1. Always construct and initialize grids separately - a constructed grid would not immediately be valid.
  2. Always wait to construct grids until we know if we have data to initialize them. Cleaner but perhaps requires deeper thought.

penrose section, region or area

Penrose pipes is too easy because of the border.

The infinite lazily-generated puzzle is possible, but

  • it's a significant engineering and algorithmic challenge
  • it would probably be unsatisfying as a game

Another possibility, as suggested by @gereleth in email, is to only require the player to solve the part of a larger puzzle within a region.

That region of the puzzle would need to be connected, so this might require a change to the generator. If any tiles outside the region are generated, they are not used.

"Region" (or section, area, portion - pick one) would be a third topology of grid, along nowrap and wrap.

Visually, the border tiles could fade out to transparent toward the border sides to indicate that those sides don't matter.

Curvy edgemarks for Penrose pipes

I copied the cube grid to get started with the Penrose grid, and so this grid inherited pointy edge marks:

image

It would be much nicer for the edge marks to be curvy like the pipes, and there are at least two ways to do this:

It will have the same effect either way. stroke-dasharray will be less code and probably easier; perhaps pathLength can be set to draw the edgemark as a portion of the total length of the pipe spline.

Tile polygon clipping is inefficient

Related to #3 flag for controlling tile polygon clipping, the implementation of tile polygon clipping is inefficient because a clipping path is created for every tile.

There only needs to be a clipping path for each base polygon, because the clip path is relative to the tile center point.

The easy way to implement this is to put the SVG clip paths into a hash and assign an ID. However, for clarity and for debugging purposes, it would be better for polygons to identify their base polygon name/ID, and use that to id their clipPath and the association with tiles.

Then there also the cube grid case, where only one clip path is needed because the square is transformed three ways.

Penrose orient/lock improvements

In the interest in getting Penrose Pipes out the door, I implemented the Orient/Lock dot using the tile transform and rotation.

This is equivalent to the cube grid implementation, where the same transforms are applied to the g.pipe, since the dot uses the same coordinate system.

This has the following weaknesses:

  • The dot is squished according to the transform, and this means it's very squished on the skinny rhombs.
  • If I extrapolate the 3D planes of all these jumbled tiles, it gives me a touch of vertigo, but it's not nearly as bad as when the pipes did were in false perspective.
  • There is no animation on the dot.
  • The dot is not perfectly centered inside its arm - ideally it should be placed on the spline at a little distance from the edge, similar to #7.

I'm not sure, but I think rotations would have to be passed into grid.getGuideDotPosition() and polygon.get_guide_dot_position() and the polygon would need to cache a dot position per direction.

It's also worth noting that this mode makes it easy to trigger #8 wrong animation for 180º turns.

Previous discussion in #6.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.