Skip to content

raylib syntax analysis

victor-kironde edited this page May 31, 2024 · 18 revisions

This analysis has been made on raylib 5.1-dev that exposes a total of 558 functions.

raylib is a simple and easy-to-use library to enjoy videogames programing... but, what makes the library simple and easy-to-use? For many users the first approach to the library is through its API, so, here it is a small analysis of the API from a syntactic point of view.

How are the functions structured? Which words are used? How many parameters are exposed? How intuitive is it to understand or even guess every function/structure/enum when required? Syntax is the set of rules, principles, and processes that govern the structure of sentences in a given language and defines how we understand it.

To do this analysis a raylib.h parser has been created. That parser dissects API into small pieces to automatize some parts of the analysis; actually, this parser can also be useful for automatic docs and bindings generation!

The analysis is organized in 3 parts, one for each API element analyzed:

  • 1. Functions: Instructions called by the users to make things happen
  • 2. Structures (struct): Data types to organize information packages
  • 3. Enumerators (enum): Sequence of named values used for convenience

1. Functions

All raylib functions try to follow this syntactic structure:

    <Verb><Subject><Complement>();

More specifically, every syntactic element implies:

    <Action><Object><Attribute/State>();  // Do an Action over some Object Attribute/State

Following this syntactic structure is what make the API comprehensive, intuitive, easy-to-remember and easy-to-use.

Checking the available functions with more detail, they can be divided into 3 groups:

  • 1.1. Functions following a common pattern
  • 1.2. Functions operating over specific type of data
  • 1.3. Functions with unique pattern
  • 1.4. Functions suffixes
  • 1.5. Functions naming
  • 1.6. Functions parameters

1.1. Functions following a common pattern

Most of the functions of the library go into this first group (416 functions), there is some common <Action> that prepends the name of most of the functions:

pattern function format API count examples
01 void Init*() 2 InitWindow(), InitAudioDevice()
02 void Close*() 2 CloseWindow(), CloseAudioDevice()
03 void Begin*() 8 BeginDrawing(), BeginBlendMode()
04 void End*() 8 EndDrawing(), EndBlendMode()
05 TYPE Get*() 93 GetKeyPressed(), GetMouseX(), GetRayCollision*()
06 void Set*() 52 SetWindowTitle(), SetTargetFPS(), SetMouseScale()
07 bool Is*() 45 IsKeyPressed(), IsGamepadAvailable(), IsSoundPlaying()
08 TYPE Gen<TYPE>*() 23 GenImage*(), GenMesh*()
09 TYPE Load<TYPE>*() 34 LoadImage*(), LoadTexture*(), LoadSound*()
10 void Unload<TYPE>*(<TYPE>) 28 UnloadImage(), UnloadTexture(), UnloadSound()
11 void Update<TYPE>*(<TYPE>, *) 9 UpdateTexture(), UpdateCamera()
12 bool Save*() 2 SaveFileData(), SaveFileText(), SaveStorageValue()
13 bool Export*() 9 ExportImage(), ExportImageAsCode(), ExportMesh(), ExportWave(), ExportWaveAsCode()
14 void Draw*() 89 DrawRectangle(), DrawTexture*(), DrawModel*()
15 bool Check*() 12 CheckCollisionRecs(), CheckCollisionCircles(), CheckCollisionBoxSphere()

1.2. Functions operating over specific type of data

Those functions (74 in total) operate over a specific data type, so, it was decided to prepend the DataType to the function name, they are an exception over the main syntax rule followed by the API:

pattern function format API count examples
01 TYPE Color*() 10 ColorAlpha(), ColorFromHSV(), ColorToHSV()
02 Image Image*()
void Image*()
45 ImageFormat(), ImageCrop(), ImageResize(), ImageFlipVertical()
03 TYPE Text*() 16 TextFormat(), TextReplace(), TextSplit(), TextToLower()
04 Wave Wave*()
void Wave*()
3 WaveFormat(), WaveCopy(), WaveCrop()

NOTE: Maybe some of them are renamed in the future for consistency.

1.3. Functions with unique pattern

Remaining functions (57 in total) follow a unique pattern, still, most of them follow the standard syntax pattern of <Verb><Subject><Complement>.

// core.c
WindowShouldClose();   // Not following pattern
ClearWindowState();
ToggleFullscreen();
ToggleBorderlessWindowed();
MaximizeWindow();
MinimizeWindow();
RestoreWindow();
EnableEventWaiting();
DisableEventWaiting();
ShowCursor();
HideCursor();
EnableCursor();
DisableCursor();
ClearBackground();
SwapScreenBuffer();
PollInputEvents();
WaitTime();
TakeScreenshot();
TraceLog();            // Not following pattern
OpenURL();
MemAlloc();            // Data-type pattern?
MemRealloc();          // Data-type pattern?
MemFree();             // Data-type pattern?
FileExists();          // Not following pattern -> IsFileAvailable()?
DirectoryExists();     // Not following pattern -> IsDirectoryAvailable()?
ClearDirectoryFiles();
ChangeDirectory();
CompressData();
DecompressData();
EncodeDataBase64();
DecodeDataBase64();
StartAutomationEventRecording();
StopAutomationEventRecording();
PlayAutomationEvent();

