flauwekeul / honeycomb

Create hex grids easily, in node or the browser.
https://abbekeultjes.nl/honeycomb
MIT License
631 stars 57 forks source link

[2.0] Model-View Separation #21

Closed grandsong closed 5 years ago

grandsong commented 5 years ago

This one is fundamental.

After dicussion about relations between hexes and grids, I recalled your "viewless" idea.

That sounded strange for me when I saw it since it is very clear that methods like toPoint and Grid.pointToHex() are all about view. And directions of ''NW' is also about view.

Now I think I can guess what the urge behind your idea is.

You are against more props like border in Hex because Hex was originally a model object.

In fact, the redblobgames.com blog post is all about model.

You might had already felt uneasy when you added size and toPoint to Hex but the seemingly obvious necessity dispelled the feeling. Then border looked to you not so seemingly necessary, so the feeling came back.


Now, let's go further, and take a leap of faith.

Why should ANY view-related job be in Hex?

My answer is no.

I suggest you remove size and toPoint from Hex.

And also deport view-related things from Gird.

Then, add a class GridView to handle those things, dedicatedly.


A not uncommon requirement in games is to have a minimap along with the main map. ( eg The Battle for Wesnoth which I plan to study from)

The models are identical. Just two very different views.

Another case is that now I use SVG.js but maybe someday later I decide to migrate to PixiJS. I won't like to modify code within Hex and Grid in the duration.

And what if a user need to use tilted hexes for pseudo 3D?


So, what will be the relations like?

Hexes and grids never care about view. Whenever a grid changes, it emits to related GridViews. For example, if you move a hex in a grid, just change their models and tell GridViews about the change.

So, the side of a hex is set in GridView?

Yes, and can be in more than one GridViews.

It may seem counterintuitive, but how hexes look like and where their views (shapes) are in the screen are not the concerns of the hexes, or the grids.

And how mouse events affect the model?

Let GridView listens those event and calculate which hex the mouse is interacting with.

Then, GridView calls control logics about what to do next with the hex or its grid.

GridView should provide its own events, converting mouse positions into hex (just as Grid.pointToHex() did), so that control logics can easily deal the target hex out-of-boxedly.

grandsong commented 5 years ago

I've made a demo!

You can click hexes shapes which will trigger events and "eventually" make the numbers of tiles increase. Note: the starting block of code is a third-party tiny lib, which is used to enable hex instances to emit events to related objects like the tiles.

flauwekeul commented 5 years ago

It seems we have different ideas of what a view is.

To me a view encapsulates everything that has to do with rendering something on screen. In more abstract terms: projecting data. It's about how something (data, maybe in the form of a model) looks. When I say that honeycomb is viewless, I'm trying to say that it has no functionality regarding how hexes/grids are rendered.

IMO, your assumption that "it is very clear that methods like toPoint and Grid.pointToHex() are all about view. And directions of ''NW' is also about view" is wrong. Translating hexes to points and vice versa has nothing to do with how those hexes look; there's no rendering involved. A hex's coordinates (either in the form of a point or a cube) doesn't necessarily equal its x and y position on screen. The method toPoint isn't called toPixel for a reason 😉

If I were to remove size and the translation of hexes from/to points, I'd have to remove nearly all methods from Hex. Because nearly all methods use either size or a hex's coordinates.

My goal is to remain honeycomb as a viewless library (as described above) and leave the view to the user.