[C Entry, c Entry
Because food is the simplest part of a snake game and is not strongly correlated with other parts, it is basically an independent part, so I plan to implement it first.
My idea is that food can only be created in the world. That is to say, there is a world with food first. So I have to determine whether the world exists before I can create food.
Food * SNK_CreateFood(World *world, int size){ Food *food; if (world == 0) return 0; if ((food = (Food *)SDL_malloc(sizeof(Food))) == 0) return 0; INIT_FOOD(world, size); return food;}
For pointer variables, I always explicitly compare them with values, which helps avoid some hidden errors. Macro INIT_FOOD is used to initialize the Food struct. The definition can be seen in the final complete source code.
Because the food is allocated using the SDL_malloc function, you only need to release the memory to destroy the food. In C, the released pointer is not zero. A good habit is to explicitly set the pointer to zero after each release. I always follow this habit. Unless the program exits immediately after the pointer is released, I always set the released pointer to zero.
void SNK_DestroyFood(Food *food){ SDL_free(food); food = 0;}
I have no idea about the beauty or ugliness of food, so the so-called food here is just a rectangle. There are a lot of creative ideas in food painting. It is refreshing to draw a wonderful food. However, I only try to be concise, so that I can.
void SNK_DrawFood(Food *food){ SDL_Rect rect; if (food != 0) { rect.x = food->x; rect.y = food->y; rect.w = rect.h = food->size; if (((food->world != 0) ? (food->world->render != 0) : 0)) { SDL_SetRenderDrawColor(food->world->render, food->color.r, food->color.g, food->color.b, food->color.a); SDL_RenderDrawRect(food->world->render, &rect); } }}
The function for setting food locations is easy to define. Just give a food and coordinates. However, I made some judgments and processing internally to ensure the feasibility of the two aspects: 1. Ensure that the coordinates are positive and within the world. 2. The food coordinate must be an integer multiple of the food size. Although it is not an integer multiple, I plan to set the food and snake to the same size. If it is not an integer multiple, it will happen that the snake has not eaten the food, the food disappears.
void SNK_SetFoodPosition(Food *food, int x, int y){ if (((food != 0) ? (food->world != 0) : 0)) { if (SDL_abs(x) > food->world->w) x = food->world->w; if (SDL_abs(y) > food->world->h) y = food->world->h; if (food->size != 0) { food->x = (SDL_abs(x) / food->size) * food->size; food->y = (SDL_abs(y) / food->size) * food->size; } }}
The last step is to set the food color. This is very simple. Just assign values one by one.
void SNK_SetFoodColor(Food *food, Uint8 r, Uint8 g, Uint8 b, Uint8 a){ if (food != 0) { food->color.r = r; food->color.g = g; food->color.b = b; food->color.a = a; }}
The following is the complete content of the snk-food.c file:
#include "snk-food.h"#define INIT_FOOD(world, size) \ food->world = (world); \ food->x = food->y = 0; \ food->size = (size) ? SDL_abs(size) : 0; \ food->color.r = food->color.g = food->color.b = food->color.a = 0;Food * SNK_CreateFood(World *world, int size){ Food *food; if (world == 0) return 0; if ((food = (Food *)SDL_malloc(sizeof(Food))) == 0) return 0; INIT_FOOD(world, size); return food;}void SNK_DestroyFood(Food *food){ SDL_free(food); food = 0;}void SNK_DrawFood(Food *food){ SDL_Rect rect; if (food != 0) { rect.x = food->x; rect.y = food->y; rect.w = rect.h = food->size; if (((food->world != 0) ? (food->world->render != 0) : 0)) { SDL_SetRenderDrawColor(food->world->render, food->color.r, food->color.g, food->color.b, food->color.a); SDL_RenderDrawRect(food->world->render, &rect); } }}void SNK_SetFoodPosition(Food *food, int x, int y){ if (((food != 0) ? (food->world != 0) : 0)) { if (SDL_abs(x) > food->world->w) x = food->world->w; if (SDL_abs(y) > food->world->h) y = food->world->h; if (food->size != 0) { food->x = (SDL_abs(x) / food->size) * food->size; food->y = (SDL_abs(y) / food->size) * food->size; } }}void SNK_SetFoodColor(Food *food, Uint8 r, Uint8 g, Uint8 b, Uint8 a){ if (food != 0) { food->color.r = r; food->color.g = g; food->color.b = b; food->color.a = a; }}