GithubHelp home page GithubHelp logo

hexworks / mixite Goto Github PK

View Code? Open in Web Editor NEW
189.0 20.0 31.0 1.03 MB

A GUI agnostic hexagonal grid library. Supports a multitude of grid layouts including hexagonal, triangular, rectangular and more.

License: Apache License 2.0

Kotlin 100.00%
hexagonal-grids hexagonal-grid-library hexagon hexagons game-development

mixite's People

Contributors

adam-arold avatar blaine-dodson avatar drekbour avatar holdyourwaffle avatar killpackoff avatar knightofiam avatar lucyletour avatar migepatschen avatar monkeywithacupcake avatar pubudug avatar seveen avatar sidem avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mixite's Issues

Create an adapter interface for storing grids

The current in memory implementation should implement it. This is the first step towards the Hexagonal Architecture milestone. All data operations (storing/fetching) on Hexagons and the HexagonalGrid should be abstracted away in the interface.

Accessing boolean fields in Kotlin using `is` prefix: `isSomething()`

Kotlin is not my forte, so this might not be possible. Boolean fields have getter methods prefixed with get and not is.
But I'm currently in the process of implementing SatelliteData and Lombok is not playing nice with these methods since they break naming convention. (https://github.com/Hexworks/mixite/blob/master/mixite.core/core/src/main/kotlin/org/hexworks/mixite/core/api/contract/SatelliteData.kt#L20,L30).

On another note, awesome library! Excellent work.

Cannot use the library in Android

When using hexameter in Android I receive the error message:

`AGPBI: {"kind":"error","text":"trouble processing "javax/xml/parsers/DocumentBuilder.class":","sources":[{}]}

AGPBI: {"kind":"error","text":"Ill-advised or mistaken usage of a core class (java.* or javax.*)","sources":[{}]}

AGPBI: {"kind":"error","text":"when not building a core library.","sources":[{}]}

AGPBI: {"kind":"error","text":"This is often due to inadvertently including a core library file","sources":[{}]}

AGPBI: {"kind":"error","text":"in your application\u0027s project, when using an IDE (such as","sources":[{}]}

AGPBI: {"kind":"error","text":"Eclipse). If you are sure you\u0027re not intentionally defining a","sources":[{}]}

AGPBI: {"kind":"error","text":"core class, then this is the most likely explanation of what\u0027s","sources":[{}]}

AGPBI: {"kind":"error","text":"going on.","sources":[{}]}`

... and so on.

That dependency of a core class is somewhere in hexameter-core. I use the version 3.0.0 of that library.

Provide strict getByPixelCoordinate(x,y)

This is an enhancement request.

The current implementation of getByPixelCoordinate() provides the nearest hexagon when called with a pixel which lies outside the grid but within the distance of one hexagon. It is therefore an approximation. This makes good sense for many applications whereby a user is clicking a screen pixel, and some tolerance is acceptable. There are certain use cases however, such as the binning of points into hexagons which require a guarantee that the coordinate lies within the hexagon.

