add astar

This commit is contained in:
Rysertio 2024-03-14 16:56:44 +06:00
parent d27c9bd1ef
commit 71025fc7fa
7 changed files with 157 additions and 19 deletions

View file

@ -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:

133
src/ai.c Normal file
View file

@ -0,0 +1,133 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#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 = &currentNode;
}
break;
}
}
if (!inOpenList) {
// Add neighbor to open list
openList[openListCount++] = (Node){neighborX, neighborY, gCost, hCost, &currentNode};
}
}
}
}
}
free(openList);
free(closedList);
}

View file

@ -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;

View file

@ -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 <SDL2/SDL.h>
// 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 */

View file

@ -4,12 +4,19 @@
#include "draw.h"
#include "input.h"
#include "ui.h"
#include <SDL2/SDL_ttf.h>
#include <SDL2/SDL_image.h>
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);

View file

@ -1,6 +1,7 @@
#include "ui.h"
#include <stdbool.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
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);

View file

@ -3,6 +3,7 @@
#include <stdbool.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
// 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