Fix flood fill algorithm issue

This commit is contained in:
Joseph Ferano 2024-08-20 15:55:27 +07:00
parent 5b4d4fe21e
commit 3515eb6f19

View File

@ -6,8 +6,8 @@
#define SCREEN_WIDTH 1000 #define SCREEN_WIDTH 1000
#define SCREEN_HEIGHT 800 #define SCREEN_HEIGHT 800
#define IMG_W 500 #define IMG_W 1000
#define IMG_H 400 #define IMG_H 800
#define IMG_SIZE IMG_W * IMG_H #define IMG_SIZE IMG_W * IMG_H
#define TARGET_FPS 120 #define TARGET_FPS 120
@ -122,7 +122,7 @@ void Update(GameState *S) {
S->paintTank += 4; S->paintTank += 4;
S->paintTank = S->paintTank > paintTankMax ? paintTankMax : S->paintTank; S->paintTank = S->paintTank > paintTankMax ? paintTankMax : S->paintTank;
} else { } else {
S->paintTank -= 1; S->paintTank -= 3;
S->paintTank = S->paintTank < 0 ? 0 : S->paintTank; S->paintTank = S->paintTank < 0 ? 0 : S->paintTank;
} }
if (S->paintTank > 0 && !sameColor) { if (S->paintTank > 0 && !sameColor) {
@ -133,38 +133,40 @@ void Update(GameState *S) {
} }
} }
if (!dirty || S->once) { if (!dirty) {
// if (true) {
return; return;
} }
memset(S->bfsBuffer, 0, IMG_SIZE * sizeof(int));
for (int i = 0; i < IMG_SIZE; i++) { for (int i = 0; i < IMG_SIZE; i++) {
Pixel pixel = IndexToPixel(i); Pixel pixel = IndexToPixel(i);
Color color = GetImageColor(S->imageBuffer, pixel.x, pixel.y); Color color = GetImageColor(S->imageBuffer, pixel.x, pixel.y);
bool sameColor = ColorIsEqual(color, playerColor); bool sameColor = ColorIsEqual(color, playerColor);
if (S->bfsBuffer[i] != 0 || sameColor) { if (S->bfsBuffer[i] != 0 || sameColor) {
if (sameColor) {
S->bfsBuffer[i] = -1;
}
continue; continue;
} }
// printf("X: %d Y: %d - C: %d IDX: %d \n", pixel.x, pixel.y, sameColor, S->bfsBuffer[i]);
S->queue[0] = pixel; S->queue[0] = pixel;
S->q_tail++; S->q_tail++;
bool edgeDetected = false; bool edgeDetected = false;
while (S->q_head != S->q_tail) { while (S->q_head != S->q_tail) {
Pixel pixel = S->queue[S->q_head++]; Pixel pixel = S->queue[S->q_head++];
int idx = PixelToIndex(pixel); int idx = PixelToIndex(pixel);
int left = abs(pixel.y * IMG_W - idx) - 1 >= 0 ? idx - 1 : -1; int left = abs(pixel.y * IMG_W - idx) - 1 >= 0 ? idx - 1 : -1;
int right = abs(pixel.y * IMG_W - idx) + 1 < IMG_W ? idx + 1 : IMG_W; int right = abs(pixel.y * IMG_W - idx) + 1 < IMG_W ? idx + 1 : -1;
int top = idx - IMG_W; int top = idx - IMG_W;
int bottom = idx + IMG_W; int bottom = idx + IMG_W;
int directions[] = { left, right, top, bottom }; int directions[] = { left, right, top, bottom };
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
int j = directions[i]; int j = directions[i];
// printf("IDX: %d ||| %d %d %d %d \n", idx, left, right, top, bottom); if ((i < 2 && j >= 0) || (i >= 2 && j >= 0 && j < IMG_SIZE)) {
if ((i < 2 && j >= 0 && j < IMG_W) || (i >= 2 && j >= 0 && j < IMG_SIZE)) {
Pixel pixel = IndexToPixel(j); Pixel pixel = IndexToPixel(j);
Color c = GetImageColor(S->imageBuffer, pixel.x, pixel.y); Color c = GetImageColor(S->imageBuffer, pixel.x, pixel.y);
if (S->bfsBuffer[j] == 0 && !ColorIsEqual(playerColor, c)) { if (S->bfsBuffer[j] == 0 && !ColorIsEqual(playerColor, c)) {
// printf("IDX: %d J: %d PX: %d PY: %d\n", idx, j, pixel.x, pixel.y); S->bfsBuffer[j] = 1;
S->queue[S->q_tail++] = pixel; S->queue[S->q_tail++] = pixel;
} else if (S->bfsBuffer[j] == 0) { } else if (S->bfsBuffer[j] == 0) {
S->bfsBuffer[j] = -1; S->bfsBuffer[j] = -1;
@ -173,17 +175,13 @@ void Update(GameState *S) {
edgeDetected = true; edgeDetected = true;
} }
} }
S->bfsBuffer[idx] = 1;
if (!edgeDetected) { if (!edgeDetected) {
S->fill[S->fillCount++] = pixel; S->fill[S->fillCount++] = pixel;
} else { } else {
} }
} }
// This should only get called twice
// printf("PX: %d PY: %d\n", pixel.x, pixel.y);
// Fill that sucker // Fill that sucker
if (!edgeDetected) { if (!edgeDetected) {
printf("no dice\n");
for (int i = 0; i < S->fillCount; i++) { for (int i = 0; i < S->fillCount; i++) {
Pixel p = S->fill[i]; Pixel p = S->fill[i];
ImageDrawPixel(&S->imageBuffer, p.x, p.y, playerColor); ImageDrawPixel(&S->imageBuffer, p.x, p.y, playerColor);
@ -191,11 +189,10 @@ void Update(GameState *S) {
UpdateTexture(S->displayTexture, S->imageBuffer.data); UpdateTexture(S->displayTexture, S->imageBuffer.data);
} }
S->fillCount = 0; S->fillCount = 0;
S->q_head = S->q_tail = 0; S->q_head = 0;
S->q_tail = 0;
} }
// memset(S->bfsBuffer, 0, IMG_SIZE * sizeof(int));
S->once = true; S->once = true;
// printf("===========================\n");
} }
void Draw2D(const GameState *S) { void Draw2D(const GameState *S) {
@ -231,37 +228,30 @@ void Draw2DDebug(GameState *S) {
DrawRectangleRec(rect, S->colorUnderPlayer); DrawRectangleRec(rect, S->colorUnderPlayer);
DrawRectangleLinesEx(rect, 2, BLACK); DrawRectangleLinesEx(rect, 2, BLACK);
if (S->once) { if (S->once) {
if (!S->nomore) { // if (!S->nomore) {
// Color color = BLACK; if (false) {
for (int i = 0; i < IMG_W; i++) { Color color = BLACK;
for (int j = 0; j < IMG_H; j++) { for (int i = 0; i < IMG_SIZE; i++) {
// int idx = S->bfsBuffer[i]; int idx = S->bfsBuffer[i];
// int idx = 2; // int idx = 2;
// if (idx == 0) { if (idx == 0) {
// color = PINK; color = BLUE;
// } else if (idx == 1) { } else if (idx == 1) {
// color = MAGENTA; color = GREEN;
// } else if (idx == -1) { } else if (idx == -1) {
// color = LIME; color = RED;
// } else { } else {
// // printf("Not even one right? %d\n", idx);
// }
// Pixel p = IndexToPixel(i);
// printf("X: %d Y: %d\n", p.x, p.y);
// ImageDrawPixel(&S->debugBfsImg, i, j, RED);
} }
Pixel p = IndexToPixel(i);
ImageDrawPixel(&S->debugBfsImg, p.x, p.y, color);
} }
printf("What the hell is going on?\n"); UpdateTexture(S->debugBfsTx, S->debugBfsImg.data);
ImageDrawPixel(&S->debugBfsImg, 0, 0, RED);
UpdateTexture(S->debugBfsTx, &S->debugBfsImg);
} }
Rectangle source = {0, 0, IMG_W, IMG_H}; Rectangle source = {0, 0, IMG_W, IMG_H};
Vector2 pos = {SCREEN_WIDTH * 0.5f - IMG_W * 0.5f,SCREEN_HEIGHT * 0.5f - IMG_H * 0.5f}; Vector2 pos = {SCREEN_WIDTH * 0.5f - IMG_W * 0.5f,SCREEN_HEIGHT * 0.5f - IMG_H * 0.5f};
Rectangle dest = {pos.x, pos.y, IMG_W, IMG_H}; Rectangle dest = {pos.x, pos.y, IMG_W, IMG_H};
// DrawTexturePro(S->debugBfsTx, source, dest, (Vector2){0,0}, 0, WHITE); // DrawTexturePro(S->debugBfsTx, source, dest, (Vector2){0,0}, 0, WHITE);
DrawTexture(S->debugBfsTx, 300, 200, WHITE); // S->nomore = true;
S->nomore = true;
} }
DrawFPS(rect.x + 17, SCREEN_HEIGHT - 33); DrawFPS(rect.x + 17, SCREEN_HEIGHT - 33);
} }