While this behaviour remains, a workaround for this scenario is proposed as:

  1. Instantiate a grid that is 1 hexagon larger all around than necessary. Should the hexagons be used on multiple adjacent canvases (e.g. on map tiles) whereby the grid is further offset to ensure adjacent hexagons align, then a larger buffer is recommended. Note for flatTop you need to increase by 2 hexagons left and right to achieve 1 complete hexagon.
  2. Offset the coordinates by the buffer size. (e.g. for flat topped hexagons with a buffer of 4 hexagons horizontally (2 left, 2 right) and 2 vertically, the offsetX is 1.5*hexWidth, and the offsetY is 1*hexHeight before calling getByPixelCoordinate(x,y)
  3. Compensate at rendering time by adjusting the vertices of the hexagon by the same offset.

As a quick fix I suggest adding a sentence in the Javadoc for the method as follows:

Note that at the boundaries this is a lenient match. When the pixel provided does not fall within a hexagon on the grid, but is within a close distance of the grid, the nearest hexagon will be returned. Where strict hexagon matching is required, please refer to the workaround offered on https://github.com/Hexworks/hexameter/issues/32

Deprecate/remove Hexagon.vertices

Every Hexagon contains 6 Points then 12 "vertices" which are just the x,y of each Point. Get the Point...

    /**
     * Returns a list containing the [Point]s of this [Hexagon].
     */
    val points: List<Point>

    /**
     * Returns an array of the vertices of this [Hexagon].
     */
    val vertices: List<Double>

Perhaps it was meant to be an Array of primitive types? (doc clearly says array in contradiction to the actual type).

The Maybe

Could you provide documentation for the Maybe class. Specifically:

  • Why does getSatelliteData() return a Maybe?
  • What does it mean when the Maybe is empty?

Get rid of Lombok

Lombok proved to be a nuisance and it acts as a barrier for possible contributors. It also interferes with coverage and adds mental overhead.

Map import/export functionality should be implemented

The format of the map file is as follows:

{
  "name": "testmap", // name of the map (parameter)
  "version": "1.0.0", // version of the map format
  "width": 4, // width of the map
  "height": 3, // height of the map
  "radius": 40.0, // radius of the hexagons
  "orientation": "POINTY_TOP", // enumerated: POINTY_TOP or FLAT_TOP
  "layout" : "RECTANGULAR", // enumerated: RECTANGULAR, HEXAGONAL, TRIANGULAR, TRAPEZOID, EMPTY
  "tilesetUrl": "http://example.com", // the url of the tileset. the tileset defines the tileIds as well
  "cells" : [
    [0, 0, 1, 1.0, 1] // x, z, isPassable, movementCost, tileId
  ]
}

Since map import/exports are not part of the core functionality it goes to the hexameter-util module.

Draw to world scale and coordinates

Hi,

I stumbled upon your excellent work here, thinking to use it on my project. After spending a day tinkering with it, I sadly concluded that it may not be possible, since it seems to be based on a pixel format.

I'm using LibGDX where my game world is logically scaled to 1 world unit: 32 pixels. When I try to render a grid, for example, 100 world units long and wide, with a radius of 0.7, the library fails to resolve the hexes, drawing lines and triangles of what I think are what's supposed to be the hex. I have to use the pixel size, to get it to draw, but then, the hexes and grid are too large. The only way I got things to draw at the appropriate scale is to affect the polygon drawer, scaling its matrix down, to draw smaller.

Needless to say, while I finally got the grid to draw to size, the rest of the library can't work under these conditions. Stuff such as getting the grid coordinates, or coordinates through pixel, resolve wrongly due to the scaling, especially getting the center of each hex, which I need to properly place objects within hexes.

I know it's likely a lot of work on your part, so this is just a suggestion to have the library be able to use world coordinates, instead of pixels units. Most, if not all, game development frameworks strongly urge developing under world coords, to simplify development, and not have to worry about resolution etc, across platforms such as mobile devices. This would make your library a perfect fit as a drop-in solution for Java-based game dev, as there aren't any existing solutions out there, and people have to, basically, roll their own.

After saying all this, I realize that, if this works for Android dev, it might already have a means to work in world scale. If so, please advise.

Thanks, and great job regardless!

External Bounding Box has negative height

call to Hexagon.getExternalBoundingBox() returns a negative value for height.

``@Test
public void negativeHeight() {
HexagonalGridBuilder builder = new HexagonalGridBuilder()
.setGridHeight(3)
.setGridWidth(3)
.setGridLayout(HexagonalGridLayout.HEXAGONAL)
.setOrientation(HexagonOrientation.FLAT_TOP)
.setRadius(138);
HexagonalGrid grid = builder.build();
Hexagon hex = (Hexagon) grid.getHexagons().iterator().next();
Rectangle rect = hex.getExternalBoundingBox();
assertTrue(rect.getHeight()>0); // [207.0, 358.5, 276.0 ,-239.0]
}```

Iterable should be lazy when getHexagons is called

The Iterable returned by getHexagons should lazily create Hexagon objects only when iterating over them. The point of this feature is to be able to iterate over Hexagons without keeping them all in memory. This will be useful when the user wants to stream the data for an 1000 * 1000 grid to an ui.

Add Java sample project

Now Mixite is written in Kotlin (still a new kid on the block), it suddenly becomes a little scary for Java devs (despite saying Don't Panic on the cover). It might do well to provide a basic Java usage of mixite.core both

  • Candy for Java-only eyes (can be linked to from README.md)
  • Regression testing the Java-facing API (c.f. #42)

Just an idea: Api is very restricted and so it cause a lot performance problem

I see this code base were left behind but i still want to raise this issue, maybe if someone has issue with performance can learn from it.

Would be great functions for be able to avoid creating a Hexagon and using instead CubeCoordinate would improve performance drasticly.

For example one of the mostly used function is the getNeighboursOf.

Firstly i am ok with the current one if you really need the list of hexagon neighbours.
I am writing about the cases when you do not need the hexagon(the most cases as they likely wont change position once they are created, if they move you just change the projection and so theri coordinate wont be affected)

So here are my results with using only CubeCoord:

getNeighboursOf on 100x100 grid(sure the grid size does not matter for neighbours, only maybe for looking up time in the storage)

Using hexagons:
Avg Duration: 2.991 seconds

Using CubeCoord only:
Avg Duration: 0.139 seconds

So roughly 20x improvent and so it could be improved even further beyond.
It also uses the user's collection to avoid object creation, it is nice and much more fitting for a game.

The code:
override fun getNeighborsOf(coordinate: CubeCoordinate, outputCollection: HashSet) {
for (i in NEIGHBORS.indices) {
val cube = getNeighborCoordinateByIndex(coordinate, i)
if(hexagonDataStorage.containsCoordinate(cube)){
outputCollection.add(cube)
}
}
}

Test:
long start = System.currentTimeMillis();

    for(int i=0; i<1000000; i++) {
        arr.clear();
        grid.getNeighborsOf(hexagons[18].getCubeCoordinate(), arr);
    }

    long end = System.currentTimeMillis();

SatelliteData class not encouraging immutability

This might not actually be desirable for other implementations right now, but it might be good to include in the next major version release.
Basically SatelliteData currently requires that you override setter methods if you implement the interface directly. If the calculators require this benefit of mutability, then there's not a nice way around this.
However, I'm trying to define my own class of data for a hex, and I want those objects to be immutable. If the board state changes, I want to be able to place newly constructed satellite data objects on those hexes in the grid.

So, this is barely a big deal since I can still just override them to have them do nothing anyway, but it does look like this:

public class MySatelliteData implements SatelliteData
{
    . . .

    public void setPassable( final boolean passable )
    {
        return;
    }

    public void setOpaque( final boolean opaque )
    {
        return;
    }

    public void setMovementCost( final double movementCost )
    {
        return;
    }

    . . .
}

Definitely just being nit-picky with this one. Immutability is definitely a good practice to be eliciting. It does result in a tad less flexibility from this library, but you are probably more than likely saving a consumer from potentially getting themselves into trouble via mutability.

Create getGrid_() methods for debugging pursposes for HEXAGONAL grid layout

This is a feature suggestion.

Currently the methods getGridX(), getGridY(), getGridZ() of the CubeCoordinate class show the grid cube coordinates with the origin (0, 0, 0) on the top left, which is outside of the grid if the layout is HEXAGONAL. Having the origin in the center of the grid would be more useful.

SatelliteData interface should be optional

As an API interface SatelliteData is actually a very opinionated choice of data. There is no hard requirement for any enforced supertype to the storage data (e.g. the core class, HexagonalGridImpl, doesn't use it even once). SatelliteDataexists so Mixite can supply some useful algorithms via the extendedHexagonalGridCalculator. If the user doesn't need movementCostorisPassableorisOpaquethen it's just cruft (note for examplemovementCost` is not used anywhere in the code base!).

