From 71025fc7fae90633b99049f06207174fd2358575 Mon Sep 17 00:00:00 2001 From: Rysertio Date: Thu, 14 Mar 2024 16:56:44 +0600 Subject: [PATCH] add astar --- makefile | 2 +- src/ai.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/data.h | 5 +- src/draw.h | 14 ------ src/main.c | 19 +++++++- src/ui.c | 1 + src/ui.h | 2 +- 7 files changed, 157 insertions(+), 19 deletions(-) create mode 100644 src/ai.c diff --git a/makefile b/makefile index 73b5a5c..f20a41f 100644 --- a/makefile +++ b/makefile @@ -11,7 +11,7 @@ INC_FLAGS := $(addprefix -I,$(INC_DIRS)) CPPFLAGS ?= $(INC_FLAGS) -MMD -MP $(TARGET): $(OBJS) - $(CC) $(LDFLAGS) $(OBJS) -o $@ $(LOADLIBES) $(LDLIBS) -lSDL2 + $(CC) $(LDFLAGS) $(OBJS) -o $@ $(LOADLIBES) $(LDLIBS) -lSDL2 -lSDL2_image -lSDL2_ttf .PHONY: clean clean: diff --git a/src/ai.c b/src/ai.c new file mode 100644 index 0000000..984b963 --- /dev/null +++ b/src/ai.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include "data.h" + +#define MAX_UNITS 100 +#define MAX_BUILDINGS 50 + +typedef struct Node { + int x, y; + int gCost; // Cost from start node + int hCost; // Heuristic cost to target node + struct Node* parent; +} Node; + +// Function to calculate the distance between two points using Manhattan distance +int calculateDistance(int x1, int y1, int x2, int y2) { + return abs(x1 - x2) + abs(y1 - y2); +} + +bool isUnitOrBuildingAtPosition(GameData* data, int x, int y) { + for (int i = 0; i < MAX_UNITS; i++) { + if (data->units[i].unitID != -1 && data->units[i].x == x && data->units[i].y == y) { + // Found a unit at the position + return true; + } + } + + for (int i = 0; i < MAX_BUILDINGS; i++) { + if (data->buildings[i].buildingID != -1 && data->buildings[i].x == x && data->buildings[i].y == y) { + // Found a building at the position + return true; + } + } + + // No unit or building found at the position + return false; +} + +// A* algorithm implementation +void aStarPathfinding(GameData* map, int startX, int startY, int targetX, int targetY) { + // Create start and target nodes + Node startNode = {startX, startY, 0, 0, NULL}; + Node targetNode = {targetX, targetY, 0, 0, NULL}; + + // Create open and closed lists + Node* openList = malloc(sizeof(Node) * MAP_SIZE * MAP_SIZE); + Node* closedList = malloc(sizeof(Node) * MAP_SIZE * MAP_SIZE); + int openListCount = 0; + int closedListCount = 0; + + // Add start node to open list + openList[openListCount++] = startNode; + + while (openListCount > 0) { + // Find the node with the lowest fCost in the open list + int currentIndex = 0; + for (int i = 0; i < openListCount; i++) { + if (openList[i].gCost + openList[i].hCost < openList[currentIndex].gCost + openList[currentIndex].hCost) { + currentIndex = i; + } + } + + // Move current node to the closed list + Node currentNode = openList[currentIndex]; + openList[currentIndex] = openList[--openListCount]; + closedList[closedListCount++] = currentNode; + + // Check if we have reached the target node + if (currentNode.x == targetNode.x && currentNode.y == targetNode.y) { + // Path found, reconstruct and print the path + while (currentNode.parent != NULL) { + printf("(%d, %d) -> ", currentNode.x, currentNode.y); + currentNode = *currentNode.parent; + } + printf("(%d, %d)\n", startX, startY); + break; + } + + // Generate neighboring nodes + for (int i = -1; i <= 1; i++) { + for (int j = -1; j <= 1; j++) { + if (i == 0 && j == 0) continue; + + int neighborX = currentNode.x + i; + int neighborY = currentNode.y + j; + + // Ignore invalid neighbors or obstacles + if (neighborX < 0 || neighborX >= MAP_SIZE || neighborY < 0 || neighborY >= MAP_SIZE || + map->currentMap.tileData[neighborX][neighborY] == 1 || isUnitOrBuildingAtPosition(map, neighborX, neighborY)) { + continue; + } + + // Calculate neighbor costs + int gCost = currentNode.gCost + 1; // Assuming uniform movement cost + int hCost = calculateDistance(neighborX, neighborY, targetNode.x, targetNode.y); + + // Check if neighbor is in the closed list + bool inClosedList = false; + for (int k = 0; k < closedListCount; k++) { + if (closedList[k].x == neighborX && closedList[k].y == neighborY) { + inClosedList = true; + break; + } + } + + if (!inClosedList) { + // Check if neighbor is in the open list + bool inOpenList = false; + for (int k = 0; k < openListCount; k++) { + if (openList[k].x == neighborX && openList[k].y == neighborY) { + inOpenList = true; + if (gCost < openList[k].gCost) { + openList[k].gCost = gCost; + openList[k].parent = ¤tNode; + } + break; + } + } + + if (!inOpenList) { + // Add neighbor to open list + openList[openListCount++] = (Node){neighborX, neighborY, gCost, hCost, ¤tNode}; + } + } + } + } + } + + free(openList); + free(closedList); +} diff --git a/src/data.h b/src/data.h index c6d4ef2..9a3473f 100644 --- a/src/data.h +++ b/src/data.h @@ -7,6 +7,7 @@ #define MAX_MISSIONS 10 #define MAX_RESOURCES 50 #define MAP_SIZE 100 +#define numLEVELS 50 typedef struct { int playerID; @@ -36,7 +37,7 @@ typedef struct { char mapName[50]; int mapWidth; int mapHeight; - int tileData[MAP_SIZE][MAP_SIZE]; + uint4_t tileData[MAP_SIZE][MAP_SIZE]; int playerStartingPositions[MAX_PLAYERS][2]; // [x, y] coordinates for each player int resourceLocations[MAX_RESOURCES][2]; // [x, y] coordinates for each resource } Map; @@ -87,7 +88,7 @@ typedef struct { } UnitData; typedef struct { - GameData data; + GameData data[numLEVELS]; BuildingData buildings[100]; UnitData units[100]; } Game; diff --git a/src/draw.h b/src/draw.h index e4c0484..a0b367d 100644 --- a/src/draw.h +++ b/src/draw.h @@ -11,17 +11,3 @@ void drawGameData(SDL_Renderer *renderer, const GameData *gameData, SDL_Texture *tileTexture, SDL_Texture *unitTexture, SDL_Texture *buildingTexture); #endif /* DRAW_H */ -#define MAP_SIZE 96 -#ifndef DRAW_H -#define DRAW_H - -#include - -// Define the size of your tiles in pixels -#define TILE_SIZE 32 -#include "data.h" - -// Function prototype for drawing game data -void drawGameData(SDL_Renderer *renderer, const GameData *gameData, SDL_Texture *tileTexture, SDL_Texture *unitTexture, SDL_Texture *buildingTexture); - -#endif /* DRAW_H */ diff --git a/src/main.c b/src/main.c index f2021e6..cbce573 100644 --- a/src/main.c +++ b/src/main.c @@ -4,12 +4,19 @@ #include "draw.h" #include "input.h" #include "ui.h" +#include +#include const int SCREEN_WIDTH = 800; const int SCREEN_HEIGHT = 600; +void updateGameState() { + +} + int main(int argc, char* argv[]) { SDL_Init(SDL_INIT_VIDEO); + TTF_Init(); SDL_Window* window = SDL_CreateWindow("RTS Game", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); @@ -18,6 +25,16 @@ int main(int argc, char* argv[]) { bool quit = false; SDL_Event event; + // Load textures for tiles, units, and buildings + SDL_Texture* unitTexture = IMG_LoadTexture(renderer, "path/to/unit_texture.png"); + SDL_Texture* buildingTexture = IMG_LoadTexture(renderer, "path/to/building_texture.png"); + SDL_Texture* tileTexture = IMG_LoadTexture(renderer, "path/to/tile_texture.png"); + + // Assuming you have a GameData instance named gameData + GameData gameData; + // Initialize gameData here... + + while (!quit) { // Event handling while (SDL_PollEvent(&event) != 0) { @@ -35,7 +52,7 @@ int main(int argc, char* argv[]) { SDL_RenderClear(renderer); // Render game objects - renderGame(renderer); // You need to define this function to render the game + drawGameData(renderer, &gameData, tileTexture, unitTexture, buildingTexture); // Update the screen SDL_RenderPresent(renderer); diff --git a/src/ui.c b/src/ui.c index 1918885..45dc2c6 100644 --- a/src/ui.c +++ b/src/ui.c @@ -1,6 +1,7 @@ #include "ui.h" #include #include +#include bool isPointInsideRect(int x, int y, SDL_Rect rect) { return (x >= rect.x && x <= rect.x + rect.w && y >= rect.y && y <= rect.y + rect.h); diff --git a/src/ui.h b/src/ui.h index 0166398..ed0ce3d 100644 --- a/src/ui.h +++ b/src/ui.h @@ -3,6 +3,7 @@ #include #include +#include // Structure representing a button typedef struct { @@ -10,7 +11,6 @@ typedef struct { bool clicked; void (*onClick)(); char text[50]; - char text[50]; } Button; // Function prototypes