Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: loading/initializing neighbors of a tile in a grid  (Read 933 times)

0 Members and 1 Guest are viewing this topic.

JensTheNewbie

  • Newbie
  • *
  • Posts: 4
    • View Profile
loading/initializing neighbors of a tile in a grid
« on: March 27, 2024, 10:02:35 pm »
Hello, I am trying to make a hexagon grid where i later want to use the A-star algorithm to make a game later. However i have come across a problem when trying to initialize the neighbors of each hexagon-tile.
I have previously written the code in java-script so i cannot see the reason why it becomes so slow when initializing the grid.

Here is some of the code i have written
[

//how i initialize the grid
void Game::initGrid() { // initialize the grid

        // actual initialize the grid
        for (int i = 0; i < cols; i++) {
                for (int j = 0; j < rows; j++) {
                        //grid[i][j] = Tile(i, j);
                        std::cout << "Setting grid[" << i << "][" << j << "]" << std::endl;
                        grid[i][j] = Tile(i,j); // declare it exists
                        grid[i][j].initializeTileShape(255, 0, 0); // declare the tile has a shape aka hexagon
                }
        }
        // each tile needs to know their neighbors
       
        for (int i = 0; i < cols; i++) {
                for (int j = 0; j < rows; j++) {
                        grid[i][j].initializeNeighbors(i,j,*this);
                }
        }
       
}

//the Tile.h
#pragma once

#include <SFML/Graphics.hpp>
#include <vector>
#include <iostream>
//#include "Game.h"


// Forward declaration of Game class so that i can use the class here
class Game;

class Tile{
private:
        double PI = 3.14159265; // just PI
       
public:// i need to access position, Neighbors, wall or not
        //variables for construction
        double midx = 200; //it was 200 before
        double midy = 200; // it was 200 before
        double r_1 = 15;
        double r_2 = 9;
        double radius;
        double angle = 0;
        double construcangle = 18;
        double sx;
        double sy;
       
        //placement of the tile
        int xRow;
        int yRow;
        double displace=0;

        //hexagon shape
        sf::ConvexShape hexagon;

        //The neighbors to the tile. Used for pathfinding
        std::vector<Tile> neighbors;

        Tile(int x, int y) {
                xRow = x;
                yRow = y;
               
                // Second row has to be displaced
                if (yRow % 2 == 0) {
                        // std::cout << "should be displaced" << std::endl; // to see if displace works
                        displace = r_1 * cos(PI * 18 / 180.0);
                }
                //placement of the middle of the hexagon compared to its coordinate in grid
                midx = midx + displace + xRow * 2 * r_1*cos(PI*construcangle / 180);
                midy = midy + yRow * (r_1 * 2 * sin(PI*construcangle / 180) + (r_2 - cos(PI*(90 - construcangle) / 180)*r_1));
        }
        Tile() {}// just for overloading

        void initializeTileShape(int x, int y, int z);
       
        void initializeNeighbors(int i, int j ,Game& game);

        void moveTile(sf::Vector2f direction);
        void display(sf::RenderWindow& );



};

// my tile.cpp

#include "Tile.h"
#include "Game.h" // Include Game.h here
#include <SFML/Graphics.hpp>

void Tile::initializeTileShape(int x, int y, int z) {
        /*
        creates the hexagon
        */

        this->hexagon.setPointCount(6);
        this->hexagon.setFillColor(sf::Color(x, y, z));

        for (int k = 0; k < 6; k++) {
                if (k == 0) {
                        angle = PI * construcangle / 180.0;
                        radius = r_1;
                }
                else if (k == 1) {
                        angle = angle + (PI * (90 - construcangle) / 180);
                        radius = r_2;
                }
                else if (k == 2) {
                        angle = angle + ((PI * (90 - construcangle)) / 180.0);
                        radius = r_1;
                }
                else if (k == 3) {
                        angle = angle + (PI * (construcangle * 2) / 180.0);
                        radius = r_1;
                }
                else if (k == 4) {
                        angle = angle + (PI * (90 - construcangle) / 180.0);
                        radius = r_2;
                }
                else if (k == 5) {
                        angle = angle + (PI * (90 - construcangle) / 180.0);
                        radius = r_1;
                }

                sx = midx + cos(angle) * radius;
                sy = midy + sin(angle) * radius;

                this->hexagon.setPoint(k, sf::Vector2f(float(sx), float(sy)));
        }
        this->hexagon.setOutlineColor(sf::Color::Blue); //sets color of outline
        this->hexagon.setOutlineThickness(1.f); //sets the thickness

}

void Tile::initializeNeighbors(int i, int j ,Game& game) { //
       
        int cols = game.cols;
        int rows = game.rows;
        std::vector<std::vector<Tile>>& grid = game.grid;
        //std::cout << "Everything is good " << game.cols << std::endl;

        if (i < cols - 1) { // right horizontal neighbor
                neighbors.emplace_back(grid[i + 1][j]);
        }
        if (i > 0) { // left horizontal neighbor
                neighbors.emplace_back(grid[i - 1][j]);
        }
        // ctrl K C and ctrl K U
        // even rows
       
        if (j % 2 == 0 && j > 0) { // upper left neighbor for row 0,2,4,6...
                neighbors.emplace_back(grid[i][j - 1]);
        }
        if (j % 2 == 0 && j > 0 && i < cols - 1) { // upper right neighbor for  row 0,2,4,6...
                neighbors.emplace_back(grid[i + 1][j - 1]);
        }
        if (j % 2 == 0 && j < rows - 1) { // down left neighbor for row 0,2,4,6...
                neighbors.emplace_back(grid[i][j + 1]);
        }
        if (j % 2 == 0 && j < rows - 1 && i < cols - 1) { //lower right neighbor  for row 0,2,4,6...
                neighbors.emplace_back(grid[i + 1][j + 1]);
        }
       

        // odd rows
        if (!(j % 2 == 0) && i > 0) { // upper left
                neighbors.emplace_back(grid[i - 1][j - 1]);
        }
        if (!(j % 2 == 0) && i < cols - 1) { // upper right (always there)
                neighbors.emplace_back(grid[i][j - 1]);
        }
        if (!(j % 2 == 0) && i > 0 && j < rows - 1) {  // lower left
                neighbors.emplace_back(grid[i - 1][j + 1]);
        }
        if (!(j % 2 == 0) && j < rows - 1) { // lower right (removed i<cols-1 condition and changed grid[i+1][j+1] to grid[i][j+1])
                neighbors.emplace_back(grid[i][j + 1]);
        }
       

        std::cout << "Everything is good at " << i << " " << j << std::endl;
}


void Tile::moveTile(sf::Vector2f direction) {
        /*
        move the corners of the hexagon in the given direction
        */

       
        this->hexagon.move(direction.x,direction.y);
}

void Tile::display(sf::RenderWindow& window) {
        /*
        display the hexagon
        */

        window.draw(this->hexagon);
}
]
 

kojack

  • Sr. Member
  • ****
  • Posts: 343
  • C++/C# game dev teacher.
    • View Profile
Re: loading/initializing neighbors of a tile in a grid
« Reply #1 on: March 28, 2024, 03:55:16 am »
The problem here is something that a few languages (not just javascript) going to C++ can run into.
Javascript uses references for classes. C++ uses values by default, but can also use references or pointers.

In your Tile class you have: std::vector<Tile> neighbors;
A vector of Tile isn't just references to tiles, it's complete copies of the tiles. So each tile contains a copy of all adjacent tiles, each of which contains copies of their adjacent tiles, and so on. As you process over the map adding neighbors, each new tile is picking up larger amounts of data.

What you'll want to do is have the neighbors either as an index (1d or 2d) that can look up the specified tile, or pointers to tiles. (C++ references aren't like in other languages, they wouldn't fit here as well as a pointer would)