Ergo, SatelliteData interface should be optional.

However, those additional utilities are very useful and key part of the value of this library.

Deprecate/remove HexagonOrientation.coordinateOffset

This value is only used in a single internal algorithm (HexagonImpl#calculatePoints). Many other similar calculations operate by checking the orientation rather than redirecting through it.

Mixite should be consistent and internalise this value?

Eliminate the coordinates object from HexagonalGridImpl

This is the current major bottleneck which affects memory usage. The GridData instance in HexagonalGridImpl holds all the necessary information for generating the possible coordinates for a given grid so we need to work around this.

As part of this task HexagonalGrid#containsCubeCoordinate also needs to be refactored. The implementation should delegate to the GridLayoutStrategy since it is used to fetch the coordinates in the first place.

External Bounding Box has incorrect Y value

Height of a pointy top hex of radius is 2*138 = 276. When the centerY of a hex is 138 the y value of the bounding box should be zero. This is not the value returned by getExternalBoundingBox() .

``
@test
public void yValue() {
HexagonalGridBuilder builder = new HexagonalGridBuilder()
.setGridHeight(3)
.setGridWidth(3)
.setGridLayout(HexagonalGridLayout.HEXAGONAL)
.setOrientation(HexagonOrientation.POINTY_TOP)
.setRadius(138);
HexagonalGrid grid = builder.build();
Hexagon hex = (Hexagon) grid.getHexagons().iterator().next();
Rectangle rect = hex.getExternalBoundingBox();
double ctrY = hex.getCenterY(); // 138
double ht = 2*138;
assertEquals(ctrY - ht/2, rect.getY(), 0.01f); // expected 0, actual 207
}

unable to compile when getSatelliteData() is called

When an application uses getSatelliteData() there is a compiler error:

...\dev\test-mixite> gradle build

> Task :app:compileJava FAILED
...\dev\test-mixite\app\src\main\java\test\mixite\App.java:29: error: cannot access Maybe
            h.getSatelliteData();
             ^
  class file for org.hexworks.cobalt.datatypes.Maybe not found
1 error

FAILURE: Build failed with an exception.

To reproduce the error, build a grid and attempt to access the satellite data:

package test.mixite;

import org.hexworks.mixite.core.api.Hexagon;
import org.hexworks.mixite.core.api.HexagonalGrid;
import org.hexworks.mixite.core.api.HexagonalGridBuilder;
import org.hexworks.mixite.core.api.defaults.DefaultSatelliteData;

public class App {
    public static void main(String[] args) {
        
        HexagonalGridBuilder<DefaultSatelliteData> builder = new HexagonalGridBuilder<DefaultSatelliteData>()
            .setGridHeight(9)
            .setGridWidth(9)
            .setRadius(30.0);
        HexagonalGrid<DefaultSatelliteData> grid = builder.build();
        
        for (final Hexagon<DefaultSatelliteData> h : grid.getHexagons()) {
            h.getSatelliteData();
            // ^error here
        }
    }
}

The error occurs whether using the latest release, or the latest commit:

dependencies {
    implementation 'com.github.Hexworks.mixite:mixite.core-jvm:2018.2.0-RELEASE'
    // ^ this works
    // implementation 'com.github.Hexworks.mixite:mixite.core-jvm:2020.1.0'
    // ^ this fails
    // implementation 'com.github.Hexworks.mixite:mixite.core-jvm:master-SNAPSHOT'
    // ^ this fails
}

The problem is not present in the 2018.2.0-RELEASE

Let me know if there is more information that I can provide. Thank you.

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.