Files
SDL/examples/game/01-snake/main.c
Sam Lantinga 9ff3446f03 Use SDL_bool instead an int return code in the SDL API
Most SDL functions used to indicate success or failure using an int return code. These functions have been changed to return SDL_bool.

Here is a coccinelle patch to change code that previously compared the return value to 0 and changes it to a boolean test:
@ bool_return_type  @
identifier func =~ "^(SDL_AddEventWatch|SDL_AddHintCallback|SDL_AddSurfaceAlternateImage|SDL_AddVulkanRenderSemaphores|SDL_BindAudioStream|SDL_BindAudioStreams|SDL_BlitSurface|SDL_BlitSurface9Grid|SDL_BlitSurfaceScaled|SDL_BlitSurfaceTiled|SDL_BlitSurfaceTiledWithScale|SDL_BlitSurfaceUnchecked|SDL_BlitSurfaceUncheckedScaled|SDL_CaptureMouse|SDL_ClearAudioStream|SDL_ClearClipboardData|SDL_ClearComposition|SDL_ClearError|SDL_ClearProperty|SDL_ClearSurface|SDL_CloseIO|SDL_CloseStorage|SDL_ConvertAudioSamples|SDL_ConvertEventToRenderCoordinates|SDL_ConvertPixels|SDL_ConvertPixelsAndColorspace|SDL_CopyFile|SDL_CopyProperties|SDL_CopyStorageFile|SDL_CreateDirectory|SDL_CreateStorageDirectory|SDL_CreateWindowAndRenderer|SDL_DateTimeToTime|SDL_DestroyWindowSurface|SDL_DetachVirtualJoystick|SDL_DisableScreenSaver|SDL_EnableScreenSaver|SDL_EnumerateDirectory|SDL_EnumerateProperties|SDL_EnumerateStorageDirectory|SDL_FillSurfaceRect|SDL_FillSurfaceRects|SDL_FlashWindow|SDL_FlipSurface|SDL_FlushAudioStream|SDL_FlushRenderer|SDL_GL_DestroyContext|SDL_GL_GetAttribute|SDL_GL_GetSwapInterval|SDL_GL_LoadLibrary|SDL_GL_MakeCurrent|SDL_GL_SetAttribute|SDL_GL_SetSwapInterval|SDL_GL_SwapWindow|SDL_GetAudioDeviceFormat|SDL_GetAudioStreamFormat|SDL_GetCameraFormat|SDL_GetClosestFullscreenDisplayMode|SDL_GetCurrentRenderOutputSize|SDL_GetCurrentTime|SDL_GetDXGIOutputInfo|SDL_GetDateTimeLocalePreferences|SDL_GetDisplayBounds|SDL_GetDisplayUsableBounds|SDL_GetGDKDefaultUser|SDL_GetGDKTaskQueue|SDL_GetGamepadSensorData|SDL_GetGamepadTouchpadFinger|SDL_GetHapticEffectStatus|SDL_GetJoystickBall|SDL_GetMasksForPixelFormat|SDL_GetPathInfo|SDL_GetRectUnion|SDL_GetRectUnionFloat|SDL_GetRenderClipRect|SDL_GetRenderColorScale|SDL_GetRenderDrawBlendMode|SDL_GetRenderDrawColor|SDL_GetRenderDrawColorFloat|SDL_GetRenderLogicalPresentation|SDL_GetRenderLogicalPresentationRect|SDL_GetRenderOutputSize|SDL_GetRenderSafeArea|SDL_GetRenderScale|SDL_GetRenderVSync|SDL_GetRenderViewport|SDL_GetSensorData|SDL_GetStorageFileSize|SDL_GetStoragePathInfo|SDL_GetSurfaceAlphaMod|SDL_GetSurfaceBlendMode|SDL_GetSurfaceClipRect|SDL_GetSurfaceColorKey|SDL_GetSurfaceColorMod|SDL_GetTextInputArea|SDL_GetTextureAlphaMod|SDL_GetTextureAlphaModFloat|SDL_GetTextureBlendMode|SDL_GetTextureColorMod|SDL_GetTextureColorModFloat|SDL_GetTextureScaleMode|SDL_GetTextureSize|SDL_GetWindowAspectRatio|SDL_GetWindowBordersSize|SDL_GetWindowMaximumSize|SDL_GetWindowMinimumSize|SDL_GetWindowPosition|SDL_GetWindowRelativeMouseMode|SDL_GetWindowSafeArea|SDL_GetWindowSize|SDL_GetWindowSizeInPixels|SDL_GetWindowSurfaceVSync|SDL_HideCursor|SDL_HideWindow|SDL_Init|SDL_InitHapticRumble|SDL_InitSubSystem|SDL_LoadWAV|SDL_LoadWAV_IO|SDL_LockAudioStream|SDL_LockProperties|SDL_LockSurface|SDL_LockTexture|SDL_LockTextureToSurface|SDL_MaximizeWindow|SDL_MinimizeWindow|SDL_MixAudio|SDL_OpenURL|SDL_OutOfMemory|SDL_PauseAudioDevice|SDL_PauseAudioStreamDevice|SDL_PauseHaptic|SDL_PlayHapticRumble|SDL_PremultiplyAlpha|SDL_PremultiplySurfaceAlpha|SDL_PushEvent|SDL_PutAudioStreamData|SDL_RaiseWindow|SDL_ReadStorageFile|SDL_ReadSurfacePixel|SDL_ReadSurfacePixelFloat|SDL_RegisterApp|SDL_ReloadGamepadMappings|SDL_RemovePath|SDL_RemoveStoragePath|SDL_RemoveTimer|SDL_RenamePath|SDL_RenameStoragePath|SDL_RenderClear|SDL_RenderCoordinatesFromWindow|SDL_RenderCoordinatesToWindow|SDL_RenderFillRect|SDL_RenderFillRects|SDL_RenderGeometry|SDL_RenderGeometryRaw|SDL_RenderLine|SDL_RenderLines|SDL_RenderPoint|SDL_RenderPoints|SDL_RenderPresent|SDL_RenderRect|SDL_RenderRects|SDL_RenderTexture|SDL_RenderTexture9Grid|SDL_RenderTextureRotated|SDL_RenderTextureTiled|SDL_RequestAndroidPermission|SDL_RestoreWindow|SDL_ResumeAudioDevice|SDL_ResumeAudioStreamDevice|SDL_ResumeHaptic|SDL_RumbleGamepad|SDL_RumbleGamepadTriggers|SDL_RumbleJoystick|SDL_RumbleJoystickTriggers|SDL_RunHapticEffect|SDL_SaveBMP|SDL_SaveBMP_IO|SDL_SendAndroidMessage|SDL_SendGamepadEffect|SDL_SendJoystickEffect|SDL_SendJoystickVirtualSensorData|SDL_SetAppMetadata|SDL_SetAppMetadataProperty|SDL_SetAudioDeviceGain|SDL_SetAudioPostmixCallback|SDL_SetAudioStreamFormat|SDL_SetAudioStreamFrequencyRatio|SDL_SetAudioStreamGain|SDL_SetAudioStreamGetCallback|SDL_SetAudioStreamInputChannelMap|SDL_SetAudioStreamOutputChannelMap|SDL_SetAudioStreamPutCallback|SDL_SetBooleanProperty|SDL_SetClipboardData|SDL_SetClipboardText|SDL_SetCursor|SDL_SetFloatProperty|SDL_SetGamepadLED|SDL_SetGamepadMapping|SDL_SetGamepadPlayerIndex|SDL_SetGamepadSensorEnabled|SDL_SetHapticAutocenter|SDL_SetHapticGain|SDL_SetJoystickLED|SDL_SetJoystickPlayerIndex|SDL_SetJoystickVirtualAxis|SDL_SetJoystickVirtualBall|SDL_SetJoystickVirtualButton|SDL_SetJoystickVirtualHat|SDL_SetJoystickVirtualTouchpad|SDL_SetLinuxThreadPriority|SDL_SetLinuxThreadPriorityAndPolicy|SDL_SetLogPriorityPrefix|SDL_SetMemoryFunctions|SDL_SetNumberProperty|SDL_SetPaletteColors|SDL_SetPointerProperty|SDL_SetPointerPropertyWithCleanup|SDL_SetPrimarySelectionText|SDL_SetRenderClipRect|SDL_SetRenderColorScale|SDL_SetRenderDrawBlendMode|SDL_SetRenderDrawColor|SDL_SetRenderDrawColorFloat|SDL_SetRenderLogicalPresentation|SDL_SetRenderScale|SDL_SetRenderTarget|SDL_SetRenderVSync|SDL_SetRenderViewport|SDL_SetScancodeName|SDL_SetStringProperty|SDL_SetSurfaceAlphaMod|SDL_SetSurfaceBlendMode|SDL_SetSurfaceColorKey|SDL_SetSurfaceColorMod|SDL_SetSurfaceColorspace|SDL_SetSurfacePalette|SDL_SetSurfaceRLE|SDL_SetTLS|SDL_SetTextInputArea|SDL_SetTextureAlphaMod|SDL_SetTextureAlphaModFloat|SDL_SetTextureBlendMode|SDL_SetTextureColorMod|SDL_SetTextureColorModFloat|SDL_SetTextureScaleMode|SDL_SetThreadPriority|SDL_SetWindowAlwaysOnTop|SDL_SetWindowAspectRatio|SDL_SetWindowBordered|SDL_SetWindowFocusable|SDL_SetWindowFullscreen|SDL_SetWindowFullscreenMode|SDL_SetWindowHitTest|SDL_SetWindowIcon|SDL_SetWindowKeyboardGrab|SDL_SetWindowMaximumSize|SDL_SetWindowMinimumSize|SDL_SetWindowModalFor|SDL_SetWindowMouseGrab|SDL_SetWindowMouseRect|SDL_SetWindowOpacity|SDL_SetWindowPosition|SDL_SetWindowRelativeMouseMode|SDL_SetWindowResizable|SDL_SetWindowShape|SDL_SetWindowSize|SDL_SetWindowSurfaceVSync|SDL_SetWindowTitle|SDL_SetiOSAnimationCallback|SDL_ShowAndroidToast|SDL_ShowCursor|SDL_ShowMessageBox|SDL_ShowSimpleMessageBox|SDL_ShowWindow|SDL_ShowWindowSystemMenu|SDL_StartTextInput|SDL_StartTextInputWithProperties|SDL_StopHapticEffect|SDL_StopHapticEffects|SDL_StopHapticRumble|SDL_StopTextInput|SDL_SyncWindow|SDL_TimeToDateTime|SDL_TryLockMutex|SDL_TryLockRWLockForReading|SDL_TryLockRWLockForWriting|SDL_TryWaitSemaphore|SDL_UnlockAudioStream|SDL_UpdateHapticEffect|SDL_UpdateNVTexture|SDL_UpdateTexture|SDL_UpdateWindowSurface|SDL_UpdateWindowSurfaceRects|SDL_UpdateYUVTexture|SDL_Vulkan_CreateSurface|SDL_Vulkan_LoadLibrary|SDL_WaitConditionTimeout|SDL_WaitSemaphoreTimeout|SDL_WarpMouseGlobal|SDL_WriteStorageFile|SDL_WriteSurfacePixel|SDL_WriteSurfacePixelFloat)$";
@@
(
  func(
  ...
  )
- == 0
|
- func(
+ !func(
  ...
  )
- < 0
|
- func(
+ !func(
  ...
  )
- != 0
|
- func(
+ !func(
  ...
  )
- == -1
)
2024-08-27 10:31:46 -07:00

156 lines
4.5 KiB
C

/*
* This example code implements a Snake game that showcases some of the
* functionalities of SDL, such as timer callbacks and event handling.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <stdlib.h> /* malloc(), free() */
#include "snake.h"
#define STEP_RATE_IN_MILLISECONDS 125
#define SNAKE_BLOCK_SIZE_IN_PIXELS 24
#define SDL_WINDOW_WIDTH (SNAKE_BLOCK_SIZE_IN_PIXELS * SNAKE_GAME_WIDTH)
#define SDL_WINDOW_HEIGHT (SNAKE_BLOCK_SIZE_IN_PIXELS * SNAKE_GAME_HEIGHT)
typedef struct
{
SDL_Window *window;
SDL_Renderer *renderer;
SDL_TimerID step_timer;
SnakeContext snake_ctx;
} AppState;
static Uint32 sdl_timer_callback_(void *payload, SDL_TimerID timer_id, Uint32 interval)
{
/* NOTE: snake_step is not called here directly for multithreaded concerns. */
SDL_Event event;
SDL_zero(event);
event.type = SDL_EVENT_USER;
SDL_PushEvent(&event);
return interval;
}
static int handle_key_event_(SnakeContext *ctx, SDL_Scancode key_code)
{
switch (key_code) {
/* Quit. */
case SDL_SCANCODE_ESCAPE:
case SDL_SCANCODE_Q:
return SDL_APP_SUCCESS;
/* Restart the game as if the program was launched. */
case SDL_SCANCODE_R:
snake_initialize(ctx, SDL_rand);
break;
/* Decide new direction of the snake. */
case SDL_SCANCODE_RIGHT:
snake_redir(ctx, SNAKE_DIR_RIGHT);
break;
case SDL_SCANCODE_UP:
snake_redir(ctx, SNAKE_DIR_UP);
break;
case SDL_SCANCODE_LEFT:
snake_redir(ctx, SNAKE_DIR_LEFT);
break;
case SDL_SCANCODE_DOWN:
snake_redir(ctx, SNAKE_DIR_DOWN);
break;
default:
break;
}
return SDL_APP_CONTINUE;
}
static void set_rect_xy_(SDL_FRect *r, short x, short y)
{
r->x = (float)(x * SNAKE_BLOCK_SIZE_IN_PIXELS);
r->y = (float)(y * SNAKE_BLOCK_SIZE_IN_PIXELS);
}
SDL_AppResult SDL_AppIterate(void *appstate)
{
AppState *as;
SnakeContext *ctx;
SDL_FRect r;
unsigned i;
unsigned j;
int ct;
as = (AppState *)appstate;
ctx = &as->snake_ctx;
r.w = r.h = SNAKE_BLOCK_SIZE_IN_PIXELS;
SDL_SetRenderDrawColor(as->renderer, 0, 0, 0, 255);
SDL_RenderClear(as->renderer);
for (i = 0; i < SNAKE_GAME_WIDTH; i++) {
for (j = 0; j < SNAKE_GAME_HEIGHT; j++) {
ct = snake_cell_at(ctx, i, j);
if (ct == SNAKE_CELL_NOTHING)
continue;
set_rect_xy_(&r, i, j);
if (ct == SNAKE_CELL_FOOD)
SDL_SetRenderDrawColor(as->renderer, 0, 0, 128, 255);
else /* body */
SDL_SetRenderDrawColor(as->renderer, 0, 128, 0, 255);
SDL_RenderFillRect(as->renderer, &r);
}
}
SDL_SetRenderDrawColor(as->renderer, 255, 255, 0, 255); /*head*/
set_rect_xy_(&r, ctx->head_xpos, ctx->head_ypos);
SDL_RenderFillRect(as->renderer, &r);
SDL_RenderPresent(as->renderer);
return SDL_APP_CONTINUE;
}
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
(void)argc;
(void)argv;
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)) {
return SDL_APP_FAILURE;
}
SDL_SetHint("SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR", "0");
AppState *as = malloc(sizeof(AppState));
*appstate = as;
as->step_timer = 0;
if (!SDL_CreateWindowAndRenderer("examples/game/snake", SDL_WINDOW_WIDTH, SDL_WINDOW_HEIGHT, 0, &as->window, &as->renderer)) {
return SDL_APP_FAILURE;
}
snake_initialize(&as->snake_ctx, SDL_rand);
as->step_timer = SDL_AddTimer(
STEP_RATE_IN_MILLISECONDS,
sdl_timer_callback_,
NULL);
if (as->step_timer == 0) {
return SDL_APP_FAILURE;
}
return SDL_APP_CONTINUE;
}
SDL_AppResult SDL_AppEvent(void *appstate, const SDL_Event *event)
{
SnakeContext *ctx = &((AppState *)appstate)->snake_ctx;
switch (event->type) {
case SDL_EVENT_QUIT:
return SDL_APP_SUCCESS;
case SDL_EVENT_USER:
snake_step(ctx, SDL_rand);
break;
case SDL_EVENT_KEY_DOWN:
return handle_key_event_(ctx, event->key.scancode);
}
return SDL_APP_CONTINUE;
}
void SDL_AppQuit(void *appstate)
{
if (appstate != NULL) {
AppState *as = (AppState *)appstate;
SDL_RemoveTimer(as->step_timer);
SDL_DestroyRenderer(as->renderer);
SDL_DestroyWindow(as->window);
free(as);
}
}