// textures.c
Fade();                // Superseded by ColorAlpha()

// text.c
MeasureText();
MeasureTextEx();
CodepointToUTF8();     // Not following pattern -> EncodeCodepointAsUTF8()?

// models.c
UploadMesh();

// raudio.c
PlaySound();
StopSound();
PauseSound();
ResumeSound();
PlayMusicStream();
StopMusicStream();
PauseMusicStream();
ResumeMusicStream();
SeekMusicStream();
PlayAudioStream();
StopAudioStream();
PauseAudioStream();
ResumeAudioStream();
SeekAudioStream();
AttachAudioStreamProcessor();
DetachAudioStreamProcessor();
AttachAudioMixedProcessor();
DetachAudioMixedProcessor();

1.4. Functions suffixes

A part from the function prefixes that we can find in many functions names (1. common patterns), we can also find some common suffixes used by several functions:

// Suffix: *V() -> Used for "Vector" versions of same name functions
//------------------------------------------------------------------------------------------------
// rcore.c
void SetShaderValueV();
Vector2 GetMouseWheelMoveV();
// rshapes.c
void DrawPixelV();
void DrawLineV();
void DrawCircleV();
void DrawCircleLinesV();
void DrawRectangleV();
void DrawRectangleGradientV();
// rtextures.c
void ImageDrawPixelV();
void ImageDrawLineV();
void ImageDrawCircleV();
void ImageDrawRectangleV();
void DrawTextureV();
// rmodels.c
void DrawCubeV();
void DrawCubeWiresV();

// Suffix: *Ex() -> Used for "Extended" versions of same name functions
//------------------------------------------------------------------------------------------------
// rcore.c
Vector2 GetWorldToScreenEx();
// rshapes.c
void DrawLineEx();
void DrawRectangleGradientEx();
void DrawRectangleLinesEx();
void DrawPolyLinesEx();
// rtextures.c
Image ImageTextEx();
void ImageDrawTextEx();
void DrawTextureEx();
// rtext.c
Font LoadFontEx();
void DrawTextEx();
Vector2 MeasureTextEx();
// rmodels.c
void DrawSphereEx();
void DrawCylinderEx();
void DrawCylinderWiresEx();
void DrawModelEx();
void DrawModelWiresEx();

// Suffix: *Pro() -> Used for "Professional" versions of same name functions, more advanced than "Ex"
//------------------------------------------------------------------------------------------------
// rshapes.c
void DrawRectanglePro();
// rtextures.c
void DrawTexturePro();
// rtext.c
void DrawTextPro();
// rmodels.c
void DrawBillboardPro();

// Suffix: *Rec() -> Used for functions requiring a "Rectangle" as one main input parameter
//------------------------------------------------------------------------------------------------
// rshapes.c
void DrawRectangleRec();
bool CheckCollisionCircleRec();
bool CheckCollisionPointRec();
Rectangle GetCollisionRec();
// rtextures.c
void ImageDrawRectangleRec();
void UpdateTextureRec();
void DrawTextureRec();
// rtext.c
Rectangle GetGlyphAtlasRec();
// rmodels.c
void DrawBillboardRec();

// Suffix: *FromMemory() -> Used for functions loading data "from memory" instead of from files
//------------------------------------------------------------------------------------------------
Shader LoadShaderFromMemory();
Image LoadImageAnimFromMemory();
Image LoadImageFromMemory();
Font LoadFontFromMemory();
Wave LoadWaveFromMemory();
Music LoadMusicStreamFromMemory();

// Suffix: *Callback() -> Used for functions setting a callback function
//------------------------------------------------------------------------------------------------
void SetTraceLogCallback();
void SetLoadFileDataCallback();
void SetSaveFileDataCallback();
void SetLoadFileTextCallback();
void SetSaveFileTextCallback();
void SetAudioStreamCallback();

1.5. Functions naming

Most functions in raylib use a maximum of 4 words on its name. I think that's a good trade-off to remember the name of the function. Still, there is a small set of functions that go beyond that limit:

count function words comments
001 GetWindowScaleDPI() 4 Acronym used
002 GetWorldToScreenEx() 5
003 GetWorldToScreen2D() 5
004 GetScreenToWorld2D() 5
005 SetTargetFPS() 5 Acronym used
006 SetLoadFileDataCallback() 5 Callback function
007 SetSaveFileDataCallback() 5 Callback function
008 SetLoadFileTextCallback() 5 Callback function
009 SetSaveFileTextCallback() 5 Callback function
010 GetFileNameWithoutExt() 5
011 SetAutomationEventBaseFrame() 5 TODO: Review!!!
012 DrawSplineSegmentCatmullRom() 5
013 DrawSplineSegmentBezierQuadratic() 5
014 DrawSplineSegmentBezierCubic() 5
015 GetSplinePointCatmullRom() 5
016 GetSplinePointBezierQuad() 5
017 GetSplinePointBezierCubic() 5
018 LoadImageAnimFromMemory() 5
019 ImageToPOT() 3 Acronym used
020 ImageRotateCCW() 3 Acronym used
021 ColorToHSV() 3 Acronym used
022 ColorFromHSV() 3 Acronym used
023 LoadMusicStreamFromMemory() 5 *FromMemory() set of functions
024 SetAudioStreamBufferSizeDefault() 6 TODO: Review!!!

1.6. Functions parameters

Most functions are limited to 5 or less input parameters. I think 5 or less parameters is a good number to keep the function simple and rememberable, more than 5 usually requires the user to use some kind of intellisense system. The number of parameters is a key point for raylib simplicity, still, there are some functions requiring 6 or more parameters:

count function param count comments
002 DrawCircleSector() 6
003 DrawCircleSectorLines() 6
004 DrawRing() 7 WARNING: >6 parameters
005 DrawRingLines() 7 WARNING: >6 parameters
006 DrawRectangleGradientV() 6
007 DrawRectangleGradientH() 6
008 DrawPolyLinesEx() 6
009 DrawSplineSegmentBasis() 6
010 DrawSplineSegmentCatmullRom() 6
011 DrawSplineSegmentBezierCubic() 6
012 GenImageChecked() 6
013 ImageResizeCanvas() 6
014 ImageDrawLine() 6
015 ImageDrawRectangle() 6
016 ImageDrawText() 6
017 ImageDrawTextEx() 7 WARNING: >6 parameters
018 DrawTexturePro() 6
019 DrawTextureNPatch() 6
020 LoadFontFromMemory() 6
021 LoadFontData() 6
022 GenImageFontAtlas() 6
023 DrawTextEx() 6
024 DrawTextPro() 8 WARNING: >7 parameters
025 DrawTextCodepoints() 7 WARNING: >6 parameters
026 DrawCylinder() 6
027 DrawCylinderEx() 6
028 DrawCylinderWires() 6
029 DrawCylinderWiresEx() 6
030 DrawCapsule() 6
031 DrawCapsuleWires() 6
032 DrawModelEx() 6
033 DrawModelWiresEx() 6
034 DrawBillboardRec() 6
035 DrawBillboardPro() 9 WARNING: >8 parameters

Note that only 6 function out of 470 require more than 6 parameters. This is what makes raylib so special.

2. Structures

raylib defines a total of 34 struct data types, most of those structs use a single word to define the type and some of them use two words.

raylib tries to provide generic data types for most common use scenarios, only some of those structs are required for specific examples: NPatchInfo, VrDeviceInfo, VrStereoConfig.

About the fields contained in every struct, it was tried to just include the minimum required but when moving into 3d Mesh and Model, the amount of required data grows fast. For a more detailed analysis on data structures (not purely syntactic), check Wiki entry: raylib data structures.

count struct name fields count comments
01 Vector2 2
02 Vector3 3
03 Vector4 4
04 Matrix 4
05 Color 4
06 Rectangle 4
07 Image 5
08 Texture 5
09 RenderTexture 3 2 words name
10 NPatchInfo 6 2 words name
11 GlyphInfo 5 2 words name
12 Font 6
13 Camera3D 5
14 Camera2D 4
15 Mesh 21
16 Shader 2
17 MaterialMap 3 2 words name
18 Material 3
19 Transform 3
20 BoneInfo 2 2 words name
21 Model 12
22 ModelAnimation 5 2 words name
23 Ray 2
24 RayCollision 4 2 words name
25 BoundingBox 2 2 words name
26 Wave 5
27 AudioStream 6 2 words name
28 Sound 2
29 Music 6
30 VrDeviceInfo 9 3 words name
31 VrStereoConfig 8 3 words name
32 FilePathList 3 3 words name
33 AutomationEvent 3 2 words name
34 AutomationEventList 3 3 words name

3. Enumerations

raylib defines 21 enumerations for convenience. Enum names and contained value names are kept simple and clear. Most of those values are only required to be used by some very specific functions, for a detailed list check Wiki entry: raylib enumerated types.

Personally, I tried to avoid enum values requirement as much as possible within the library, actually, only 35 function in raylib could require using some enum value on some of its input parameters.

count enum name values count comments
01 ConfigFlags 16
02 TraceLogLevel 8 3 words name
03 KeyboardKey 114
04 MouseButton 7
05 MouseCursor 11
06 GamepadButton 18
07 GamepadAxis 6
08 MaterialMapIndex 11 3 words name
09 ShaderLocationIndex 26 3 words name
10 ShaderUniformDataType 9 4 words name
11 ShaderAttributeDataType 4 4 words name
12 PixelFormat 24
13 TextureFilter 6
14 TextureWrap 4
15 CubemapLayout 6
16 FontType 3
17 BlendMode 8
18 Gesture 11
19 CameraMode 5
20 CameraProjection 2
21 NPatchLayout 3 3 words name

Conclusion

One of the goals of raylib is being simple and easy-to-use and many hours have been put into the API design; thinking about the best name for every function, the minimum number of parameters required, the right name of each parameter, the data types structure and more.

I think this syntax analysis is useful to see what worked for raylib library and also help to improve it.

Clone this wiki locally