All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.codeheadsystems.gamelib.hex.manager.HexFieldSearchManager Maven / Gradle / Ivy

/*
 *   Copyright (c) 2022. Ned Wolpert 
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 *
 */

package com.codeheadsystems.gamelib.hex.manager;

import static com.codeheadsystems.gamelib.core.util.LoggerHelper.logger;
import static com.codeheadsystems.gamelib.hex.utilities.MathConverter.toFloat;
import static java.lang.Math.sqrt;

import com.badlogic.ashley.core.ComponentMapper;
import com.badlogic.ashley.core.Entity;
import com.badlogic.gdx.utils.Logger;
import com.codeheadsystems.gamelib.hex.component.HexComponent;
import com.codeheadsystems.gamelib.hex.model.Hex;
import com.codeheadsystems.gamelib.hex.model.HexField;
import com.codeheadsystems.gamelib.hex.model.Layout;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Singleton;

/**
 * Provides the ability to search a hex field.
 */
@Singleton
public class HexFieldSearchManager {
    private static final Logger LOGGER = logger(HexFieldSearchManager.class);
    private final ComponentMapper hm = ComponentMapper.getFor(HexComponent.class);
    private final HexManager hexManager;

    @Inject
    public HexFieldSearchManager(final HexManager hexManager) {
        this.hexManager = hexManager;
        LOGGER.debug("HexFieldSearchManager()");
    }

    public Map hexEntityHashMap(final Set entities) {
        return entities.stream()
            .collect(Collectors.toMap(this::hexForEntity, e -> e));
    }

    public Hex hexForEntity(final Entity entity) {
        return hm.get(entity).hex();
    }

    /**
     * Provides a way to convert a point to a hex that can then be used for a search function.
     *
     * @param x              from the layout. Must be unprojected from the screen. (See camera manager)
     * @param y              from the layout. Must be unprojected from the screen. (See camera manager).
     * @param layout         to be used.
     * @param searchFunction the search function.
     * @return whatever type they found.
     */
    protected  Optional fromPoint(final float x,
                                        final float y,
                                        final Layout layout,
                                        final Function> searchFunction) {
        // Convert the point on the screen to the whole field, based on the camera.
        final float layoutX = x - layout.origin().x;
        final float layoutY = y - layout.origin().y;
        // Convert the point to a fractional q/r/s via https://www.redblobgames.com/grids/hexagons/#pixel-to-hex
        final float fractionalQ = toFloat(2. / 3 * layoutX) / layout.size().x;
        final float fractionalR = toFloat(-1. / 3 * layoutX + sqrt(3) / 3 * layoutY) / layout.size().y;
        final float fractionalS = -fractionalQ - fractionalR;

        // Finally, getting the hex by converting to an integer q/r/s based on where the fractional q/r/s was in the hex.
        // https://www.redblobgames.com/grids/hexagons/#rounding
        int q = Math.round(fractionalQ);
        int r = Math.round(fractionalR);
        int s = Math.round(fractionalS);
        final float q_diff = Math.abs(q - fractionalQ);
        final float r_diff = Math.abs(r - fractionalR);
        final float s_diff = Math.abs(s - fractionalS);
        if (q_diff > r_diff && q_diff > s_diff) {
            q = -r - s;
        } else if (r_diff > s_diff) {
            r = -q - s;
        } else {
            s = -q - r;
        }
        Hex checkHex = null;
        try {
            checkHex = hexManager.obtain().set(q, r, s);
            // finally, lets see if anything is there.
            return searchFunction.apply(checkHex);
        } finally {
            if (checkHex != null) {
                hexManager.free(checkHex);
            }
        }
    }

    /**
     * Note, the x/y here must be in the same space that was used for the hex map. This likely needs conversion
     * from the layout to work correctly.
     *
     * @param x               mouse point.
     * @param y               mouse point.
     * @param layout          the layout of the hex field.
     * @param hexComponentSet we are looking at.
     * @return
     */
    public Optional fromPoint(final float x,
                                            final float y,
                                            final Layout layout,
                                            final Set hexComponentSet) {
        return fromPoint(x, y, layout, h -> hexComponentSet.stream()
            .filter(hc -> hc.isHex(h))
            .findFirst());
    }

    /**
     * Note, the x/y here must be in the same space that was used for the hex map. This likely needs conversion
     * from the layout to work correctly.
     *
     * @param x        mouse point.
     * @param y        mouse point.
     * @param hexField we are looking at.
     * @return
     */
    public Optional fromPoint(final float x,
                                      final float y,
                                      final HexField hexField) {
        return fromPoint(x, y, hexField.getHexFieldLayout().layout(), h ->
            Optional.ofNullable(hexField.hexEntityHashMap().get(h)));
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy