├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── blocks_game.gif ├── images ├── graphics_pipeline.png └── raylib_game_loop_full.png ├── lessons ├── 01_blocks_game_intro.c ├── 02_blocks_game_drawing.c ├── 03_blocks_game_inputs.c ├── 04_blocks_game_collisions.c ├── 05_blocks_game_textures.c ├── 06_blocks_game_text.c ├── 07_blocks_game_audio.c ├── Makefile ├── blocks.rc ├── raylib.ico └── resources │ ├── ball.png │ ├── bounce.wav │ ├── brick.png │ ├── explosion.wav │ ├── paddle.png │ ├── raylib_logo.png │ ├── setback.png │ └── start.wav ├── pong ├── pong.c ├── pong_web.c └── resources │ ├── logo_raylib.png │ ├── pixantiqua.ttf │ ├── pong.wav │ ├── qt-plimp.xm │ └── start.wav └── projects └── VS2022 ├── blocks.sln ├── blocks ├── blocks.vcxproj └── blocks.vcxproj.user └── raylib └── raylib.vcxproj /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: raysan5 4 | patreon: # raylib 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # raysan 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | custom: # Replace with a single custom sponsorship URL 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | 54 | # Visual Studio files 55 | [Dd]ebug/ 56 | [Dd]ebug.DLL/ 57 | [R]elease/ 58 | [Rr]elease.DLL/ 59 | .vs 60 | 61 | # Build folder 62 | [Bb]uild 63 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Lectures code is licensed under an unmodified zlib/libpng license, which is an OSI-certified, BSD-like license that allows static linking with closed source software. 2 | 3 | LICENSE: zlib/libpng 4 | 5 | Copyright (c) 2017-2022 Ramon Santamaria (@raysan5) 6 | 7 | This software is provided "as-is", without any express or implied warranty. In no event 8 | will the authors be held liable for any damages arising from the use of this software. 9 | 10 | Permission is granted to anyone to use this software for any purpose, including commercial 11 | applications, and to alter it and redistribute it freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not claim that you 14 | wrote the original software. If you use this software in a product, an acknowledgment 15 | in the product documentation would be appreciated but is not required. 16 | 17 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented 18 | as being the original software. 19 | 20 | 3. This notice may not be removed or altered from any source distribution. 21 | 22 | -------------------------------------------------------------------------------------------------- 23 | 24 | Lectures are licensed under a Creative Commons Attribution-NonCommercial 4.0 International License. 25 | 26 | LICENSE: Creative Commons Attribution-NonCommercial 4.0 International Public License 27 | 28 | By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-NonCommercial 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. 29 | 30 | Section 1 – Definitions. 31 | 32 | Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. 33 | Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. 34 | Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. 35 | Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. 36 | Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. 37 | Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. 38 | Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. 39 | Licensor means the individual(s) or entity(ies) granting rights under this Public License. 40 | NonCommercial means not primarily intended for or directed towards commercial advantage or monetary compensation. For purposes of this Public License, the exchange of the Licensed Material for other material subject to Copyright and Similar Rights by digital file-sharing or similar means is NonCommercial provided there is no payment of monetary compensation in connection with the exchange. 41 | Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. 42 | Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. 43 | You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. 44 | Section 2 – Scope. 45 | 46 | License grant. 47 | Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: 48 | reproduce and Share the Licensed Material, in whole or in part, for NonCommercial purposes only; and 49 | produce, reproduce, and Share Adapted Material for NonCommercial purposes only. 50 | Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. 51 | Term. The term of this Public License is specified in Section 6(a). 52 | Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. 53 | Downstream recipients. 54 | Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. 55 | No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. 56 | No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). 57 | Other rights. 58 | 59 | Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. 60 | Patent and trademark rights are not licensed under this Public License. 61 | To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties, including when the Licensed Material is used other than for NonCommercial purposes. 62 | Section 3 – License Conditions. 63 | 64 | Your exercise of the Licensed Rights is expressly made subject to the following conditions. 65 | 66 | Attribution. 67 | 68 | If You Share the Licensed Material (including in modified form), You must: 69 | 70 | retain the following if it is supplied by the Licensor with the Licensed Material: 71 | identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); 72 | a copyright notice; 73 | a notice that refers to this Public License; 74 | a notice that refers to the disclaimer of warranties; 75 | a URI or hyperlink to the Licensed Material to the extent reasonably practicable; 76 | indicate if You modified the Licensed Material and retain an indication of any previous modifications; and 77 | indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. 78 | You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. 79 | If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. 80 | If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License. 81 | Section 4 – Sui Generis Database Rights. 82 | 83 | Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: 84 | 85 | for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database for NonCommercial purposes only; 86 | if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and 87 | You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. 88 | For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. 89 | Section 5 – Disclaimer of Warranties and Limitation of Liability. 90 | 91 | Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You. 92 | To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You. 93 | The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. 94 | Section 6 – Term and Termination. 95 | 96 | This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. 97 | Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: 98 | 99 | automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or 100 | upon express reinstatement by the Licensor. 101 | For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. 102 | For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. 103 | Sections 1, 5, 6, 7, and 8 survive termination of this Public License. 104 | Section 7 – Other Terms and Conditions. 105 | 106 | The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. 107 | Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. 108 | Section 8 – Interpretation. 109 | 110 | For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. 111 | To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. 112 | No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. 113 | Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # raylib Introduction Course 3 | 4 | *by Ramon Santamaria ([@raysan5](https://twitter.com/raysan5))* 5 | 6 | ![blocks game](blocks_game.gif "Blocks Game") 7 | 8 | ## Introduction 9 | 10 | In this introductory course to [raylib](http://www.raylib.com/) we will implement a Blocks game similar to the well-known [Arkanoid](https://en.wikipedia.org/wiki/Arkanoid) (Taito, 1986). Along this process we will learn how the videogames life cycle works, how to manage the window and player inputs, and how to draw some graphics on screen. 11 | 12 | [raylib](http://www.raylib.com/) is a simple and easy-to-use library to enjoy videogames programming. 13 | 14 | **Learning Outcomes:** 15 | 16 | - raylib functionality and possibilities 17 | - Videogame life cycle (Init -> Update -> Draw -> DeInit) 18 | - Basic screens management with screens transition 19 | - Basic shapes drawing (circle, rectangle) 20 | - Inputs management (keyboard, mouse) 21 | - Collision detection and resolution 22 | - Textures loading and drawing 23 | - Fonts loading and text drawing 24 | - Sounds and music loading and playing 25 | 26 | **NOTE:** All code provided is in C language for simplicity and clearness but it's up to the student to use more complex C++ code structures (OOP) if desired. 27 | 28 | ## Lessons Summary 29 | 30 | Lesson | Learning outcome | Source file | Related functions 31 | :-----:|------------------|:------------|:-----------------: 32 | [01](#lesson-01-introduction-to-raylib-and-videogames-programming) | raylib functionality,
videogame life cycle,
basic screens management | [01_blocks_game_intro.c](lessons/01_blocks_game_intro.c) | InitWindow(), CloseWindow(),
BeginDrawing(), EndDrawing() 33 | [02](#lesson-02-draw-basic-shapes-circle-rectangle) | basic shapes drawing | [02_blocks_game_drawing.c](lessons/02_blocks_game_drawing.c) | DrawRectangle(), DrawCircle() 34 | [03](#lesson-03-inputs-management-keyboard-mouse) | inputs management | [03_blocks_game_inputs.c](lessons/03_blocks_game_inputs.c) | IsKeyPressed(), IsKeyDown(),
IsMouseButtonPressed(),
IsMouseButtonDown(),
GetMouseX(), GetMouseY() 35 | [04](#lesson-04-collision-detection-and-resolution) | collision detection and resolution | [04_blocks_game_collisions.c](lessons/04_blocks_game_collisions.c) | CheckCollisionCircleRec(),
CheckCollisionRecs(),
CheckCollisionCircles() 36 | [05](#lesson-05-textures-loading-and-drawing) | textures loading and drawing | [05_blocks_game_textures.c](lessons/05_blocks_game_textures.c) | LoadTexture(), UnloadTexture(),
DrawTexture() 37 | [06](#lesson-06-fonts-loading-and-text-drawing) | fonts loading and text drawing | [06_blocks_game_text.c](lessons/06_blocks_game_text.c) | LoadFont(), UnloadFont(),
DrawText(), DrawTextEx() 38 | [07](#lesson-07-sounds-and-music-loading-and-playing) | sounds and music loading and playing | [07_blocks_game_audio.c](lessons/07_blocks_game_audio.c) | InitAudioDevice(), CloseAudioDevice(),
LoadSound(), UnloadSound(),
PlaySound(), LoadMusicStream(), UnloadMusicStream(),
PlayMusicStream() 39 | 40 | **NOTE:** Most of the documentation for the exercise is directly included in the source code files as code comments. Read carefully those comments to understand every task and how implement the proposed solutions. 41 | 42 | ### Lesson 01: Introduction to raylib and videogames programming 43 | 44 | *Lesson code file to review: [01_blocks_game_intro.c](lessons/01_blocks_game_intro.c)* 45 | 46 | In this first lesson we will introduce raylib library and videogames programming principles. We will setup raylib and take a look to its functionality; we will see how videogame life cycle works and we will implement a basic screens management system for our game. 47 | 48 | **Introduction to raylib** 49 | 50 | raylib is simple and easy-to-use library to learn videogames programming. raylib abstracts the user from the more low level libraries like OpenGL or GLFW3. 51 | 52 | Here there are some interesting links to know more about raylib: 53 | 54 | - [raylib Features](http://www.raylib.com) 55 | - [raylib Frequently Asked Questions](https://github.com/raysan5/raylib/blob/master/FAQ.md) 56 | - [raylib Architecture](https://github.com/raysan5/raylib/wiki/raylib-architecture) 57 | - [raylib Functions Cheatsheet](http://www.raylib.com/cheatsheet/cheatsheet.html) 58 | - [raylib Data Structures](https://github.com/raysan5/raylib/wiki/raylib-data-structures) 59 | - [raylib Examples](http://www.raylib.com/examples.html) 60 | - [raylib Wiki](https://github.com/raysan5/raylib/wiki) 61 | 62 | raylib follows the KISS principle, providing simple functions with clear naming conventions. Main documentation for the library functionality is condensed in a single [cheatsheet](http://www.raylib.com/cheatsheet/cheatsheet.html). 63 | 64 | **Environment setup** 65 | 66 | raylib can be used with many environment configurations as far as a code-editor and compiler are provided. 67 | By default, [raylib webpage](http://www.raylib.com/) distributes a Windows Installer containing all required tools to develop videogames with raylib in C/C++ on Windows platforms. Tools included with installer are **preconfigured** versions of: 68 | 69 | - [w64devkit/MinGW](https://github.com/skeeto/w64devkit) - Minimalistic GNU for Windows, including GCC compiler and several tools and libraries 70 | - [Notepad++](https://notepad-plus-plus.org) - Windows simple code editor, preconfigured with multiple compiling scripts 71 | 72 | In case some students desire to use other tools or want to work in another environment different than Windows, detailed information is provided on [raylib Wiki](https://github.com/raysan5/raylib/wiki) to configure raylib on multiple environments, including [macOS](https://github.com/raysan5/raylib/wiki/Working-on-macOS) and [GNU Linux](https://github.com/raysan5/raylib/wiki/Working-on-GNU-Linux) platforms. 73 | 74 | **Basic concept: Game loop** 75 | 76 | The standard videogame game loop or life-cycle consist of 4 parts: **Initialization -> [ Update -> Draw ] -> DeInitialization** 77 | 78 | The following diagram shows this life-cycle, the related processes for every part of the cycle and some of the raylib functions involved in those processes: 79 | 80 | ![raylib Game Loop](images/raylib_game_loop_full.png) 81 | 82 | **Basic concept: Graphic Pipeline** 83 | 84 | Understanding the Graphics Pipeline is very important to understand the processes that happen in a computer to generate one-frame of the game. Despite it could be a quite advanced topic to go into detail, here it is a general diagram of the process: 85 | 86 | ![Graphics pipeline](images/graphics_pipeline.png) 87 | 88 | **Basic concept: Screens management** 89 | 90 | To manage the different screens for our game we have multiple options, we will start with the most simple one, based in game states tracked by a simple enum. 91 | 92 | On our game loop (Update/Draw) we will just check for current game state and we will Update/Draw required data. 93 | 94 | Recommended [raylib examples](http://www.raylib.com/examples.html) to check: 95 | - [core_basic_window](http://www.raylib.com/examples/core/loader.html?name=core_basic_window) - simple code showing a videogame life cycle 96 | - [core_basic_screen_manager](https://github.com/raysan5/raylib/blob/master/examples/core/core_basic_screen_manager.c) - basic screens management structure 97 | 98 | 99 | ### Lesson 02: Draw basic shapes (circle, rectangle) 100 | 101 | *Lesson code file to review: [02_blocks_game_drawing.c](lessons/02_blocks_game_drawing.c)* 102 | 103 | To draw basic shapes, raylib provides the following functions: 104 | ```c 105 | void DrawPixel(int posX, int posY, Color color); 106 | void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color); 107 | void DrawCircle(int centerX, int centerY, float radius, Color color); 108 | void DrawCircleLines(int centerX, int centerY, float radius, Color color); 109 | void DrawRectangle(int posX, int posY, int width, int height, Color color); 110 | void DrawRectangleLines(int posX, int posY, int width, int height, Color color); 111 | ``` 112 | Most of those functions are self explanatory, they must be called in the draw part of the game loop, between `BeginDrawing()` and `EndDrawing()`. User needs to provide the drawing position (x, y), size and color. Just note that in case of rectangle-shapes drawing origin is upper-left corner while drawing circle-shapes origin is set in the center of the circle. 113 | 114 | Recommended [raylib examples](http://www.raylib.com/examples.html) to check: 115 | - [shapes_basic_shapes](http://www.raylib.com/examples/shapes/loader.html?name=shapes_basic_shapes) - basic shapes drawing 116 | - [shapes_logo_raylib](http://www.raylib.com/examples/shapes/loader.html?name=shapes_logo_raylib) - raylib logo drawn using shapes 117 | 118 | 119 | ### Lesson 03: Inputs management (keyboard, mouse) 120 | 121 | *Lesson code file to review: [03_blocks_game_inputs.c](lessons/03_blocks_game_inputs.c)* 122 | 123 | To manage inputs, raylib provides a set of functions to detect keyboard and mouse current state: 124 | ```c 125 | bool IsKeyPressed(int key); // Detect if a key has been pressed once 126 | bool IsKeyDown(int key); // Detect if a key is being pressed 127 | bool IsKeyReleased(int key); // Detect if a key has been released once 128 | bool IsKeyUp(int key); // Detect if a key is NOT being pressed 129 | 130 | bool IsMouseButtonPressed(int button); // Detect if a mouse button has been pressed once 131 | bool IsMouseButtonDown(int button); // Detect if a mouse button is being pressed 132 | bool IsMouseButtonReleased(int button); // Detect if a mouse button has been released once 133 | bool IsMouseButtonUp(int button); // Detect if a mouse button is NOT being pressed 134 | int GetMouseX(void); // Returns mouse position X 135 | int GetMouseY(void); // Returns mouse position Y 136 | Vector2 GetMousePosition(void); // Returns mouse position XY 137 | ``` 138 | This set of functions can be used in the `update` part of the game loop to check **if** one key or button has been pressed (or is being pressed in that frame). 139 | 140 | Recommended [raylib examples](http://www.raylib.com/examples.html) to check: 141 | - [core_input_keys](http://www.raylib.com/examples/core/loader.html?name=core_input_keys) - keyboard inputs check 142 | - [core_input_mouse](http://www.raylib.com/examples/core/loader.html?name=core_input_mouse) - mouse inputs check 143 | 144 | 145 | ### Lesson 04: Collision detection and resolution 146 | 147 | *Lesson code file to review: [04_blocks_game_collisions.c](lessons/04_blocks_game_collisions.c)* 148 | 149 | To check collisions between simple shapes (circle, rectangle), raylib provides the following functions: 150 | ```c 151 | bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2); // Check collision between two rectangles 152 | bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2); // Check collision between two circles 153 | bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec); // Check collision between circle and rectangle 154 | ``` 155 | Those functions return *true* if the involved rectangles/circles collide, is up to the user to resolve that collision in an appropiate way. Keep always in mind that collisions in games are always treatened as two separate parts: **detection** and **resolution**. 156 | 157 | 158 | ### Lesson 05: Textures loading and drawing 159 | 160 | *Lesson code file to review: [05_blocks_game_textures.c](lessons/05_blocks_game_textures.c)* 161 | 162 | Actually texture loading and drawing is a quite complex process: 163 | 164 | First, the image file is loaded, image data is usually decompressed and decodified (.png, .jpg) to obtain a plain array of pixel data; every pixel can be interpreted with different pixel formats (8bit, 16bit, 32bit...) but usually raylib translates that data to RGBA 32Bit (4 channels - RedGrenBlueAlpha, 8bit per channel). Image data is loaded into RAM. 165 | 166 | Second, that image data must be uploaded to VRAM memory (GPU) to be used on screen rendering. 167 | 168 | Third, when drawing a texture to screen, texture is actually pasted over a quad (two triangles structure) and processed to display on the screen; that processing occurs in a per-fragment basis... think about it like a per pixel or sub-pixel processing, placing every fragment on the final canvas. 169 | 170 | raylib provides multiple functions to deal with textures an images, depending on the intended use of the data, user can choose the right one; for example, most of the time, images will be loaded as textures to be displayed on screen but image data can also be used to generate 3d models, like in the case of [heightmaps](https://www.raylib.com/examples/models/loader.html?name=models_heightmap). 171 | 172 | To load and draw textures, raylib provides the following functions: 173 | ```c 174 | Texture2D LoadTexture(const char *fileName); // Load an image file as texture into GPU memory 175 | void UnloadTexture(Texture2D texture); // Unload texture from GPU memory 176 | 177 | void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a texture in the canvas 178 | ``` 179 | 180 | Recommended [raylib examples](http://www.raylib.com/examples.html) to check: 181 | - [textures_logo_raylib](http://www.raylib.com/examples/textures/loader.html?name=textures_logo_raylib) - texture loading and drawing 182 | - [textures_rectangle](http://www.raylib.com/examples/textures/loader.html?name=textures_rectangle) - texture loading and piece drawing 183 | 184 | 185 | ### Lesson 06: Fonts loading and text drawing 186 | 187 | *Lesson code file to review: [06_blocks_game_text.c](lessons/06_blocks_game_text.c)* 188 | 189 | To draw text, raylib loads a default font on `InitWindow()`, that font is used when drawing text with: 190 | ```c 191 | void DrawText(const char *text, int posX, int posY, int fontSize, Color color); 192 | ``` 193 | But raylib users can also load custom fonts, raylib support multiple fonts formats, including TTF format and BMFonts. To load custom fonts and draw with them, use the following functions: 194 | ```c 195 | Font LoadFont(const char *fileName); // Load a Font image into GPU 196 | void UnloadFont(Font font); // Unload Font from GPU memory 197 | 198 | void DrawTextEx(Font font, const char* text, Vector2 position, int fontSize, int spacing, Color tint); 199 | ``` 200 | 201 | Recommended [raylib examples](http://www.raylib.com/examples.html) to check: 202 | - [text_sprite_fonts](http://www.raylib.com/examples/text/loader.html?name=text_sprite_fonts) - sprite fonts loading and drawing 203 | - [text_bmfonts_ttf](http://www.raylib.com/examples/text/loader.html?name=text_bmfont_ttf) - bmfonts and ttf fonts loading 204 | - [text_writing_anim](http://www.raylib.com/examples/text/loader.html?name=text_writing_anim) - text writting animation effect 205 | 206 | 207 | ### Lesson 07: Sounds and music loading and playing 208 | 209 | *Lesson code file to review: [07_blocks_game_audio.c](lessons/07_blocks_game_audio.c)* 210 | 211 | To deal with audio on raylib, first of all, audio device must be initialized. To manage audio device, use the following functions: 212 | ```c 213 | void InitAudioDevice(void); // Initialize audio device and context 214 | void CloseAudioDevice(void); // Close the audio device and context (and music stream) 215 | ``` 216 | To load and play sounds, raylib provides the following functions: 217 | ```c 218 | Sound LoadSound(const char *fileName); // Load sound from file into memory 219 | void UnloadSound(Sound sound); // Unload sound from memory 220 | 221 | void PlaySound(Sound sound); // Play a sound 222 | void PauseSound(Sound sound); // Pause a sound 223 | void ResumeSound(Sound sound); // Resume a paused sound 224 | void StopSound(Sound sound); // Stop playing a sound 225 | ``` 226 | To load and stream music, raylib provides the following functions: 227 | ```c 228 | Music LoadMusicStream(const char *fileName); // Load music stream from file 229 | void UnloadMusicStream(Music music); // Unload music stream 230 | 231 | void UpdateMusicStream(Music music); // Update buffers for music streaming 232 | void PlayMusicStream(Music music); // Start music playing 233 | void PauseMusicStream(Music music); // Pause music playing 234 | void ResumeMusicStream(Music music); // Resume playing paused music 235 | void StopMusicStream(Music music); // Stop music playing 236 | ``` 237 | 238 | Recommended [raylib examples](http://www.raylib.com/examples.html) to check: 239 | - [audio_sound_loading](http://www.raylib.com/examples/audio/loader.html?name=audio_sound_loading) - sounds loading and playing 240 | - [audio_music_stream](http://www.raylib.com/examples/audio/loader.html?name=audio_music_stream) - music loading and streaming 241 | 242 | 243 | ## Getting help 244 | It's recommended to join [raylib Discord community](https://discord.gg/raylib) to ask other developers and get help from the community or just showcase your creations. 245 | 246 | ## License 247 | 248 | This lecture is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License. 249 | 250 | Lessons code is licensed under an unmodified zlib/libpng license. 251 | 252 | Check [LICENSE](LICENSE) for further details. 253 | 254 | *Copyright (c) 2017-2022 Ramon Santamaria ([@raysan5](https://twitter.com/raysan5))* 255 | -------------------------------------------------------------------------------- /blocks_game.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raysan5/raylib-intro-course/8a0472b753b783d1b51958003c70b1b4fedf5a51/blocks_game.gif -------------------------------------------------------------------------------- /images/graphics_pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raysan5/raylib-intro-course/8a0472b753b783d1b51958003c70b1b4fedf5a51/images/graphics_pipeline.png -------------------------------------------------------------------------------- /images/raylib_game_loop_full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raysan5/raylib-intro-course/8a0472b753b783d1b51958003c70b1b4fedf5a51/images/raylib_game_loop_full.png -------------------------------------------------------------------------------- /lessons/01_blocks_game_intro.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * 3 | * PROJECT: BLOCKS GAME 4 | * LESSON 01: raylib intro 5 | * DESCRIPTION: Introduction to raylib and the basic videogames life cycle 6 | * 7 | * COMPILATION (Windows - MinGW): 8 | * gcc -o $(NAME_PART).exe $(FILE_NAME) -lraylib -lopengl32 -lgdi32 -lwinmm -Wall -std=c99 9 | * 10 | * COMPILATION (Linux - GCC): 11 | * gcc -o $(NAME_PART).exe $(FILE_NAME) -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 12 | * 13 | * Example originally created with raylib 2.0, last time updated with raylib 4.2 14 | 15 | * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 16 | * BSD-like license that allows static linking with closed source software 17 | * 18 | * Copyright (c) 2017-2022 Ramon Santamaria (@raysan5) 19 | * 20 | ********************************************************************************************/ 21 | 22 | #include "raylib.h" 23 | 24 | //---------------------------------------------------------------------------------- 25 | // Types and Structures Definition 26 | //---------------------------------------------------------------------------------- 27 | 28 | // LESSON 01: Window initialization and screens management 29 | typedef enum GameScreen { LOGO, TITLE, GAMEPLAY, ENDING } GameScreen; 30 | 31 | // TODO: Define required structs 32 | 33 | //------------------------------------------------------------------------------------ 34 | // Program main entry point 35 | //------------------------------------------------------------------------------------ 36 | int main() 37 | { 38 | // Initialization 39 | //-------------------------------------------------------------------------------------- 40 | const int screenWidth = 800; 41 | const int screenHeight = 450; 42 | 43 | // LESSON 01: Window initialization and screens management 44 | InitWindow(screenWidth, screenHeight, "PROJECT: BLOCKS GAME"); 45 | 46 | // NOTE: Load resources (textures, fonts, audio) after Window initialization 47 | 48 | // Game required variables 49 | GameScreen screen = LOGO; // Current game screen state 50 | 51 | int framesCounter = 0; // General pourpose frames counter 52 | int gameResult = -1; // Game result: 0 - Loose, 1 - Win, -1 - Not defined 53 | bool gamePaused = false; // Game paused state toggle 54 | 55 | // TODO: Define and Initialize game variables 56 | 57 | SetTargetFPS(60); // Set desired framerate (frames per second) 58 | //-------------------------------------------------------------------------------------- 59 | 60 | // Main game loop 61 | while (!WindowShouldClose()) // Detect window close button or ESC key 62 | { 63 | // Update 64 | //---------------------------------------------------------------------------------- 65 | switch(screen) 66 | { 67 | case LOGO: 68 | { 69 | // Update LOGO screen data here! 70 | 71 | framesCounter++; 72 | 73 | if (framesCounter > 180) 74 | { 75 | screen = TITLE; // Change to TITLE screen after 3 seconds 76 | framesCounter = 0; 77 | } 78 | 79 | } break; 80 | case TITLE: 81 | { 82 | // Update TITLE screen data here! 83 | 84 | framesCounter++; 85 | 86 | // LESSON 03: Inputs management (keyboard, mouse) 87 | if (IsKeyPressed(KEY_ENTER)) screen = GAMEPLAY; 88 | 89 | } break; 90 | case GAMEPLAY: 91 | { 92 | // Update GAMEPLAY screen data here! 93 | 94 | if (!gamePaused) 95 | { 96 | // TODO: Gameplay logic 97 | } 98 | 99 | if (IsKeyPressed(KEY_ENTER)) screen = ENDING; 100 | 101 | } break; 102 | case ENDING: 103 | { 104 | // Update END screen data here! 105 | 106 | framesCounter++; 107 | 108 | // LESSON 03: Inputs management (keyboard, mouse) 109 | if (IsKeyPressed(KEY_ENTER)) screen = TITLE; 110 | 111 | } break; 112 | default: break; 113 | } 114 | //---------------------------------------------------------------------------------- 115 | 116 | // Draw 117 | //---------------------------------------------------------------------------------- 118 | BeginDrawing(); 119 | 120 | ClearBackground(RAYWHITE); 121 | 122 | switch(screen) 123 | { 124 | case LOGO: 125 | { 126 | // TODO: Draw LOGO screen here! 127 | DrawText("LOGO SCREEN", 20, 20, 40, LIGHTGRAY); 128 | DrawText("WAIT for 3 SECONDS...", 290, 220, 20, GRAY); 129 | 130 | } break; 131 | case TITLE: 132 | { 133 | // TODO: Draw TITLE screen here! 134 | DrawRectangle(0, 0, screenWidth, screenHeight, GREEN); 135 | DrawText("TITLE SCREEN", 20, 20, 40, DARKGREEN); 136 | DrawText("PRESS ENTER or TAP to JUMP to GAMEPLAY SCREEN", 120, 220, 20, DARKGREEN); 137 | 138 | } break; 139 | case GAMEPLAY: 140 | { 141 | // TODO: Draw GAMEPLAY screen here! 142 | DrawRectangle(0, 0, screenWidth, screenHeight, PURPLE); 143 | DrawText("GAMEPLAY SCREEN", 20, 20, 40, MAROON); 144 | DrawText("PRESS ENTER or TAP to JUMP to ENDING SCREEN", 130, 220, 20, MAROON); 145 | 146 | } break; 147 | case ENDING: 148 | { 149 | // TODO: Draw ENDING screen here! 150 | DrawRectangle(0, 0, screenWidth, screenHeight, BLUE); 151 | DrawText("ENDING SCREEN", 20, 20, 40, DARKBLUE); 152 | DrawText("PRESS ENTER or TAP to RETURN to TITLE SCREEN", 120, 220, 20, DARKBLUE); 153 | 154 | } break; 155 | default: break; 156 | } 157 | 158 | EndDrawing(); 159 | //---------------------------------------------------------------------------------- 160 | } 161 | 162 | // De-Initialization 163 | //-------------------------------------------------------------------------------------- 164 | 165 | // NOTE: Unload any loaded resources (texture, fonts, audio) 166 | 167 | CloseWindow(); // Close window and OpenGL context 168 | //-------------------------------------------------------------------------------------- 169 | 170 | return 0; 171 | } -------------------------------------------------------------------------------- /lessons/02_blocks_game_drawing.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * 3 | * PROJECT: BLOCKS GAME 4 | * LESSON 02: basic drawing 5 | * DESCRIPTION: Basic shapes drawing (lines, circles, rectangles) 6 | * 7 | * COMPILATION (Windows - MinGW): 8 | * gcc -o $(NAME_PART).exe $(FILE_NAME) -lraylib -lopengl32 -lgdi32 -lwinmm -Wall -std=c99 9 | * 10 | * COMPILATION (Linux - GCC): 11 | * gcc -o $(NAME_PART).exe $(FILE_NAME) -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 12 | * 13 | * Example originally created with raylib 2.0, last time updated with raylib 4.2 14 | 15 | * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 16 | * BSD-like license that allows static linking with closed source software 17 | * 18 | * Copyright (c) 2017-2022 Ramon Santamaria (@raysan5) 19 | * 20 | ********************************************************************************************/ 21 | 22 | #include "raylib.h" 23 | 24 | //---------------------------------------------------------------------------------- 25 | // Useful values definitions 26 | //---------------------------------------------------------------------------------- 27 | #define PLAYER_LIFES 5 28 | #define BRICKS_LINES 5 29 | #define BRICKS_PER_LINE 20 30 | 31 | #define BRICKS_POSITION_Y 50 32 | 33 | //---------------------------------------------------------------------------------- 34 | // Types and Structures Definition 35 | //---------------------------------------------------------------------------------- 36 | 37 | // LESSON 01: Window initialization and screens management 38 | typedef enum GameScreen { LOGO, TITLE, GAMEPLAY, ENDING } GameScreen; 39 | 40 | // Player structure 41 | typedef struct Player { 42 | Vector2 position; 43 | Vector2 speed; 44 | Vector2 size; 45 | Rectangle bounds; 46 | int lifes; 47 | } Player; 48 | 49 | // Ball structure 50 | typedef struct Ball { 51 | Vector2 position; 52 | Vector2 speed; 53 | float radius; 54 | bool active; 55 | } Ball; 56 | 57 | // Bricks structure 58 | typedef struct Brick { 59 | Vector2 position; 60 | Vector2 size; 61 | Rectangle bounds; 62 | int resistance; 63 | bool active; 64 | } Brick; 65 | 66 | //------------------------------------------------------------------------------------ 67 | // Program main entry point 68 | //------------------------------------------------------------------------------------ 69 | int main() 70 | { 71 | // Initialization 72 | //-------------------------------------------------------------------------------------- 73 | const int screenWidth = 800; 74 | const int screenHeight = 450; 75 | 76 | // LESSON 01: Window initialization and screens management 77 | InitWindow(screenWidth, screenHeight, "PROJECT: BLOCKS GAME"); 78 | 79 | // NOTE: Load resources (textures, fonts, audio) after Window initialization 80 | 81 | // Game required variables 82 | GameScreen screen = LOGO; // Current game screen state 83 | 84 | int framesCounter = 0; // General pourpose frames counter 85 | int gameResult = -1; // Game result: 0 - Loose, 1 - Win, -1 - Not defined 86 | bool gamePaused = false; // Game paused state toggle 87 | 88 | // NOTE: Check defined structs on top 89 | Player player = { 0 }; 90 | Ball ball = { 0 }; 91 | Brick bricks[BRICKS_LINES][BRICKS_PER_LINE] = { 0 }; 92 | 93 | // Initialize player 94 | player.position = (Vector2){ screenWidth/2, screenHeight*7/8 }; 95 | player.speed = (Vector2){ 8.0f, 0.0f }; 96 | player.size = (Vector2){ 100, 24 }; 97 | player.lifes = PLAYER_LIFES; 98 | 99 | // Initialize ball 100 | ball.radius = 10.0f; 101 | ball.active = false; 102 | ball.position = (Vector2){ player.position.x + player.size.x/2, player.position.y - ball.radius*2 }; 103 | ball.speed = (Vector2){ 4.0f, 4.0f }; 104 | 105 | // Initialize bricks 106 | for (int j = 0; j < BRICKS_LINES; j++) 107 | { 108 | for (int i = 0; i < BRICKS_PER_LINE; i++) 109 | { 110 | bricks[j][i].size = (Vector2){ screenWidth/BRICKS_PER_LINE, 20 }; 111 | bricks[j][i].position = (Vector2){ i*bricks[j][i].size.x, j*bricks[j][i].size.y + BRICKS_POSITION_Y }; 112 | bricks[j][i].bounds = (Rectangle){ bricks[j][i].position.x, bricks[j][i].position.y, bricks[j][i].size.x, bricks[j][i].size.y }; 113 | bricks[j][i].active = true; 114 | } 115 | } 116 | 117 | SetTargetFPS(60); // Set desired framerate (frames per second) 118 | //-------------------------------------------------------------------------------------- 119 | 120 | // Main game loop 121 | while (!WindowShouldClose()) // Detect window close button or ESC key 122 | { 123 | // Update 124 | //---------------------------------------------------------------------------------- 125 | switch(screen) 126 | { 127 | case LOGO: 128 | { 129 | // Update LOGO screen data here! 130 | 131 | framesCounter++; 132 | 133 | if (framesCounter > 180) 134 | { 135 | screen = TITLE; // Change to TITLE screen after 3 seconds 136 | framesCounter = 0; 137 | } 138 | 139 | } break; 140 | case TITLE: 141 | { 142 | // Update TITLE screen data here! 143 | 144 | framesCounter++; 145 | 146 | // LESSON 03: Inputs management (keyboard, mouse) 147 | if (IsKeyPressed(KEY_ENTER)) screen = GAMEPLAY; 148 | 149 | } break; 150 | case GAMEPLAY: 151 | { 152 | // Update GAMEPLAY screen data here! 153 | 154 | if (!gamePaused) 155 | { 156 | // TODO: Gameplay logic 157 | } 158 | 159 | } break; 160 | case ENDING: 161 | { 162 | // Update END screen data here! 163 | 164 | framesCounter++; 165 | 166 | // LESSON 03: Inputs management (keyboard, mouse) 167 | if (IsKeyPressed(KEY_ENTER)) 168 | { 169 | // Replay / Exit game logic 170 | screen = TITLE; 171 | } 172 | 173 | } break; 174 | default: break; 175 | } 176 | //---------------------------------------------------------------------------------- 177 | 178 | // Draw 179 | //---------------------------------------------------------------------------------- 180 | BeginDrawing(); 181 | 182 | ClearBackground(RAYWHITE); 183 | 184 | switch(screen) 185 | { 186 | case LOGO: 187 | { 188 | // Draw LOGO screen here! 189 | 190 | DrawText("LOGO SCREEN", 20, 20, 40, LIGHTGRAY); 191 | 192 | } break; 193 | case TITLE: 194 | { 195 | // Draw TITLE screen here! 196 | 197 | DrawText("TITLE SCREEN", 20, 20, 40, DARKGREEN); 198 | 199 | if ((framesCounter/30)%2 == 0) DrawText("PRESS [ENTER] to START", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] to START", 20)/2, GetScreenHeight()/2 + 60, 20, DARKGRAY); 200 | 201 | } break; 202 | case GAMEPLAY: 203 | { 204 | // Draw GAMEPLAY screen here! 205 | 206 | // LESSON 02: Draw basic shapes (circle, rectangle) 207 | DrawRectangle(player.position.x, player.position.y, player.size.x, player.size.y, BLACK); // Draw player bar 208 | DrawCircleV(ball.position, ball.radius, MAROON); // Draw ball 209 | 210 | // Draw bricks 211 | for (int j = 0; j < BRICKS_LINES; j++) 212 | { 213 | for (int i = 0; i < BRICKS_PER_LINE; i++) 214 | { 215 | if (bricks[j][i].active) 216 | { 217 | if ((i + j)%2 == 0) DrawRectangle(bricks[j][i].position.x, bricks[j][i].position.y, bricks[j][i].size.x, bricks[j][i].size.y, GRAY); 218 | else DrawRectangle(bricks[j][i].position.x, bricks[j][i].position.y, bricks[j][i].size.x, bricks[j][i].size.y, DARKGRAY); 219 | } 220 | } 221 | } 222 | 223 | // Draw GUI: player lives 224 | for (int i = 0; i < player.lifes; i++) DrawRectangle(20 + 40*i, screenHeight - 30, 35, 10, LIGHTGRAY); 225 | 226 | // Draw pause message when required 227 | if (gamePaused) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 + 60, 40, GRAY); 228 | 229 | } break; 230 | case ENDING: 231 | { 232 | // Draw END screen here! 233 | 234 | DrawText("ENDING SCREEN", 20, 20, 40, DARKBLUE); 235 | 236 | if ((framesCounter/30)%2 == 0) DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 + 80, 20, GRAY); 237 | 238 | } break; 239 | default: break; 240 | } 241 | 242 | EndDrawing(); 243 | //---------------------------------------------------------------------------------- 244 | } 245 | 246 | // De-Initialization 247 | //-------------------------------------------------------------------------------------- 248 | 249 | // NOTE: Unload any loaded resources (texture, fonts, audio) 250 | 251 | CloseWindow(); // Close window and OpenGL context 252 | //-------------------------------------------------------------------------------------- 253 | 254 | return 0; 255 | } 256 | -------------------------------------------------------------------------------- /lessons/03_blocks_game_inputs.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * 3 | * PROJECT: BLOCKS GAME 4 | * LESSON 03: inputs management 5 | * DESCRIPTION: Read user inputs (keyboard, mouse) 6 | * 7 | * COMPILATION (Windows - MinGW): 8 | * gcc -o $(NAME_PART).exe $(FILE_NAME) -lraylib -lopengl32 -lgdi32 -lwinmm -Wall -std=c99 9 | * 10 | * COMPILATION (Linux - GCC): 11 | * gcc -o $(NAME_PART).exe $(FILE_NAME) -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 12 | * 13 | * Example originally created with raylib 2.0, last time updated with raylib 4.2 14 | 15 | * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 16 | * BSD-like license that allows static linking with closed source software 17 | * 18 | * Copyright (c) 2017-2022 Ramon Santamaria (@raysan5) 19 | * 20 | ********************************************************************************************/ 21 | 22 | #include "raylib.h" 23 | 24 | //---------------------------------------------------------------------------------- 25 | // Useful values definitions 26 | //---------------------------------------------------------------------------------- 27 | #define PLAYER_LIFES 5 28 | #define BRICKS_LINES 5 29 | #define BRICKS_PER_LINE 20 30 | 31 | #define BRICKS_POSITION_Y 50 32 | 33 | //---------------------------------------------------------------------------------- 34 | // Types and Structures Definition 35 | //---------------------------------------------------------------------------------- 36 | 37 | // LESSON 01: Window initialization and screens management 38 | typedef enum GameScreen { LOGO, TITLE, GAMEPLAY, ENDING } GameScreen; 39 | 40 | // Player structure 41 | typedef struct Player { 42 | Vector2 position; 43 | Vector2 speed; 44 | Vector2 size; 45 | Rectangle bounds; 46 | int lifes; 47 | } Player; 48 | 49 | // Ball structure 50 | typedef struct Ball { 51 | Vector2 position; 52 | Vector2 speed; 53 | float radius; 54 | bool active; 55 | } Ball; 56 | 57 | // Bricks structure 58 | typedef struct Brick { 59 | Vector2 position; 60 | Vector2 size; 61 | Rectangle bounds; 62 | int resistance; 63 | bool active; 64 | } Brick; 65 | 66 | //------------------------------------------------------------------------------------ 67 | // Program main entry point 68 | //------------------------------------------------------------------------------------ 69 | int main() 70 | { 71 | // Initialization 72 | //-------------------------------------------------------------------------------------- 73 | const int screenWidth = 800; 74 | const int screenHeight = 450; 75 | 76 | // LESSON 01: Window initialization and screens management 77 | InitWindow(screenWidth, screenHeight, "PROJECT: BLOCKS GAME"); 78 | 79 | // NOTE: Load resources (textures, fonts, audio) after Window initialization 80 | 81 | // Game required variables 82 | GameScreen screen = LOGO; // Current game screen state 83 | 84 | int framesCounter = 0; // General pourpose frames counter 85 | int gameResult = -1; // Game result: 0 - Loose, 1 - Win, -1 - Not defined 86 | bool gamePaused = false; // Game paused state toggle 87 | 88 | // NOTE: Check defined structs on top 89 | Player player = { 0 }; 90 | Ball ball = { 0 }; 91 | Brick bricks[BRICKS_LINES][BRICKS_PER_LINE] = { 0 }; 92 | 93 | // Initialize player 94 | player.position = (Vector2){ screenWidth/2, screenHeight*7/8 }; 95 | player.speed = (Vector2){ 8.0f, 0.0f }; 96 | player.size = (Vector2){ 100, 24 }; 97 | player.lifes = PLAYER_LIFES; 98 | 99 | // Initialize ball 100 | ball.radius = 10.0f; 101 | ball.active = false; 102 | ball.position = (Vector2){ player.position.x + player.size.x/2, player.position.y - ball.radius*2 }; 103 | ball.speed = (Vector2){ 4.0f, 4.0f }; 104 | 105 | // Initialize bricks 106 | for (int j = 0; j < BRICKS_LINES; j++) 107 | { 108 | for (int i = 0; i < BRICKS_PER_LINE; i++) 109 | { 110 | bricks[j][i].size = (Vector2){ screenWidth/BRICKS_PER_LINE, 20 }; 111 | bricks[j][i].position = (Vector2){ i*bricks[j][i].size.x, j*bricks[j][i].size.y + BRICKS_POSITION_Y }; 112 | bricks[j][i].bounds = (Rectangle){ bricks[j][i].position.x, bricks[j][i].position.y, bricks[j][i].size.x, bricks[j][i].size.y }; 113 | bricks[j][i].active = true; 114 | } 115 | } 116 | 117 | SetTargetFPS(60); // Set desired framerate (frames per second) 118 | //-------------------------------------------------------------------------------------- 119 | 120 | // Main game loop 121 | while (!WindowShouldClose()) // Detect window close button or ESC key 122 | { 123 | // Update 124 | //---------------------------------------------------------------------------------- 125 | switch(screen) 126 | { 127 | case LOGO: 128 | { 129 | // Update LOGO screen data here! 130 | 131 | framesCounter++; 132 | 133 | if (framesCounter > 180) 134 | { 135 | screen = TITLE; // Change to TITLE screen after 3 seconds 136 | framesCounter = 0; 137 | } 138 | 139 | } break; 140 | case TITLE: 141 | { 142 | // Update TITLE screen data here! 143 | 144 | framesCounter++; 145 | 146 | // LESSON 03: Inputs management (keyboard, mouse) 147 | if (IsKeyPressed(KEY_ENTER)) screen = GAMEPLAY; 148 | 149 | } break; 150 | case GAMEPLAY: 151 | { 152 | // Update GAMEPLAY screen data here! 153 | 154 | // LESSON 03: Inputs management (keyboard, mouse) 155 | if (IsKeyPressed('P')) gamePaused = !gamePaused; // Pause button logic 156 | 157 | if (!gamePaused) 158 | { 159 | // LESSON 03: Inputs management (keyboard, mouse) 160 | 161 | // Player movement logic 162 | if (IsKeyDown(KEY_LEFT)) player.position.x -= player.speed.x; 163 | if (IsKeyDown(KEY_RIGHT)) player.position.x += player.speed.x; 164 | 165 | if ((player.position.x) <= 0) player.position.x = 0; 166 | if ((player.position.x + player.size.x) >= screenWidth) player.position.x = screenWidth - player.size.x; 167 | 168 | player.bounds = (Rectangle){ player.position.x, player.position.y, player.size.x, player.size.y }; 169 | 170 | if (ball.active) 171 | { 172 | // Ball movement logic 173 | ball.position.x += ball.speed.x; 174 | ball.position.y += ball.speed.y; 175 | 176 | // Collision logic: ball vs screen-limits 177 | if (((ball.position.x + ball.radius) >= screenWidth) || ((ball.position.x - ball.radius) <= 0)) ball.speed.x *= -1; 178 | if ((ball.position.y - ball.radius) <= 0) ball.speed.y *= -1; 179 | 180 | // TODO: Collision detection and resolution 181 | 182 | // Game ending logic 183 | if ((ball.position.y + ball.radius) >= screenHeight) 184 | { 185 | ball.position.x = player.position.x + player.size.x/2; 186 | ball.position.y = player.position.y - ball.radius - 1.0f; 187 | ball.speed = (Vector2){ 0, 0 }; 188 | ball.active = false; 189 | 190 | player.lifes--; 191 | } 192 | 193 | if (player.lifes < 0) 194 | { 195 | screen = ENDING; 196 | player.lifes = 5; 197 | framesCounter = 0; 198 | } 199 | } 200 | else 201 | { 202 | // Reset ball position 203 | ball.position.x = player.position.x + player.size.x/2; 204 | 205 | // LESSON 03: Inputs management (keyboard, mouse) 206 | if (IsKeyPressed(KEY_SPACE)) 207 | { 208 | // Activate ball logic 209 | ball.active = true; 210 | ball.speed = (Vector2){ 0, -5.0f }; 211 | } 212 | } 213 | } 214 | 215 | } break; 216 | case ENDING: 217 | { 218 | // Update END screen data here! 219 | 220 | framesCounter++; 221 | 222 | // LESSON 03: Inputs management (keyboard, mouse) 223 | if (IsKeyPressed(KEY_ENTER)) 224 | { 225 | // Replay / Exit game logic 226 | screen = TITLE; 227 | } 228 | 229 | } break; 230 | default: break; 231 | } 232 | //---------------------------------------------------------------------------------- 233 | 234 | // Draw 235 | //---------------------------------------------------------------------------------- 236 | BeginDrawing(); 237 | 238 | ClearBackground(RAYWHITE); 239 | 240 | switch(screen) 241 | { 242 | case LOGO: 243 | { 244 | // Draw LOGO screen here! 245 | 246 | DrawText("LOGO SCREEN", 20, 20, 40, LIGHTGRAY); 247 | 248 | } break; 249 | case TITLE: 250 | { 251 | // Draw TITLE screen here! 252 | 253 | DrawText("TITLE SCREEN", 20, 20, 40, DARKGREEN); 254 | 255 | if ((framesCounter/30)%2 == 0) DrawText("PRESS [ENTER] to START", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] to START", 20)/2, GetScreenHeight()/2 + 60, 20, DARKGRAY); 256 | 257 | } break; 258 | case GAMEPLAY: 259 | { 260 | // Draw GAMEPLAY screen here! 261 | 262 | // LESSON 02: Draw basic shapes (circle, rectangle) 263 | DrawRectangle(player.position.x, player.position.y, player.size.x, player.size.y, BLACK); // Draw player bar 264 | DrawCircleV(ball.position, ball.radius, MAROON); // Draw ball 265 | 266 | // Draw bricks 267 | for (int j = 0; j < BRICKS_LINES; j++) 268 | { 269 | for (int i = 0; i < BRICKS_PER_LINE; i++) 270 | { 271 | if (bricks[j][i].active) 272 | { 273 | if ((i + j)%2 == 0) DrawRectangle(bricks[j][i].position.x, bricks[j][i].position.y, bricks[j][i].size.x, bricks[j][i].size.y, GRAY); 274 | else DrawRectangle(bricks[j][i].position.x, bricks[j][i].position.y, bricks[j][i].size.x, bricks[j][i].size.y, DARKGRAY); 275 | } 276 | } 277 | } 278 | 279 | // Draw GUI: player lives 280 | for (int i = 0; i < player.lifes; i++) DrawRectangle(20 + 40*i, screenHeight - 30, 35, 10, LIGHTGRAY); 281 | 282 | // Draw pause message when required 283 | if (gamePaused) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 + 60, 40, GRAY); 284 | 285 | } break; 286 | case ENDING: 287 | { 288 | // Draw END screen here! 289 | 290 | DrawText("ENDING SCREEN", 20, 20, 40, DARKBLUE); 291 | 292 | if ((framesCounter/30)%2 == 0) DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 + 80, 20, GRAY); 293 | 294 | } break; 295 | default: break; 296 | } 297 | 298 | EndDrawing(); 299 | //---------------------------------------------------------------------------------- 300 | } 301 | 302 | // De-Initialization 303 | //-------------------------------------------------------------------------------------- 304 | 305 | // NOTE: Unload any loaded resources (texture, fonts, audio) 306 | 307 | CloseWindow(); // Close window and OpenGL context 308 | //-------------------------------------------------------------------------------------- 309 | 310 | return 0; 311 | } 312 | -------------------------------------------------------------------------------- /lessons/04_blocks_game_collisions.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * 3 | * PROJECT: BLOCKS GAME 4 | * LESSON 04: collisions 5 | * DESCRIPTION: Collision detection and resolution 6 | * 7 | * COMPILATION (Windows - MinGW): 8 | * gcc -o $(NAME_PART).exe $(FILE_NAME) -lraylib -lopengl32 -lgdi32 -lwinmm -Wall -std=c99 9 | * 10 | * COMPILATION (Linux - GCC): 11 | * gcc -o $(NAME_PART).exe $(FILE_NAME) -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 12 | * 13 | * Example originally created with raylib 2.0, last time updated with raylib 4.2 14 | 15 | * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 16 | * BSD-like license that allows static linking with closed source software 17 | * 18 | * Copyright (c) 2017-2022 Ramon Santamaria (@raysan5) 19 | * 20 | ********************************************************************************************/ 21 | 22 | #include "raylib.h" 23 | 24 | //---------------------------------------------------------------------------------- 25 | // Useful values definitions 26 | //---------------------------------------------------------------------------------- 27 | #define PLAYER_LIFES 5 28 | #define BRICKS_LINES 5 29 | #define BRICKS_PER_LINE 20 30 | 31 | #define BRICKS_POSITION_Y 50 32 | 33 | //---------------------------------------------------------------------------------- 34 | // Types and Structures Definition 35 | //---------------------------------------------------------------------------------- 36 | 37 | // LESSON 01: Window initialization and screens management 38 | typedef enum GameScreen { LOGO, TITLE, GAMEPLAY, ENDING } GameScreen; 39 | 40 | // Player structure 41 | typedef struct Player { 42 | Vector2 position; 43 | Vector2 speed; 44 | Vector2 size; 45 | Rectangle bounds; 46 | int lifes; 47 | } Player; 48 | 49 | // Ball structure 50 | typedef struct Ball { 51 | Vector2 position; 52 | Vector2 speed; 53 | float radius; 54 | bool active; 55 | } Ball; 56 | 57 | // Bricks structure 58 | typedef struct Brick { 59 | Vector2 position; 60 | Vector2 size; 61 | Rectangle bounds; 62 | int resistance; 63 | bool active; 64 | } Brick; 65 | 66 | //------------------------------------------------------------------------------------ 67 | // Program main entry point 68 | //------------------------------------------------------------------------------------ 69 | int main() 70 | { 71 | // Initialization 72 | //-------------------------------------------------------------------------------------- 73 | const int screenWidth = 800; 74 | const int screenHeight = 450; 75 | 76 | // LESSON 01: Window initialization and screens management 77 | InitWindow(screenWidth, screenHeight, "PROJECT: BLOCKS GAME"); 78 | 79 | // NOTE: Load resources (textures, fonts, audio) after Window initialization 80 | 81 | // Game required variables 82 | GameScreen screen = LOGO; // Current game screen state 83 | 84 | int framesCounter = 0; // General pourpose frames counter 85 | int gameResult = -1; // Game result: 0 - Loose, 1 - Win, -1 - Not defined 86 | bool gamePaused = false; // Game paused state toggle 87 | 88 | // NOTE: Check defined structs on top 89 | Player player = { 0 }; 90 | Ball ball = { 0 }; 91 | Brick bricks[BRICKS_LINES][BRICKS_PER_LINE] = { 0 }; 92 | 93 | // Initialize player 94 | player.position = (Vector2){ screenWidth/2, screenHeight*7/8 }; 95 | player.speed = (Vector2){ 8.0f, 0.0f }; 96 | player.size = (Vector2){ 100, 24 }; 97 | player.lifes = PLAYER_LIFES; 98 | 99 | // Initialize ball 100 | ball.radius = 10.0f; 101 | ball.active = false; 102 | ball.position = (Vector2){ player.position.x + player.size.x/2, player.position.y - ball.radius*2 }; 103 | ball.speed = (Vector2){ 4.0f, 4.0f }; 104 | 105 | // Initialize bricks 106 | for (int j = 0; j < BRICKS_LINES; j++) 107 | { 108 | for (int i = 0; i < BRICKS_PER_LINE; i++) 109 | { 110 | bricks[j][i].size = (Vector2){ screenWidth/BRICKS_PER_LINE, 20 }; 111 | bricks[j][i].position = (Vector2){ i*bricks[j][i].size.x, j*bricks[j][i].size.y + BRICKS_POSITION_Y }; 112 | bricks[j][i].bounds = (Rectangle){ bricks[j][i].position.x, bricks[j][i].position.y, bricks[j][i].size.x, bricks[j][i].size.y }; 113 | bricks[j][i].active = true; 114 | } 115 | } 116 | 117 | SetTargetFPS(60); // Set desired framerate (frames per second) 118 | //-------------------------------------------------------------------------------------- 119 | 120 | // Main game loop 121 | while (!WindowShouldClose()) // Detect window close button or ESC key 122 | { 123 | // Update 124 | //---------------------------------------------------------------------------------- 125 | switch(screen) 126 | { 127 | case LOGO: 128 | { 129 | // Update LOGO screen data here! 130 | 131 | framesCounter++; 132 | 133 | if (framesCounter > 180) 134 | { 135 | screen = TITLE; // Change to TITLE screen after 3 seconds 136 | framesCounter = 0; 137 | } 138 | 139 | } break; 140 | case TITLE: 141 | { 142 | // Update TITLE screen data here! 143 | 144 | framesCounter++; 145 | 146 | // LESSON 03: Inputs management (keyboard, mouse) 147 | if (IsKeyPressed(KEY_ENTER)) screen = GAMEPLAY; 148 | 149 | } break; 150 | case GAMEPLAY: 151 | { 152 | // Update GAMEPLAY screen data here! 153 | 154 | // LESSON 03: Inputs management (keyboard, mouse) 155 | if (IsKeyPressed('P')) gamePaused = !gamePaused; // Pause button logic 156 | 157 | if (!gamePaused) 158 | { 159 | // LESSON 03: Inputs management (keyboard, mouse) 160 | 161 | // Player movement logic 162 | if (IsKeyDown(KEY_LEFT)) player.position.x -= player.speed.x; 163 | if (IsKeyDown(KEY_RIGHT)) player.position.x += player.speed.x; 164 | 165 | if ((player.position.x) <= 0) player.position.x = 0; 166 | if ((player.position.x + player.size.x) >= screenWidth) player.position.x = screenWidth - player.size.x; 167 | 168 | player.bounds = (Rectangle){ player.position.x, player.position.y, player.size.x, player.size.y }; 169 | 170 | if (ball.active) 171 | { 172 | // Ball movement logic 173 | ball.position.x += ball.speed.x; 174 | ball.position.y += ball.speed.y; 175 | 176 | // Collision logic: ball vs screen-limits 177 | if (((ball.position.x + ball.radius) >= screenWidth) || ((ball.position.x - ball.radius) <= 0)) ball.speed.x *= -1; 178 | if ((ball.position.y - ball.radius) <= 0) ball.speed.y *= -1; 179 | 180 | // LESSON 04: Collision detection and resolution 181 | 182 | // NOTE: For collisions we consider elements bounds parameters, 183 | // that's independent of elements drawing but they should match texture parameters 184 | 185 | // Collision logic: ball vs player 186 | if (CheckCollisionCircleRec(ball.position, ball.radius, player.bounds)) 187 | { 188 | ball.speed.y *= -1; 189 | ball.speed.x = (ball.position.x - (player.position.x + player.size.x/2))/player.size.x*5.0f; 190 | } 191 | 192 | // Collision logic: ball vs bricks 193 | for (int j = 0; j < BRICKS_LINES; j++) 194 | { 195 | for (int i = 0; i < BRICKS_PER_LINE; i++) 196 | { 197 | if (bricks[j][i].active && (CheckCollisionCircleRec(ball.position, ball.radius, bricks[j][i].bounds))) 198 | { 199 | bricks[j][i].active = false; 200 | ball.speed.y *= -1; 201 | 202 | break; 203 | } 204 | } 205 | } 206 | 207 | // Game ending logic 208 | if ((ball.position.y + ball.radius) >= screenHeight) 209 | { 210 | ball.position.x = player.position.x + player.size.x/2; 211 | ball.position.y = player.position.y - ball.radius - 1.0f; 212 | ball.speed = (Vector2){ 0, 0 }; 213 | ball.active = false; 214 | 215 | player.lifes--; 216 | } 217 | 218 | if (player.lifes < 0) 219 | { 220 | screen = ENDING; 221 | player.lifes = 5; 222 | framesCounter = 0; 223 | } 224 | } 225 | else 226 | { 227 | // Reset ball position 228 | ball.position.x = player.position.x + player.size.x/2; 229 | 230 | // LESSON 03: Inputs management (keyboard, mouse) 231 | if (IsKeyPressed(KEY_SPACE)) 232 | { 233 | // Activate ball logic 234 | ball.active = true; 235 | ball.speed = (Vector2){ 0, -5.0f }; 236 | } 237 | } 238 | } 239 | 240 | } break; 241 | case ENDING: 242 | { 243 | // Update END screen data here! 244 | 245 | framesCounter++; 246 | 247 | // LESSON 03: Inputs management (keyboard, mouse) 248 | if (IsKeyPressed(KEY_ENTER)) 249 | { 250 | // Replay / Exit game logic 251 | screen = TITLE; 252 | } 253 | 254 | } break; 255 | default: break; 256 | } 257 | //---------------------------------------------------------------------------------- 258 | 259 | // Draw 260 | //---------------------------------------------------------------------------------- 261 | BeginDrawing(); 262 | 263 | ClearBackground(RAYWHITE); 264 | 265 | switch(screen) 266 | { 267 | case LOGO: 268 | { 269 | // Draw LOGO screen here! 270 | 271 | DrawText("LOGO SCREEN", 20, 20, 40, LIGHTGRAY); 272 | 273 | } break; 274 | case TITLE: 275 | { 276 | // Draw TITLE screen here! 277 | 278 | DrawText("TITLE SCREEN", 20, 20, 40, DARKGREEN); 279 | 280 | if ((framesCounter/30)%2 == 0) DrawText("PRESS [ENTER] to START", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] to START", 20)/2, GetScreenHeight()/2 + 60, 20, DARKGRAY); 281 | 282 | } break; 283 | case GAMEPLAY: 284 | { 285 | // Draw GAMEPLAY screen here! 286 | 287 | // LESSON 02: Draw basic shapes (circle, rectangle) 288 | DrawRectangle(player.position.x, player.position.y, player.size.x, player.size.y, BLACK); // Draw player bar 289 | DrawCircleV(ball.position, ball.radius, MAROON); // Draw ball 290 | 291 | // Draw bricks 292 | for (int j = 0; j < BRICKS_LINES; j++) 293 | { 294 | for (int i = 0; i < BRICKS_PER_LINE; i++) 295 | { 296 | if (bricks[j][i].active) 297 | { 298 | if ((i + j)%2 == 0) DrawRectangle(bricks[j][i].position.x, bricks[j][i].position.y, bricks[j][i].size.x, bricks[j][i].size.y, GRAY); 299 | else DrawRectangle(bricks[j][i].position.x, bricks[j][i].position.y, bricks[j][i].size.x, bricks[j][i].size.y, DARKGRAY); 300 | } 301 | } 302 | } 303 | 304 | // Draw GUI: player lives 305 | for (int i = 0; i < player.lifes; i++) DrawRectangle(20 + 40*i, screenHeight - 30, 35, 10, LIGHTGRAY); 306 | 307 | // Draw pause message when required 308 | if (gamePaused) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 + 60, 40, GRAY); 309 | 310 | } break; 311 | case ENDING: 312 | { 313 | // Draw END screen here! 314 | 315 | DrawText("ENDING SCREEN", 20, 20, 40, DARKBLUE); 316 | 317 | if ((framesCounter/30)%2 == 0) DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 + 80, 20, GRAY); 318 | 319 | } break; 320 | default: break; 321 | } 322 | 323 | EndDrawing(); 324 | //---------------------------------------------------------------------------------- 325 | } 326 | 327 | // De-Initialization 328 | //-------------------------------------------------------------------------------------- 329 | 330 | // NOTE: Unload any loaded resources (texture, fonts, audio) 331 | 332 | CloseWindow(); // Close window and OpenGL context 333 | //-------------------------------------------------------------------------------------- 334 | 335 | return 0; 336 | } 337 | -------------------------------------------------------------------------------- /lessons/05_blocks_game_textures.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * 3 | * PROJECT: BLOCKS GAME 4 | * LESSON 05: textures 5 | * DESCRIPTION: Textures loading and drawing 6 | * 7 | * COMPILATION (Windows - MinGW): 8 | * gcc -o $(NAME_PART).exe $(FILE_NAME) -lraylib -lopengl32 -lgdi32 -lwinmm -Wall -std=c99 9 | * 10 | * COMPILATION (Linux - GCC): 11 | * gcc -o $(NAME_PART).exe $(FILE_NAME) -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 12 | * 13 | * Example originally created with raylib 2.0, last time updated with raylib 4.2 14 | 15 | * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 16 | * BSD-like license that allows static linking with closed source software 17 | * 18 | * Copyright (c) 2017-2022 Ramon Santamaria (@raysan5) 19 | * 20 | ********************************************************************************************/ 21 | 22 | #include "raylib.h" 23 | 24 | //---------------------------------------------------------------------------------- 25 | // Useful values definitions 26 | //---------------------------------------------------------------------------------- 27 | #define PLAYER_LIFES 5 28 | #define BRICKS_LINES 5 29 | #define BRICKS_PER_LINE 20 30 | 31 | #define BRICKS_POSITION_Y 50 32 | 33 | //---------------------------------------------------------------------------------- 34 | // Types and Structures Definition 35 | //---------------------------------------------------------------------------------- 36 | 37 | // LESSON 01: Window initialization and screens management 38 | typedef enum GameScreen { LOGO, TITLE, GAMEPLAY, ENDING } GameScreen; 39 | 40 | // Player structure 41 | typedef struct Player { 42 | Vector2 position; 43 | Vector2 speed; 44 | Vector2 size; 45 | Rectangle bounds; 46 | int lifes; 47 | } Player; 48 | 49 | // Ball structure 50 | typedef struct Ball { 51 | Vector2 position; 52 | Vector2 speed; 53 | float radius; 54 | bool active; 55 | } Ball; 56 | 57 | // Bricks structure 58 | typedef struct Brick { 59 | Vector2 position; 60 | Vector2 size; 61 | Rectangle bounds; 62 | int resistance; 63 | bool active; 64 | } Brick; 65 | 66 | //------------------------------------------------------------------------------------ 67 | // Program main entry point 68 | //------------------------------------------------------------------------------------ 69 | int main() 70 | { 71 | // Initialization 72 | //-------------------------------------------------------------------------------------- 73 | const int screenWidth = 800; 74 | const int screenHeight = 450; 75 | 76 | // LESSON 01: Window initialization and screens management 77 | InitWindow(screenWidth, screenHeight, "PROJECT: BLOCKS GAME"); 78 | 79 | // NOTE: Load resources (textures, fonts, audio) after Window initialization 80 | 81 | // LESSON 05: Textures loading and drawing 82 | Texture2D texLogo = LoadTexture("resources/raylib_logo.png"); 83 | Texture2D texBall = LoadTexture("resources/ball.png"); 84 | Texture2D texPaddle = LoadTexture("resources/paddle.png"); 85 | Texture2D texBrick = LoadTexture("resources/brick.png"); 86 | 87 | // Game required variables 88 | GameScreen screen = LOGO; // Current game screen state 89 | 90 | int framesCounter = 0; // General pourpose frames counter 91 | int gameResult = -1; // Game result: 0 - Loose, 1 - Win, -1 - Not defined 92 | bool gamePaused = false; // Game paused state toggle 93 | 94 | // NOTE: Check defined structs on top 95 | Player player = { 0 }; 96 | Ball ball = { 0 }; 97 | Brick bricks[BRICKS_LINES][BRICKS_PER_LINE] = { 0 }; 98 | 99 | // Initialize player 100 | player.position = (Vector2){ screenWidth/2, screenHeight*7/8 }; 101 | player.speed = (Vector2){ 8.0f, 0.0f }; 102 | player.size = (Vector2){ 100, 24 }; 103 | player.lifes = PLAYER_LIFES; 104 | 105 | // Initialize ball 106 | ball.radius = 10.0f; 107 | ball.active = false; 108 | ball.position = (Vector2){ player.position.x + player.size.x/2, player.position.y - ball.radius*2 }; 109 | ball.speed = (Vector2){ 4.0f, 4.0f }; 110 | 111 | // Initialize bricks 112 | for (int j = 0; j < BRICKS_LINES; j++) 113 | { 114 | for (int i = 0; i < BRICKS_PER_LINE; i++) 115 | { 116 | bricks[j][i].size = (Vector2){ screenWidth/BRICKS_PER_LINE, 20 }; 117 | bricks[j][i].position = (Vector2){ i*bricks[j][i].size.x, j*bricks[j][i].size.y + BRICKS_POSITION_Y }; 118 | bricks[j][i].bounds = (Rectangle){ bricks[j][i].position.x, bricks[j][i].position.y, bricks[j][i].size.x, bricks[j][i].size.y }; 119 | bricks[j][i].active = true; 120 | } 121 | } 122 | 123 | SetTargetFPS(60); // Set desired framerate (frames per second) 124 | //-------------------------------------------------------------------------------------- 125 | 126 | // Main game loop 127 | while (!WindowShouldClose()) // Detect window close button or ESC key 128 | { 129 | // Update 130 | //---------------------------------------------------------------------------------- 131 | switch(screen) 132 | { 133 | case LOGO: 134 | { 135 | // Update LOGO screen data here! 136 | 137 | framesCounter++; 138 | 139 | if (framesCounter > 180) 140 | { 141 | screen = TITLE; // Change to TITLE screen after 3 seconds 142 | framesCounter = 0; 143 | } 144 | 145 | } break; 146 | case TITLE: 147 | { 148 | // Update TITLE screen data here! 149 | 150 | framesCounter++; 151 | 152 | // LESSON 03: Inputs management (keyboard, mouse) 153 | if (IsKeyPressed(KEY_ENTER)) screen = GAMEPLAY; 154 | 155 | } break; 156 | case GAMEPLAY: 157 | { 158 | // Update GAMEPLAY screen data here! 159 | 160 | // LESSON 03: Inputs management (keyboard, mouse) 161 | if (IsKeyPressed('P')) gamePaused = !gamePaused; // Pause button logic 162 | 163 | if (!gamePaused) 164 | { 165 | // LESSON 03: Inputs management (keyboard, mouse) 166 | 167 | // Player movement logic 168 | if (IsKeyDown(KEY_LEFT)) player.position.x -= player.speed.x; 169 | if (IsKeyDown(KEY_RIGHT)) player.position.x += player.speed.x; 170 | 171 | if ((player.position.x) <= 0) player.position.x = 0; 172 | if ((player.position.x + player.size.x) >= screenWidth) player.position.x = screenWidth - player.size.x; 173 | 174 | player.bounds = (Rectangle){ player.position.x, player.position.y, player.size.x, player.size.y }; 175 | 176 | if (ball.active) 177 | { 178 | // Ball movement logic 179 | ball.position.x += ball.speed.x; 180 | ball.position.y += ball.speed.y; 181 | 182 | // Collision logic: ball vs screen-limits 183 | if (((ball.position.x + ball.radius) >= screenWidth) || ((ball.position.x - ball.radius) <= 0)) ball.speed.x *= -1; 184 | if ((ball.position.y - ball.radius) <= 0) ball.speed.y *= -1; 185 | 186 | // LESSON 04: Collision detection and resolution 187 | 188 | // NOTE: For collisions we consider elements bounds parameters, 189 | // that's independent of elements drawing but they should match texture parameters 190 | 191 | // Collision logic: ball vs player 192 | if (CheckCollisionCircleRec(ball.position, ball.radius, player.bounds)) 193 | { 194 | ball.speed.y *= -1; 195 | ball.speed.x = (ball.position.x - (player.position.x + player.size.x/2))/player.size.x*5.0f; 196 | } 197 | 198 | // Collision logic: ball vs bricks 199 | for (int j = 0; j < BRICKS_LINES; j++) 200 | { 201 | for (int i = 0; i < BRICKS_PER_LINE; i++) 202 | { 203 | if (bricks[j][i].active && (CheckCollisionCircleRec(ball.position, ball.radius, bricks[j][i].bounds))) 204 | { 205 | bricks[j][i].active = false; 206 | ball.speed.y *= -1; 207 | 208 | break; 209 | } 210 | } 211 | } 212 | 213 | // Game ending logic 214 | if ((ball.position.y + ball.radius) >= screenHeight) 215 | { 216 | ball.position.x = player.position.x + player.size.x/2; 217 | ball.position.y = player.position.y - ball.radius - 1.0f; 218 | ball.speed = (Vector2){ 0, 0 }; 219 | ball.active = false; 220 | 221 | player.lifes--; 222 | } 223 | 224 | if (player.lifes < 0) 225 | { 226 | screen = ENDING; 227 | player.lifes = 5; 228 | framesCounter = 0; 229 | } 230 | } 231 | else 232 | { 233 | // Reset ball position 234 | ball.position.x = player.position.x + player.size.x/2; 235 | 236 | // LESSON 03: Inputs management (keyboard, mouse) 237 | if (IsKeyPressed(KEY_SPACE)) 238 | { 239 | // Activate ball logic 240 | ball.active = true; 241 | ball.speed = (Vector2){ 0, -5.0f }; 242 | } 243 | } 244 | } 245 | 246 | } break; 247 | case ENDING: 248 | { 249 | // Update END screen data here! 250 | 251 | framesCounter++; 252 | 253 | // LESSON 03: Inputs management (keyboard, mouse) 254 | if (IsKeyPressed(KEY_ENTER)) 255 | { 256 | // Replay / Exit game logic 257 | screen = TITLE; 258 | } 259 | 260 | } break; 261 | default: break; 262 | } 263 | //---------------------------------------------------------------------------------- 264 | 265 | // Draw 266 | //---------------------------------------------------------------------------------- 267 | BeginDrawing(); 268 | 269 | ClearBackground(RAYWHITE); 270 | 271 | switch(screen) 272 | { 273 | case LOGO: 274 | { 275 | // Draw LOGO screen here! 276 | 277 | // LESSON 05: Textures loading and drawing 278 | DrawTexture(texLogo, screenWidth/2 - texLogo.width/2, screenHeight/2 - texLogo.height/2, WHITE); 279 | 280 | } break; 281 | case TITLE: 282 | { 283 | // Draw TITLE screen here! 284 | 285 | DrawText("TITLE SCREEN", 20, 20, 40, DARKGREEN); 286 | 287 | if ((framesCounter/30)%2 == 0) DrawText("PRESS [ENTER] to START", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] to START", 20)/2, GetScreenHeight()/2 + 60, 20, DARKGRAY); 288 | 289 | } break; 290 | case GAMEPLAY: 291 | { 292 | // Draw GAMEPLAY screen here! 293 | 294 | #define LESSON05_TEXTURES // Alternative: LESSON02_SHAPES 295 | #if defined(LESSON02_SHAPES) 296 | // LESSON 02: Draw basic shapes (circle, rectangle) 297 | DrawRectangle(player.position.x, player.position.y, player.size.x, player.size.y, BLACK); // Draw player bar 298 | DrawCircleV(ball.position, ball.radius, MAROON); // Draw ball 299 | 300 | // Draw bricks 301 | for (int j = 0; j < BRICKS_LINES; j++) 302 | { 303 | for (int i = 0; i < BRICKS_PER_LINE; i++) 304 | { 305 | if (bricks[j][i].active) 306 | { 307 | if ((i + j)%2 == 0) DrawRectangle(bricks[j][i].position.x, bricks[j][i].position.y, bricks[j][i].size.x, bricks[j][i].size.y, GRAY); 308 | else DrawRectangle(bricks[j][i].position.x, bricks[j][i].position.y, bricks[j][i].size.x, bricks[j][i].size.y, DARKGRAY); 309 | } 310 | } 311 | } 312 | #elif defined(LESSON05_TEXTURES) 313 | // LESSON 05: Textures loading and drawing 314 | DrawTextureEx(texPaddle, player.position, 0.0f, 1.0f, WHITE); // Draw player 315 | 316 | DrawTexture(texBall, ball.position.x - ball.radius/2, ball.position.y - ball.radius/2, MAROON); // Draw ball 317 | 318 | // Draw bricks 319 | for (int j = 0; j < BRICKS_LINES; j++) 320 | { 321 | for (int i = 0; i < BRICKS_PER_LINE; i++) 322 | { 323 | if (bricks[j][i].active) 324 | { 325 | // NOTE: Texture is not scaled, just using original size 326 | 327 | if ((i + j)%2 == 0) DrawTextureEx(texBrick, bricks[j][i].position, 0.0f, 1.0f, GRAY); 328 | else DrawTextureEx(texBrick, bricks[j][i].position, 0.0f, 1.0f, DARKGRAY); 329 | } 330 | } 331 | } 332 | #endif 333 | 334 | // Draw GUI: player lives 335 | for (int i = 0; i < player.lifes; i++) DrawRectangle(20 + 40*i, screenHeight - 30, 35, 10, LIGHTGRAY); 336 | 337 | // Draw pause message when required 338 | if (gamePaused) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 + 60, 40, GRAY); 339 | 340 | } break; 341 | case ENDING: 342 | { 343 | // Draw END screen here! 344 | 345 | DrawText("ENDING SCREEN", 20, 20, 40, DARKBLUE); 346 | 347 | if ((framesCounter/30)%2 == 0) DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 + 80, 20, GRAY); 348 | 349 | } break; 350 | default: break; 351 | } 352 | 353 | EndDrawing(); 354 | //---------------------------------------------------------------------------------- 355 | } 356 | 357 | // De-Initialization 358 | //-------------------------------------------------------------------------------------- 359 | 360 | // NOTE: Unload any loaded resources (texture, fonts, audio) 361 | 362 | // LESSON 05: Textures loading and drawing 363 | UnloadTexture(texBall); 364 | UnloadTexture(texPaddle); 365 | UnloadTexture(texBrick); 366 | 367 | CloseWindow(); // Close window and OpenGL context 368 | //-------------------------------------------------------------------------------------- 369 | 370 | return 0; 371 | } 372 | -------------------------------------------------------------------------------- /lessons/06_blocks_game_text.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * 3 | * PROJECT: BLOCKS GAME 4 | * LESSON 06: text 5 | * DESCRIPTION: Font loading and text drawing 6 | * 7 | * COMPILATION (Windows - MinGW): 8 | * gcc -o $(NAME_PART).exe $(FILE_NAME) -lraylib -lopengl32 -lgdi32 -lwinmm -Wall -std=c99 9 | * 10 | * COMPILATION (Linux - GCC): 11 | * gcc -o $(NAME_PART).exe $(FILE_NAME) -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 12 | * 13 | * Example originally created with raylib 2.0, last time updated with raylib 4.2 14 | 15 | * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 16 | * BSD-like license that allows static linking with closed source software 17 | * 18 | * Copyright (c) 2017-2022 Ramon Santamaria (@raysan5) 19 | * 20 | ********************************************************************************************/ 21 | 22 | #include "raylib.h" 23 | 24 | //---------------------------------------------------------------------------------- 25 | // Useful values definitions 26 | //---------------------------------------------------------------------------------- 27 | #define PLAYER_LIFES 5 28 | #define BRICKS_LINES 5 29 | #define BRICKS_PER_LINE 20 30 | 31 | #define BRICKS_POSITION_Y 50 32 | 33 | //---------------------------------------------------------------------------------- 34 | // Types and Structures Definition 35 | //---------------------------------------------------------------------------------- 36 | 37 | // LESSON 01: Window initialization and screens management 38 | typedef enum GameScreen { LOGO, TITLE, GAMEPLAY, ENDING } GameScreen; 39 | 40 | // Player structure 41 | typedef struct Player { 42 | Vector2 position; 43 | Vector2 speed; 44 | Vector2 size; 45 | Rectangle bounds; 46 | int lifes; 47 | } Player; 48 | 49 | // Ball structure 50 | typedef struct Ball { 51 | Vector2 position; 52 | Vector2 speed; 53 | float radius; 54 | bool active; 55 | } Ball; 56 | 57 | // Bricks structure 58 | typedef struct Brick { 59 | Vector2 position; 60 | Vector2 size; 61 | Rectangle bounds; 62 | int resistance; 63 | bool active; 64 | } Brick; 65 | 66 | //------------------------------------------------------------------------------------ 67 | // Program main entry point 68 | //------------------------------------------------------------------------------------ 69 | int main() 70 | { 71 | // Initialization 72 | //-------------------------------------------------------------------------------------- 73 | const int screenWidth = 800; 74 | const int screenHeight = 450; 75 | 76 | // LESSON 01: Window initialization and screens management 77 | InitWindow(screenWidth, screenHeight, "PROJECT: BLOCKS GAME"); 78 | 79 | // NOTE: Load resources (textures, fonts, audio) after Window initialization 80 | 81 | // LESSON 05: Textures loading and drawing 82 | Texture2D texLogo = LoadTexture("resources/raylib_logo.png"); 83 | Texture2D texBall = LoadTexture("resources/ball.png"); 84 | Texture2D texPaddle = LoadTexture("resources/paddle.png"); 85 | Texture2D texBrick = LoadTexture("resources/brick.png"); 86 | 87 | // LESSON 06: Fonts loading and text drawing 88 | Font font = LoadFont("resources/setback.png"); 89 | 90 | // Game required variables 91 | GameScreen screen = LOGO; // Current game screen state 92 | 93 | int framesCounter = 0; // General pourpose frames counter 94 | int gameResult = -1; // Game result: 0 - Loose, 1 - Win, -1 - Not defined 95 | bool gamePaused = false; // Game paused state toggle 96 | 97 | // NOTE: Check defined structs on top 98 | Player player = { 0 }; 99 | Ball ball = { 0 }; 100 | Brick bricks[BRICKS_LINES][BRICKS_PER_LINE] = { 0 }; 101 | 102 | // Initialize player 103 | player.position = (Vector2){ screenWidth/2, screenHeight*7/8 }; 104 | player.speed = (Vector2){ 8.0f, 0.0f }; 105 | player.size = (Vector2){ 100, 24 }; 106 | player.lifes = PLAYER_LIFES; 107 | 108 | // Initialize ball 109 | ball.radius = 10.0f; 110 | ball.active = false; 111 | ball.position = (Vector2){ player.position.x + player.size.x/2, player.position.y - ball.radius*2 }; 112 | ball.speed = (Vector2){ 4.0f, 4.0f }; 113 | 114 | // Initialize bricks 115 | for (int j = 0; j < BRICKS_LINES; j++) 116 | { 117 | for (int i = 0; i < BRICKS_PER_LINE; i++) 118 | { 119 | bricks[j][i].size = (Vector2){ screenWidth/BRICKS_PER_LINE, 20 }; 120 | bricks[j][i].position = (Vector2){ i*bricks[j][i].size.x, j*bricks[j][i].size.y + BRICKS_POSITION_Y }; 121 | bricks[j][i].bounds = (Rectangle){ bricks[j][i].position.x, bricks[j][i].position.y, bricks[j][i].size.x, bricks[j][i].size.y }; 122 | bricks[j][i].active = true; 123 | } 124 | } 125 | 126 | SetTargetFPS(60); // Set desired framerate (frames per second) 127 | //-------------------------------------------------------------------------------------- 128 | 129 | // Main game loop 130 | while (!WindowShouldClose()) // Detect window close button or ESC key 131 | { 132 | // Update 133 | //---------------------------------------------------------------------------------- 134 | switch(screen) 135 | { 136 | case LOGO: 137 | { 138 | // Update LOGO screen data here! 139 | 140 | framesCounter++; 141 | 142 | if (framesCounter > 180) 143 | { 144 | screen = TITLE; // Change to TITLE screen after 3 seconds 145 | framesCounter = 0; 146 | } 147 | 148 | } break; 149 | case TITLE: 150 | { 151 | // Update TITLE screen data here! 152 | 153 | framesCounter++; 154 | 155 | // LESSON 03: Inputs management (keyboard, mouse) 156 | if (IsKeyPressed(KEY_ENTER)) screen = GAMEPLAY; 157 | 158 | } break; 159 | case GAMEPLAY: 160 | { 161 | // Update GAMEPLAY screen data here! 162 | 163 | // LESSON 03: Inputs management (keyboard, mouse) 164 | if (IsKeyPressed('P')) gamePaused = !gamePaused; // Pause button logic 165 | 166 | if (!gamePaused) 167 | { 168 | // LESSON 03: Inputs management (keyboard, mouse) 169 | 170 | // Player movement logic 171 | if (IsKeyDown(KEY_LEFT)) player.position.x -= player.speed.x; 172 | if (IsKeyDown(KEY_RIGHT)) player.position.x += player.speed.x; 173 | 174 | if ((player.position.x) <= 0) player.position.x = 0; 175 | if ((player.position.x + player.size.x) >= screenWidth) player.position.x = screenWidth - player.size.x; 176 | 177 | player.bounds = (Rectangle){ player.position.x, player.position.y, player.size.x, player.size.y }; 178 | 179 | if (ball.active) 180 | { 181 | // Ball movement logic 182 | ball.position.x += ball.speed.x; 183 | ball.position.y += ball.speed.y; 184 | 185 | // Collision logic: ball vs screen-limits 186 | if (((ball.position.x + ball.radius) >= screenWidth) || ((ball.position.x - ball.radius) <= 0)) ball.speed.x *= -1; 187 | if ((ball.position.y - ball.radius) <= 0) ball.speed.y *= -1; 188 | 189 | // LESSON 04: Collision detection and resolution 190 | 191 | // NOTE: For collisions we consider elements bounds parameters, 192 | // that's independent of elements drawing but they should match texture parameters 193 | 194 | // Collision logic: ball vs player 195 | if (CheckCollisionCircleRec(ball.position, ball.radius, player.bounds)) 196 | { 197 | ball.speed.y *= -1; 198 | ball.speed.x = (ball.position.x - (player.position.x + player.size.x/2))/player.size.x*5.0f; 199 | } 200 | 201 | // Collision logic: ball vs bricks 202 | for (int j = 0; j < BRICKS_LINES; j++) 203 | { 204 | for (int i = 0; i < BRICKS_PER_LINE; i++) 205 | { 206 | if (bricks[j][i].active && (CheckCollisionCircleRec(ball.position, ball.radius, bricks[j][i].bounds))) 207 | { 208 | bricks[j][i].active = false; 209 | ball.speed.y *= -1; 210 | 211 | break; 212 | } 213 | } 214 | } 215 | 216 | // Game ending logic 217 | if ((ball.position.y + ball.radius) >= screenHeight) 218 | { 219 | ball.position.x = player.position.x + player.size.x/2; 220 | ball.position.y = player.position.y - ball.radius - 1.0f; 221 | ball.speed = (Vector2){ 0, 0 }; 222 | ball.active = false; 223 | 224 | player.lifes--; 225 | } 226 | 227 | if (player.lifes < 0) 228 | { 229 | screen = ENDING; 230 | player.lifes = 5; 231 | framesCounter = 0; 232 | } 233 | } 234 | else 235 | { 236 | // Reset ball position 237 | ball.position.x = player.position.x + player.size.x/2; 238 | 239 | // LESSON 03: Inputs management (keyboard, mouse) 240 | if (IsKeyPressed(KEY_SPACE)) 241 | { 242 | // Activate ball logic 243 | ball.active = true; 244 | ball.speed = (Vector2){ 0, -5.0f }; 245 | } 246 | } 247 | } 248 | 249 | } break; 250 | case ENDING: 251 | { 252 | // Update END screen data here! 253 | 254 | framesCounter++; 255 | 256 | // LESSON 03: Inputs management (keyboard, mouse) 257 | if (IsKeyPressed(KEY_ENTER)) 258 | { 259 | // Replay / Exit game logic 260 | screen = TITLE; 261 | } 262 | 263 | } break; 264 | default: break; 265 | } 266 | //---------------------------------------------------------------------------------- 267 | 268 | // Draw 269 | //---------------------------------------------------------------------------------- 270 | BeginDrawing(); 271 | 272 | ClearBackground(RAYWHITE); 273 | 274 | switch(screen) 275 | { 276 | case LOGO: 277 | { 278 | // Draw LOGO screen here! 279 | 280 | // LESSON 05: Textures loading and drawing 281 | DrawTexture(texLogo, screenWidth/2 - texLogo.width/2, screenHeight/2 - texLogo.height/2, WHITE); 282 | 283 | } break; 284 | case TITLE: 285 | { 286 | // Draw TITLE screen here! 287 | 288 | // LESSON 06: Fonts loading and text drawing 289 | DrawTextEx(font, "BLOCKS", (Vector2){ 100, 80 }, 160, 10, MAROON); // Draw Title 290 | 291 | if ((framesCounter/30)%2 == 0) DrawText("PRESS [ENTER] to START", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] to START", 20)/2, GetScreenHeight()/2 + 60, 20, DARKGRAY); 292 | 293 | } break; 294 | case GAMEPLAY: 295 | { 296 | // Draw GAMEPLAY screen here! 297 | 298 | #define LESSON05_TEXTURES // Alternative: LESSON02_SHAPES 299 | #if defined(LESSON02_SHAPES) 300 | // LESSON 02: Draw basic shapes (circle, rectangle) 301 | DrawRectangle(player.position.x, player.position.y, player.size.x, player.size.y, BLACK); // Draw player bar 302 | DrawCircleV(ball.position, ball.radius, MAROON); // Draw ball 303 | 304 | // Draw bricks 305 | for (int j = 0; j < BRICKS_LINES; j++) 306 | { 307 | for (int i = 0; i < BRICKS_PER_LINE; i++) 308 | { 309 | if (bricks[j][i].active) 310 | { 311 | if ((i + j)%2 == 0) DrawRectangle(bricks[j][i].position.x, bricks[j][i].position.y, bricks[j][i].size.x, bricks[j][i].size.y, GRAY); 312 | else DrawRectangle(bricks[j][i].position.x, bricks[j][i].position.y, bricks[j][i].size.x, bricks[j][i].size.y, DARKGRAY); 313 | } 314 | } 315 | } 316 | #elif defined(LESSON05_TEXTURES) 317 | // LESSON 05: Textures loading and drawing 318 | DrawTextureEx(texPaddle, player.position, 0.0f, 1.0f, WHITE); // Draw player 319 | 320 | DrawTexture(texBall, ball.position.x - ball.radius/2, ball.position.y - ball.radius/2, MAROON); // Draw ball 321 | 322 | // Draw bricks 323 | for (int j = 0; j < BRICKS_LINES; j++) 324 | { 325 | for (int i = 0; i < BRICKS_PER_LINE; i++) 326 | { 327 | if (bricks[j][i].active) 328 | { 329 | // NOTE: Texture is not scaled, just using original size 330 | 331 | if ((i + j)%2 == 0) DrawTextureEx(texBrick, bricks[j][i].position, 0.0f, 1.0f, GRAY); 332 | else DrawTextureEx(texBrick, bricks[j][i].position, 0.0f, 1.0f, DARKGRAY); 333 | } 334 | } 335 | } 336 | #endif 337 | 338 | // Draw GUI: player lives 339 | for (int i = 0; i < player.lifes; i++) DrawRectangle(20 + 40*i, screenHeight - 30, 35, 10, LIGHTGRAY); 340 | 341 | // Draw pause message when required 342 | if (gamePaused) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 + 60, 40, GRAY); 343 | 344 | } break; 345 | case ENDING: 346 | { 347 | // Draw END screen here! 348 | 349 | // LESSON 06: Fonts loading and text drawing 350 | // Draw ending message 351 | DrawTextEx(font, "GAME FINISHED", (Vector2){ 80, 100 }, 80, 6, MAROON); 352 | 353 | if ((framesCounter/30)%2 == 0) DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 + 80, 20, GRAY); 354 | 355 | } break; 356 | default: break; 357 | } 358 | 359 | EndDrawing(); 360 | //---------------------------------------------------------------------------------- 361 | } 362 | 363 | // De-Initialization 364 | //-------------------------------------------------------------------------------------- 365 | 366 | // NOTE: Unload any loaded resources (texture, fonts, audio) 367 | 368 | // LESSON 05: Textures loading and drawing 369 | UnloadTexture(texBall); 370 | UnloadTexture(texPaddle); 371 | UnloadTexture(texBrick); 372 | 373 | // LESSON 06: Fonts loading and text drawing 374 | UnloadFont(font); 375 | 376 | CloseWindow(); // Close window and OpenGL context 377 | //-------------------------------------------------------------------------------------- 378 | 379 | return 0; 380 | } 381 | -------------------------------------------------------------------------------- /lessons/07_blocks_game_audio.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * 3 | * PROJECT: BLOCKS GAME 4 | * LESSON 07: audio 5 | * DESCRIPTION: Sounds and music loading and playing 6 | * 7 | * COMPILATION (Windows - MinGW): 8 | * gcc -o $(NAME_PART).exe $(FILE_NAME) -lraylib -lopengl32 -lgdi32 -lwinmm -Wall -std=c99 9 | * 10 | * COMPILATION (Linux - GCC): 11 | * gcc -o $(NAME_PART).exe $(FILE_NAME) -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 12 | * 13 | * Example originally created with raylib 2.0, last time updated with raylib 4.2 14 | 15 | * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 16 | * BSD-like license that allows static linking with closed source software 17 | * 18 | * Copyright (c) 2017-2022 Ramon Santamaria (@raysan5) 19 | * 20 | ********************************************************************************************/ 21 | 22 | #include "raylib.h" 23 | 24 | //---------------------------------------------------------------------------------- 25 | // Useful values definitions 26 | //---------------------------------------------------------------------------------- 27 | #define PLAYER_LIFES 5 28 | #define BRICKS_LINES 5 29 | #define BRICKS_PER_LINE 20 30 | 31 | #define BRICKS_POSITION_Y 50 32 | 33 | //---------------------------------------------------------------------------------- 34 | // Types and Structures Definition 35 | //---------------------------------------------------------------------------------- 36 | 37 | // LESSON 01: Window initialization and screens management 38 | typedef enum GameScreen { LOGO, TITLE, GAMEPLAY, ENDING } GameScreen; 39 | 40 | // Player structure 41 | typedef struct Player { 42 | Vector2 position; 43 | Vector2 speed; 44 | Vector2 size; 45 | Rectangle bounds; 46 | int lifes; 47 | } Player; 48 | 49 | // Ball structure 50 | typedef struct Ball { 51 | Vector2 position; 52 | Vector2 speed; 53 | float radius; 54 | bool active; 55 | } Ball; 56 | 57 | // Bricks structure 58 | typedef struct Brick { 59 | Vector2 position; 60 | Vector2 size; 61 | Rectangle bounds; 62 | int resistance; 63 | bool active; 64 | } Brick; 65 | 66 | //------------------------------------------------------------------------------------ 67 | // Program main entry point 68 | //------------------------------------------------------------------------------------ 69 | int main() 70 | { 71 | // Initialization 72 | //-------------------------------------------------------------------------------------- 73 | const int screenWidth = 800; 74 | const int screenHeight = 450; 75 | 76 | // LESSON 01: Window initialization and screens management 77 | InitWindow(screenWidth, screenHeight, "PROJECT: BLOCKS GAME"); 78 | 79 | // NOTE: Load resources (textures, fonts, audio) after Window initialization 80 | 81 | // LESSON 05: Textures loading and drawing 82 | Texture2D texLogo = LoadTexture("resources/raylib_logo.png"); 83 | Texture2D texBall = LoadTexture("resources/ball.png"); 84 | Texture2D texPaddle = LoadTexture("resources/paddle.png"); 85 | Texture2D texBrick = LoadTexture("resources/brick.png"); 86 | 87 | // LESSON 06: Fonts loading and text drawing 88 | Font font = LoadFont("resources/setback.png"); 89 | 90 | // LESSON 07: Sounds and music loading and playing 91 | InitAudioDevice(); // Initialize audio system 92 | 93 | Sound fxStart = LoadSound("resources/start.wav"); 94 | Sound fxBounce = LoadSound("resources/bounce.wav"); 95 | Sound fxExplode = LoadSound("resources/explosion.wav"); 96 | 97 | Music music = LoadMusicStream("resources/blockshock.mod"); 98 | 99 | PlayMusicStream(music); // Start music streaming 100 | 101 | // Game required variables 102 | GameScreen screen = LOGO; // Current game screen state 103 | 104 | int framesCounter = 0; // General purpose frames counter 105 | int gameResult = -1; // Game result: 0 - Loose, 1 - Win, -1 - Not defined 106 | bool gamePaused = false; // Game paused state toggle 107 | 108 | // NOTE: Check defined structs on top 109 | Player player = { 0 }; 110 | Ball ball = { 0 }; 111 | Brick bricks[BRICKS_LINES][BRICKS_PER_LINE] = { 0 }; 112 | 113 | // Initialize player 114 | player.position = (Vector2){ screenWidth/2, screenHeight*7/8 }; 115 | player.speed = (Vector2){ 8.0f, 0.0f }; 116 | player.size = (Vector2){ 100, 24 }; 117 | player.lifes = PLAYER_LIFES; 118 | 119 | // Initialize ball 120 | ball.radius = 10.0f; 121 | ball.active = false; 122 | ball.position = (Vector2){ player.position.x + player.size.x/2, player.position.y - ball.radius*2 }; 123 | ball.speed = (Vector2){ 4.0f, 4.0f }; 124 | 125 | // Initialize bricks 126 | for (int j = 0; j < BRICKS_LINES; j++) 127 | { 128 | for (int i = 0; i < BRICKS_PER_LINE; i++) 129 | { 130 | bricks[j][i].size = (Vector2){ screenWidth/BRICKS_PER_LINE, 20 }; 131 | bricks[j][i].position = (Vector2){ i*bricks[j][i].size.x, j*bricks[j][i].size.y + BRICKS_POSITION_Y }; 132 | bricks[j][i].bounds = (Rectangle){ bricks[j][i].position.x, bricks[j][i].position.y, bricks[j][i].size.x, bricks[j][i].size.y }; 133 | bricks[j][i].active = true; 134 | } 135 | } 136 | 137 | SetTargetFPS(60); // Set desired framerate (frames per second) 138 | //-------------------------------------------------------------------------------------- 139 | 140 | // Main game loop 141 | while (!WindowShouldClose()) // Detect window close button or ESC key 142 | { 143 | // Update 144 | //---------------------------------------------------------------------------------- 145 | switch(screen) 146 | { 147 | case LOGO: 148 | { 149 | // Update LOGO screen data here! 150 | 151 | framesCounter++; 152 | 153 | if (framesCounter > 180) 154 | { 155 | screen = TITLE; // Change to TITLE screen after 3 seconds 156 | framesCounter = 0; 157 | } 158 | 159 | } break; 160 | case TITLE: 161 | { 162 | // Update TITLE screen data here! 163 | 164 | framesCounter++; 165 | 166 | // LESSON 03: Inputs management (keyboard, mouse) 167 | if (IsKeyPressed(KEY_ENTER)) 168 | { 169 | screen = GAMEPLAY; 170 | PlaySound(fxStart); 171 | } 172 | 173 | } break; 174 | case GAMEPLAY: 175 | { 176 | // Update GAMEPLAY screen data here! 177 | 178 | // LESSON 03: Inputs management (keyboard, mouse) 179 | if (IsKeyPressed('P')) gamePaused = !gamePaused; // Pause button logic 180 | 181 | if (!gamePaused) 182 | { 183 | // LESSON 03: Inputs management (keyboard, mouse) 184 | 185 | // Player movement logic 186 | if (IsKeyDown(KEY_LEFT)) player.position.x -= player.speed.x; 187 | if (IsKeyDown(KEY_RIGHT)) player.position.x += player.speed.x; 188 | 189 | if ((player.position.x) <= 0) player.position.x = 0; 190 | if ((player.position.x + player.size.x) >= screenWidth) player.position.x = screenWidth - player.size.x; 191 | 192 | player.bounds = (Rectangle){ player.position.x, player.position.y, player.size.x, player.size.y }; 193 | 194 | if (ball.active) 195 | { 196 | // Ball movement logic 197 | ball.position.x += ball.speed.x; 198 | ball.position.y += ball.speed.y; 199 | 200 | // Collision logic: ball vs screen-limits 201 | if (((ball.position.x + ball.radius) >= screenWidth) || ((ball.position.x - ball.radius) <= 0)) ball.speed.x *= -1; 202 | if ((ball.position.y - ball.radius) <= 0) ball.speed.y *= -1; 203 | 204 | // LESSON 04: Collision detection and resolution 205 | 206 | // NOTE: For collisions we consider elements bounds parameters, 207 | // that's independent of elements drawing but they should match texture parameters 208 | 209 | // Collision logic: ball vs player 210 | if (CheckCollisionCircleRec(ball.position, ball.radius, player.bounds)) 211 | { 212 | ball.speed.y *= -1; 213 | ball.speed.x = (ball.position.x - (player.position.x + player.size.x/2))/player.size.x*5.0f; 214 | PlaySound(fxBounce); 215 | } 216 | 217 | // Collision logic: ball vs bricks 218 | for (int j = 0; j < BRICKS_LINES; j++) 219 | { 220 | for (int i = 0; i < BRICKS_PER_LINE; i++) 221 | { 222 | if (bricks[j][i].active && (CheckCollisionCircleRec(ball.position, ball.radius, bricks[j][i].bounds))) 223 | { 224 | bricks[j][i].active = false; 225 | ball.speed.y *= -1; 226 | PlaySound(fxExplode); 227 | 228 | break; 229 | } 230 | } 231 | } 232 | 233 | // Game ending logic 234 | if ((ball.position.y + ball.radius) >= screenHeight) 235 | { 236 | ball.position.x = player.position.x + player.size.x/2; 237 | ball.position.y = player.position.y - ball.radius - 1.0f; 238 | ball.speed = (Vector2){ 0, 0 }; 239 | ball.active = false; 240 | 241 | player.lifes--; 242 | } 243 | 244 | if (player.lifes < 0) 245 | { 246 | screen = ENDING; 247 | player.lifes = 5; 248 | framesCounter = 0; 249 | } 250 | } 251 | else 252 | { 253 | // Reset ball position 254 | ball.position.x = player.position.x + player.size.x/2; 255 | 256 | // LESSON 03: Inputs management (keyboard, mouse) 257 | if (IsKeyPressed(KEY_SPACE)) 258 | { 259 | // Activate ball logic 260 | ball.active = true; 261 | ball.speed = (Vector2){ 0, -5.0f }; 262 | } 263 | } 264 | } 265 | 266 | } break; 267 | case ENDING: 268 | { 269 | // Update END screen data here! 270 | 271 | framesCounter++; 272 | 273 | // LESSON 03: Inputs management (keyboard, mouse) 274 | if (IsKeyPressed(KEY_ENTER)) 275 | { 276 | // Replay / Exit game logic 277 | screen = TITLE; 278 | } 279 | 280 | } break; 281 | default: break; 282 | } 283 | 284 | // LESSON 07: Sounds and music loading and playing 285 | // NOTE: Music buffers must be refilled if consumed 286 | UpdateMusicStream(music); 287 | //---------------------------------------------------------------------------------- 288 | 289 | // Draw 290 | //---------------------------------------------------------------------------------- 291 | BeginDrawing(); 292 | 293 | ClearBackground(RAYWHITE); 294 | 295 | switch(screen) 296 | { 297 | case LOGO: 298 | { 299 | // Draw LOGO screen here! 300 | 301 | // LESSON 05: Textures loading and drawing 302 | DrawTexture(texLogo, screenWidth/2 - texLogo.width/2, screenHeight/2 - texLogo.height/2, WHITE); 303 | 304 | } break; 305 | case TITLE: 306 | { 307 | // Draw TITLE screen here! 308 | 309 | // LESSON 06: Fonts loading and text drawing 310 | DrawTextEx(font, "BLOCKS", (Vector2){ 100, 80 }, 160, 10, MAROON); // Draw Title 311 | 312 | if ((framesCounter/30)%2 == 0) DrawText("PRESS [ENTER] to START", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] to START", 20)/2, GetScreenHeight()/2 + 60, 20, DARKGRAY); 313 | 314 | } break; 315 | case GAMEPLAY: 316 | { 317 | // Draw GAMEPLAY screen here! 318 | 319 | #define LESSON05_TEXTURES // Alternative: LESSON02_SHAPES 320 | #if defined(LESSON02_SHAPES) 321 | // LESSON 02: Draw basic shapes (circle, rectangle) 322 | DrawRectangle(player.position.x, player.position.y, player.size.x, player.size.y, BLACK); // Draw player bar 323 | DrawCircleV(ball.position, ball.radius, MAROON); // Draw ball 324 | 325 | // Draw bricks 326 | for (int j = 0; j < BRICKS_LINES; j++) 327 | { 328 | for (int i = 0; i < BRICKS_PER_LINE; i++) 329 | { 330 | if (bricks[j][i].active) 331 | { 332 | if ((i + j)%2 == 0) DrawRectangle(bricks[j][i].position.x, bricks[j][i].position.y, bricks[j][i].size.x, bricks[j][i].size.y, GRAY); 333 | else DrawRectangle(bricks[j][i].position.x, bricks[j][i].position.y, bricks[j][i].size.x, bricks[j][i].size.y, DARKGRAY); 334 | } 335 | } 336 | } 337 | #elif defined(LESSON05_TEXTURES) 338 | // LESSON 05: Textures loading and drawing 339 | DrawTextureEx(texPaddle, player.position, 0.0f, 1.0f, WHITE); // Draw player 340 | 341 | DrawTexture(texBall, ball.position.x - ball.radius/2, ball.position.y - ball.radius/2, MAROON); // Draw ball 342 | 343 | // Draw bricks 344 | for (int j = 0; j < BRICKS_LINES; j++) 345 | { 346 | for (int i = 0; i < BRICKS_PER_LINE; i++) 347 | { 348 | if (bricks[j][i].active) 349 | { 350 | // NOTE: Texture is not scaled, just using original size 351 | 352 | if ((i + j)%2 == 0) DrawTextureEx(texBrick, bricks[j][i].position, 0.0f, 1.0f, GRAY); 353 | else DrawTextureEx(texBrick, bricks[j][i].position, 0.0f, 1.0f, DARKGRAY); 354 | } 355 | } 356 | } 357 | #endif 358 | 359 | // Draw GUI: player lives 360 | for (int i = 0; i < player.lifes; i++) DrawRectangle(20 + 40*i, screenHeight - 30, 35, 10, LIGHTGRAY); 361 | 362 | // Draw pause message when required 363 | if (gamePaused) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 + 60, 40, GRAY); 364 | 365 | } break; 366 | case ENDING: 367 | { 368 | // Draw END screen here! 369 | 370 | // LESSON 06: Fonts loading and text drawing 371 | // Draw ending message 372 | DrawTextEx(font, "GAME FINISHED", (Vector2){ 80, 100 }, 80, 6, MAROON); 373 | 374 | if ((framesCounter/30)%2 == 0) DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 + 80, 20, GRAY); 375 | 376 | } break; 377 | default: break; 378 | } 379 | 380 | EndDrawing(); 381 | //---------------------------------------------------------------------------------- 382 | } 383 | 384 | // De-Initialization 385 | //-------------------------------------------------------------------------------------- 386 | 387 | // NOTE: Unload any loaded resources (texture, fonts, audio) 388 | 389 | // LESSON 05: Textures loading and drawing 390 | UnloadTexture(texBall); 391 | UnloadTexture(texPaddle); 392 | UnloadTexture(texBrick); 393 | 394 | // LESSON 06: Fonts loading and text drawing 395 | UnloadFont(font); 396 | 397 | // LESSON 07: Sounds and music loading and playing 398 | UnloadSound(fxStart); 399 | UnloadSound(fxBounce); 400 | UnloadSound(fxExplode); 401 | 402 | UnloadMusicStream(music); // Unload music streaming buffers 403 | 404 | CloseAudioDevice(); // Close audio device connection 405 | 406 | CloseWindow(); // Close window and OpenGL context 407 | //-------------------------------------------------------------------------------------- 408 | 409 | return 0; 410 | } 411 | -------------------------------------------------------------------------------- /lessons/Makefile: -------------------------------------------------------------------------------- 1 | #************************************************************************************************** 2 | # 3 | # raylib makefile for Desktop platforms, Raspberry Pi and Web Assembly 4 | # 5 | # Copyright (c) 2021-2025 Ramon Santamaria (@raysan5) 6 | # 7 | # This software is provided "as-is", without any express or implied warranty. In no event 8 | # will the authors be held liable for any damages arising from the use of this software. 9 | # 10 | # Permission is granted to anyone to use this software for any purpose, including commercial 11 | # applications, and to alter it and redistribute it freely, subject to the following restrictions: 12 | # 13 | # 1. The origin of this software must not be misrepresented; you must not claim that you 14 | # wrote the original software. If you use this software in a product, an acknowledgment 15 | # in the product documentation would be appreciated but is not required. 16 | # 17 | # 2. Altered source versions must be plainly marked as such, and must not be misrepresented 18 | # as being the original software. 19 | # 20 | # 3. This notice may not be removed or altered from any source distribution. 21 | # 22 | #************************************************************************************************** 23 | 24 | .PHONY: all clean 25 | 26 | # Define required environment variables 27 | #------------------------------------------------------------------------------------------------ 28 | # Define target platform: PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_WEB 29 | PLATFORM ?= PLATFORM_DESKTOP 30 | 31 | # Define project variables 32 | PROJECT_NAME ?= project_name 33 | PROJECT_VERSION ?= 1.0 34 | PROJECT_BUILD_PATH ?= . 35 | 36 | RAYLIB_PATH ?= C:/GitHub/raylib 37 | RAYLIB_INCLUDE_PATH ?= $(RAYLIB_PATH)/src 38 | RAYLIB_LIB_PATH ?= $(RAYLIB_PATH)/src 39 | 40 | # Build mode for project: DEBUG or RELEASE 41 | BUILD_MODE ?= RELEASE 42 | 43 | # PLATFORM_WEB: Default properties 44 | BUILD_WEB_ASYNCIFY ?= TRUE 45 | BUILD_WEB_SHELL ?= $(RAYLIB_PATH)/src/shell.html 46 | BUILD_WEB_HEAP_SIZE ?= 134217728 47 | BUILD_WEB_RESOURCES ?= FALSE 48 | BUILD_WEB_RESOURCES_PATH ?= resources 49 | 50 | # Determine PLATFORM_OS in case PLATFORM_DESKTOP selected 51 | ifeq ($(PLATFORM),PLATFORM_DESKTOP) 52 | # No uname.exe on MinGW!, but OS=Windows_NT on Windows! 53 | # ifeq ($(UNAME),Msys) -> Windows 54 | ifeq ($(OS),Windows_NT) 55 | PLATFORM_OS = WINDOWS 56 | else 57 | UNAMEOS = $(shell uname) 58 | ifeq ($(UNAMEOS),Linux) 59 | PLATFORM_OS = LINUX 60 | endif 61 | ifeq ($(UNAMEOS),FreeBSD) 62 | PLATFORM_OS = BSD 63 | endif 64 | ifeq ($(UNAMEOS),OpenBSD) 65 | PLATFORM_OS = BSD 66 | endif 67 | ifeq ($(UNAMEOS),NetBSD) 68 | PLATFORM_OS = BSD 69 | endif 70 | ifeq ($(UNAMEOS),DragonFly) 71 | PLATFORM_OS = BSD 72 | endif 73 | ifeq ($(UNAMEOS),Darwin) 74 | PLATFORM_OS = OSX 75 | endif 76 | endif 77 | endif 78 | ifeq ($(PLATFORM),PLATFORM_RPI) 79 | UNAMEOS = $(shell uname) 80 | ifeq ($(UNAMEOS),Linux) 81 | PLATFORM_OS = LINUX 82 | endif 83 | endif 84 | ifeq ($(PLATFORM),PLATFORM_DRM) 85 | UNAMEOS = $(shell uname) 86 | ifeq ($(UNAMEOS),Linux) 87 | PLATFORM_OS = LINUX 88 | endif 89 | endif 90 | 91 | ifeq ($(PLATFORM),PLATFORM_WEB) 92 | # Emscripten required variables 93 | EMSDK_PATH ?= C:/raylib/emsdk 94 | EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten 95 | CLANG_PATH = $(EMSDK_PATH)/upstream/bin 96 | PYTHON_PATH = $(EMSDK_PATH)/python/3.9.2-nuget_64bit 97 | NODE_PATH = $(EMSDK_PATH)/node/20.18.0_64bit/bin 98 | export PATH = $(EMSDK_PATH);$(EMSCRIPTEN_PATH);$(CLANG_PATH);$(NODE_PATH);$(PYTHON_PATH):$$(PATH) 99 | endif 100 | 101 | # Define default C compiler: CC 102 | #------------------------------------------------------------------------------------------------ 103 | CC = gcc 104 | 105 | ifeq ($(PLATFORM),PLATFORM_DESKTOP) 106 | ifeq ($(PLATFORM_OS),OSX) 107 | # OSX default compiler 108 | CC = clang 109 | endif 110 | ifeq ($(PLATFORM_OS),BSD) 111 | # FreeBSD, OpenBSD, NetBSD, DragonFly default compiler 112 | CC = clang 113 | endif 114 | endif 115 | ifeq ($(PLATFORM),PLATFORM_RPI) 116 | ifeq ($(USE_RPI_CROSS_COMPILER),TRUE) 117 | # Define RPI cross-compiler 118 | #CC = armv6j-hardfloat-linux-gnueabi-gcc 119 | CC = $(RPI_TOOLCHAIN)/bin/arm-linux-gnueabihf-gcc 120 | endif 121 | endif 122 | ifeq ($(PLATFORM),PLATFORM_WEB) 123 | # HTML5 emscripten compiler 124 | # WARNING: To compile to HTML5, code must be redesigned 125 | # to use emscripten.h and emscripten_set_main_loop() 126 | CC = emcc 127 | endif 128 | 129 | # Define default make program: MAKE 130 | #------------------------------------------------------------------------------------------------ 131 | MAKE ?= make 132 | 133 | ifeq ($(PLATFORM),PLATFORM_DESKTOP) 134 | ifeq ($(PLATFORM_OS),WINDOWS) 135 | MAKE = mingw32-make 136 | endif 137 | endif 138 | 139 | # Define compiler flags: CFLAGS 140 | #------------------------------------------------------------------------------------------------ 141 | # -O1 defines optimization level 142 | # -g include debug information on compilation 143 | # -s strip unnecessary data from build 144 | # -Wall turns on most, but not all, compiler warnings 145 | # -std=c99 defines C language mode (standard C from 1999 revision) 146 | # -std=gnu99 defines C language mode (GNU C from 1999 revision) 147 | # -Wno-missing-braces ignore invalid warning (GCC bug 53119) 148 | # -Wno-unused-value ignore unused return values of some functions (i.e. fread()) 149 | # -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec 150 | CFLAGS = -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces -Wno-unused-value $(PROJECT_CUSTOM_FLAGS) 151 | #CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes 152 | 153 | ifeq ($(BUILD_MODE),DEBUG) 154 | CFLAGS += -g -D_DEBUG 155 | else 156 | ifeq ($(PLATFORM),PLATFORM_WEB) 157 | ifeq ($(BUILD_WEB_ASYNCIFY),TRUE) 158 | CFLAGS += -O3 159 | else 160 | CFLAGS += -Os 161 | endif 162 | else 163 | CFLAGS += -s -O2 164 | endif 165 | endif 166 | ifeq ($(PLATFORM),PLATFORM_RPI) 167 | CFLAGS += -std=gnu99 168 | endif 169 | ifeq ($(PLATFORM),PLATFORM_DRM) 170 | CFLAGS += -std=gnu99 -DEGL_NO_X11 171 | endif 172 | 173 | # Define include paths for required headers: INCLUDE_PATHS 174 | #------------------------------------------------------------------------------------------------ 175 | # NOTE: Several external required libraries (stb and others) 176 | INCLUDE_PATHS += -I. -Iexternal -I$(RAYLIB_INCLUDE_PATH) 177 | 178 | # Define additional directories containing required header files 179 | ifeq ($(PLATFORM),PLATFORM_RPI) 180 | # RPI required libraries 181 | INCLUDE_PATHS += -I/opt/vc/include 182 | INCLUDE_PATHS += -I/opt/vc/include/interface/vmcs_host/linux 183 | INCLUDE_PATHS += -I/opt/vc/include/interface/vcos/pthreads 184 | endif 185 | ifeq ($(PLATFORM),PLATFORM_DRM) 186 | # DRM required libraries 187 | INCLUDE_PATHS += -I/usr/include/libdrm 188 | endif 189 | ifeq ($(PLATFORM),PLATFORM_DESKTOP) 190 | ifeq ($(PLATFORM_OS),BSD) 191 | # Consider -L$(RAYLIB_H_INSTALL_PATH) 192 | INCLUDE_PATHS += -I/usr/local/include 193 | endif 194 | endif 195 | 196 | # Define library paths containing required libs: LDFLAGS 197 | #------------------------------------------------------------------------------------------------ 198 | LDFLAGS = -L. -L$(RAYLIB_LIB_PATH) 199 | 200 | ifeq ($(PLATFORM),PLATFORM_DESKTOP) 201 | ifeq ($(PLATFORM_OS),WINDOWS) 202 | # resource file contains windows executable icon and properties 203 | LDFLAGS += $(RAYLIB_PATH)/src/raylib.rc.data 204 | # -Wl,--subsystem,windows hides the console window 205 | ifeq ($(BUILD_MODE), RELEASE) 206 | LDFLAGS += -Wl,--subsystem,windows 207 | endif 208 | endif 209 | ifeq ($(PLATFORM_OS),BSD) 210 | # Consider -L$(RAYLIB_INSTALL_PATH) 211 | LDFLAGS += -Lsrc -L/usr/local/lib 212 | endif 213 | ifeq ($(PLATFORM_OS),LINUX) 214 | # Reset everything. 215 | # Precedence: immediately local, installed version, raysan5 provided libs 216 | #LDFLAGS += -L$(RAYLIB_RELEASE_PATH) 217 | endif 218 | endif 219 | ifeq ($(PLATFORM),PLATFORM_WEB) 220 | # -Os # size optimization 221 | # -O2 # optimization level 2, if used, also set --memory-init-file 0 222 | # -sUSE_GLFW=3 # Use glfw3 library (context/input management) 223 | # -sALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! 224 | # -sTOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) (67108864 = 64MB) 225 | # -sUSE_PTHREADS=1 # multithreading support 226 | # -sWASM=0 # disable Web Assembly, emitted by default 227 | # -sASYNCIFY # lets synchronous C/C++ code interact with asynchronous JS 228 | # -sFORCE_FILESYSTEM=1 # force filesystem to load/save files data 229 | # -sASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) 230 | # -sMINIFY_HTML=0 # minify generated html from shell.html 231 | # --profiling # include information for code profiling 232 | # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) 233 | # --preload-file resources # specify a resources folder for data compilation 234 | # --source-map-base # allow debugging in browser with source map 235 | # --shell-file shell.html # define a custom shell .html and output extension 236 | LDFLAGS += -sUSE_GLFW=3 -sTOTAL_MEMORY=$(BUILD_WEB_HEAP_SIZE) -sFORCE_FILESYSTEM=1 -sMINIFY_HTML=0 237 | 238 | # Build using asyncify 239 | ifeq ($(BUILD_WEB_ASYNCIFY),TRUE) 240 | LDFLAGS += -sASYNCIFY 241 | endif 242 | 243 | # Add resources building if required 244 | ifeq ($(BUILD_WEB_RESOURCES),TRUE) 245 | LDFLAGS += --preload-file $(BUILD_WEB_RESOURCES_PATH) 246 | endif 247 | 248 | # Add debug mode flags if required 249 | ifeq ($(BUILD_MODE),DEBUG) 250 | LDFLAGS += -sASSERTIONS=1 --profiling 251 | endif 252 | 253 | # Define a custom shell .html and output extension 254 | LDFLAGS += --shell-file $(BUILD_WEB_SHELL) 255 | EXT = .html 256 | endif 257 | 258 | ifeq ($(PLATFORM),PLATFORM_RPI) 259 | LDFLAGS += -L/opt/vc/lib 260 | endif 261 | 262 | # Define libraries required on linking: LDLIBS 263 | # NOTE: To link libraries (lib.so or lib.a), use -l 264 | #------------------------------------------------------------------------------------------------ 265 | ifeq ($(PLATFORM),PLATFORM_DESKTOP) 266 | ifeq ($(PLATFORM_OS),WINDOWS) 267 | # Libraries for Windows desktop compilation 268 | # NOTE: WinMM library required to set high-res timer resolution 269 | LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm -lcomdlg32 -lole32 270 | # Required for physac examples 271 | LDLIBS += -static -lpthread 272 | endif 273 | ifeq ($(PLATFORM_OS),LINUX) 274 | # Libraries for Debian GNU/Linux desktop compiling 275 | # NOTE: Required packages: libegl1-mesa-dev 276 | LDLIBS = -lraylib -lGL -lm -lpthread -ldl -lrt 277 | 278 | # On X11 requires also below libraries 279 | LDLIBS += -lX11 280 | # NOTE: It seems additional libraries are not required any more, latest GLFW just dlopen them 281 | #LDLIBS += -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor 282 | 283 | # On Wayland windowing system, additional libraries requires 284 | ifeq ($(USE_WAYLAND_DISPLAY),TRUE) 285 | LDLIBS = -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon 286 | endif 287 | # Explicit link to libc 288 | ifeq ($(RAYLIB_LIBTYPE),SHARED) 289 | LDLIBS += -lc 290 | endif 291 | endif 292 | ifeq ($(PLATFORM_OS),OSX) 293 | # Libraries for OSX 10.9 desktop compiling 294 | # NOTE: Required packages: libopenal-dev libegl1-mesa-dev 295 | LDLIBS = -lraylib -framework OpenGL -framework Cocoa -framework IOKit -framework CoreAudio -framework CoreVideo 296 | endif 297 | ifeq ($(PLATFORM_OS),BSD) 298 | # Libraries for FreeBSD, OpenBSD, NetBSD, DragonFly desktop compiling 299 | # NOTE: Required packages: mesa-libs 300 | LDLIBS = -lraylib -lGL -lpthread -lm 301 | 302 | # On XWindow requires also below libraries 303 | LDLIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor 304 | endif 305 | endif 306 | ifeq ($(PLATFORM),PLATFORM_RPI) 307 | # Libraries for Raspberry Pi compiling 308 | # NOTE: Required packages: libasound2-dev (ALSA) 309 | LDLIBS = -lraylib -lbrcmGLESv2 -lbrcmEGL -lpthread -lrt -lm -lbcm_host -ldl 310 | endif 311 | ifeq ($(PLATFORM),PLATFORM_DRM) 312 | # Libraries for DRM compiling 313 | # NOTE: Required packages: libasound2-dev (ALSA) 314 | LDLIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lgbm -ldrm -ldl 315 | endif 316 | ifeq ($(PLATFORM),PLATFORM_WEB) 317 | # Libraries for web (HTML5) compiling 318 | LDLIBS = $(RAYLIB_LIB_PATH)/libraylib.a 319 | endif 320 | 321 | # Define source code files required 322 | #------------------------------------------------------------------------------------------------ 323 | PROJECT_SOURCE_FILES ?= \ 324 | project_game.c \ 325 | screen_logo.c \ 326 | screen_title.c \ 327 | screen_options.c \ 328 | screen_gameplay.c \ 329 | screen_ending.c 330 | 331 | # Define all object files from source files 332 | OBJS = $(patsubst %.c, %.o, $(PROJECT_SOURCE_FILES)) 333 | 334 | # Define processes to execute 335 | #------------------------------------------------------------------------------------------------ 336 | # Default target entry 337 | # NOTE: We call this Makefile target or Makefile.Android target 338 | all: 339 | $(MAKE) $(PROJECT_NAME) 340 | 341 | # Project target defined by PROJECT_NAME 342 | $(PROJECT_NAME): $(OBJS) 343 | $(CC) -o $(PROJECT_BUILD_PATH)/$(PROJECT_NAME)$(EXT) $(OBJS) $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) 344 | 345 | # Compile source files 346 | # NOTE: This pattern will compile every module defined on $(OBJS) 347 | %.o: %.c 348 | $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM) 349 | 350 | # Clean everything 351 | clean: 352 | ifeq ($(PLATFORM),PLATFORM_DESKTOP) 353 | ifeq ($(PLATFORM_OS),WINDOWS) 354 | del *.o *.exe /s 355 | endif 356 | ifeq ($(PLATFORM_OS),LINUX) 357 | find . -type f -executable -delete 358 | rm -fv *.o 359 | endif 360 | ifeq ($(PLATFORM_OS),OSX) 361 | find . -type f -perm +ugo+x -delete 362 | rm -f *.o 363 | endif 364 | endif 365 | ifeq ($(PLATFORM),PLATFORM_RPI) 366 | find . -type f -executable -delete 367 | rm -fv *.o 368 | endif 369 | ifeq ($(PLATFORM),PLATFORM_DRM) 370 | find . -type f -executable -delete 371 | rm -fv *.o 372 | endif 373 | ifeq ($(PLATFORM),PLATFORM_WEB) 374 | del *.o *.html *.js 375 | endif 376 | @echo Cleaning done 377 | 378 | -------------------------------------------------------------------------------- /lessons/blocks.rc: -------------------------------------------------------------------------------- 1 | GLFW_ICON ICON "raylib.ico" 2 | 3 | 1 VERSIONINFO 4 | FILEVERSION 1,0,0,0 5 | PRODUCTVERSION 1,0,0,0 6 | BEGIN 7 | BLOCK "StringFileInfo" 8 | BEGIN 9 | //BLOCK "080904E4" // English UK 10 | BLOCK "040904E4" // English US 11 | BEGIN 12 | VALUE "CompanyName", "raylib technologies" 13 | VALUE "FileDescription", "Blocks" 14 | VALUE "FileVersion", "1.0" 15 | VALUE "InternalName", "blocks" 16 | VALUE "LegalCopyright", "(c) 2022 raylib technologies (@raylibtech)" 17 | //VALUE "OriginalFilename", "blocks.exe" 18 | VALUE "ProductName", "Blocks" 19 | VALUE "ProductVersion", "1.0" 20 | END 21 | END 22 | BLOCK "VarFileInfo" 23 | BEGIN 24 | //VALUE "Translation", 0x809, 1252 // English UK 25 | VALUE "Translation", 0x409, 1252 // English US 26 | END 27 | END 28 | -------------------------------------------------------------------------------- /lessons/raylib.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raysan5/raylib-intro-course/8a0472b753b783d1b51958003c70b1b4fedf5a51/lessons/raylib.ico -------------------------------------------------------------------------------- /lessons/resources/ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raysan5/raylib-intro-course/8a0472b753b783d1b51958003c70b1b4fedf5a51/lessons/resources/ball.png -------------------------------------------------------------------------------- /lessons/resources/bounce.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raysan5/raylib-intro-course/8a0472b753b783d1b51958003c70b1b4fedf5a51/lessons/resources/bounce.wav -------------------------------------------------------------------------------- /lessons/resources/brick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raysan5/raylib-intro-course/8a0472b753b783d1b51958003c70b1b4fedf5a51/lessons/resources/brick.png -------------------------------------------------------------------------------- /lessons/resources/explosion.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raysan5/raylib-intro-course/8a0472b753b783d1b51958003c70b1b4fedf5a51/lessons/resources/explosion.wav -------------------------------------------------------------------------------- /lessons/resources/paddle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raysan5/raylib-intro-course/8a0472b753b783d1b51958003c70b1b4fedf5a51/lessons/resources/paddle.png -------------------------------------------------------------------------------- /lessons/resources/raylib_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raysan5/raylib-intro-course/8a0472b753b783d1b51958003c70b1b4fedf5a51/lessons/resources/raylib_logo.png -------------------------------------------------------------------------------- /lessons/resources/setback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raysan5/raylib-intro-course/8a0472b753b783d1b51958003c70b1b4fedf5a51/lessons/resources/setback.png -------------------------------------------------------------------------------- /lessons/resources/start.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raysan5/raylib-intro-course/8a0472b753b783d1b51958003c70b1b4fedf5a51/lessons/resources/start.wav -------------------------------------------------------------------------------- /pong/pong.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * 3 | * raylib pong 4 | * 5 | * COMPILATION (Windows - MinGW): 6 | * gcc -o $(NAME_PART).exe $(FILE_NAME) -lraylib -lopengl32 -lgdi32 -lwinmm -Wall -std=c99 7 | * 8 | * COMPILATION (Linux - GCC): 9 | * gcc -o $(NAME_PART).exe $(FILE_NAME) -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 10 | * 11 | * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 12 | * BSD-like license that allows static linking with closed source software 13 | * 14 | * Copyright (c) 2022 Ramon Santamaria (@raysan5) 15 | * 16 | ********************************************************************************************/ 17 | 18 | #include "raylib.h" 19 | 20 | typedef enum { SCREEN_LOGO = 0, SCREEN_TITLE, SCREEN_GAMEPLAY, SCREEN_ENDING } GameScreen; 21 | 22 | //------------------------------------------------------------------------------------ 23 | // Program main entry point 24 | //------------------------------------------------------------------------------------ 25 | int main(void) 26 | { 27 | // Initialization 28 | //-------------------------------------------------------------------------------------- 29 | const int screenWidth = 800; 30 | const int screenHeight = 600; 31 | 32 | //SetConfigFlags(FLAG_WINDOW_RESIZABLE | FLAG_WINDOW_UNDECORATED); 33 | InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window"); 34 | 35 | InitAudioDevice(); 36 | 37 | // Ball 38 | Vector2 ballPosition = { screenWidth/2, screenHeight/2 }; 39 | float ballRadius = 20.0f; 40 | int ballSpeedX = 6; 41 | int ballSpeedY = -4; 42 | 43 | // Player 44 | Rectangle player = { 10, screenHeight/2 - 50, 25, 100 }; 45 | float playerSpeed = 8.0f; 46 | int playerScore = 0; 47 | 48 | // Enemy 49 | Rectangle enemy = { screenWidth - 10 - 25, screenHeight/2 - 50, 25, 100 }; 50 | float enemySpeed = 3.0f; 51 | int enemyVisionRange = screenWidth/2; 52 | int enemyScore = 0; 53 | 54 | // Resources loading 55 | Texture2D texLogo = LoadTexture("resources/logo_raylib.png"); 56 | float alphaLogo = 0.0f; 57 | int logoState = 0; // 0-FadeIn, 1-Wait, 2-FadeOut 58 | 59 | //Image imLogo = LoadImage("resources/logo_raylib.png"); 60 | //Texture2D texLogo = LoadTextureFromImage(imLogo); 61 | //UnloadImage(imLogo); 62 | 63 | //Font fntTitle = LoadFont("resources/pixantiqua.ttf"); // Font size: 32px default 64 | Font fntTitle = LoadFontEx("resources/pixantiqua.ttf", 12, 0, 0); // Font size: pixel-perfect 65 | SetTextureFilter(fntTitle.texture, TEXTURE_FILTER_POINT); 66 | 67 | Sound fxStart = LoadSound("resources/start.wav"); 68 | Sound fxPong = LoadSound("resources/pong.wav"); 69 | 70 | Music ambient = LoadMusicStream("resources/qt-plimp.xm"); 71 | PlayMusicStream(ambient); 72 | 73 | // General variables 74 | bool pause = false; 75 | bool finishGame = false; 76 | int framesCounter = 0; 77 | GameScreen currentScreen = SCREEN_LOGO; // 0-LOGO, 1-TITLE, 2-GAMEPLAY, 3-ENDING 78 | 79 | SetTargetFPS(60); // Set our game to run at 60 frames-per-second 80 | //-------------------------------------------------------------------------------------- 81 | 82 | // Main game loop 83 | while (!WindowShouldClose() && !finishGame) // Detect window close button or ESC key 84 | { 85 | // Update 86 | //---------------------------------------------------------------------------------- 87 | UpdateMusicStream(ambient); 88 | 89 | switch (currentScreen) 90 | { 91 | case SCREEN_LOGO: 92 | { 93 | if (logoState == 0) 94 | { 95 | alphaLogo += (1.0f/180); 96 | if (alphaLogo > 1.0f) 97 | { 98 | alphaLogo = 1.0f; 99 | logoState = 1; 100 | } 101 | } 102 | else if (logoState == 1) 103 | { 104 | framesCounter++; 105 | if (framesCounter >= 200) 106 | { 107 | framesCounter = 0; 108 | logoState = 2; 109 | } 110 | } 111 | else if (logoState == 2) 112 | { 113 | alphaLogo -= (1.0f/180); 114 | if (alphaLogo < 0.0f) 115 | { 116 | alphaLogo = 0.0f; 117 | currentScreen = 1; 118 | } 119 | } 120 | 121 | } break; 122 | case SCREEN_TITLE: 123 | { 124 | framesCounter++; 125 | 126 | // Update TITLE screen 127 | if (IsKeyPressed(KEY_ENTER)) 128 | { 129 | PlaySound(fxStart); 130 | currentScreen = 2; 131 | } 132 | } break; 133 | case SCREEN_GAMEPLAY: 134 | { 135 | // Update GAMEPLAY screen 136 | if (!pause) 137 | { 138 | // Ball movement logic 139 | ballPosition.x += ballSpeedX; 140 | ballPosition.y += ballSpeedY; 141 | 142 | if (((ballPosition.x + ballRadius) > screenWidth) || ((ballPosition.x - ballRadius) < 0)) 143 | { 144 | PlaySound(fxPong); 145 | ballSpeedX *= -1; 146 | } 147 | 148 | if (((ballPosition.y + ballRadius) > screenHeight) || ((ballPosition.y - ballRadius) < 0)) 149 | { 150 | PlaySound(fxPong); 151 | ballSpeedY *= -1; 152 | } 153 | 154 | if ((ballPosition.x - ballRadius) <= 0) enemyScore += 1000; 155 | else if ((ballPosition.x + ballRadius) > GetScreenWidth()) playerScore += 1000; 156 | 157 | // Player movement logic 158 | if (IsKeyDown(KEY_UP)) player.y -= playerSpeed; 159 | else if (IsKeyDown(KEY_DOWN)) player.y += playerSpeed; 160 | 161 | if (player.y <= 0) player.y = 0; 162 | else if ((player.y + player.height) >= screenHeight) player.y = screenHeight - player.height; 163 | 164 | if (CheckCollisionCircleRec(ballPosition, ballRadius, player)) 165 | { 166 | PlaySound(fxPong); 167 | ballSpeedX *= -1; 168 | } 169 | 170 | // Enemy movement logic 171 | if (ballPosition.x > enemyVisionRange) 172 | { 173 | if (ballPosition.y > (enemy.y + enemy.height/2)) enemy.y += enemySpeed; 174 | else if (ballPosition.y < (enemy.y + enemy.height/2)) enemy.y -= enemySpeed; 175 | } 176 | 177 | if (CheckCollisionCircleRec(ballPosition, ballRadius, enemy)) 178 | { 179 | PlaySound(fxPong); 180 | ballSpeedX *= -1; 181 | } 182 | 183 | if (IsKeyDown(KEY_RIGHT)) enemyVisionRange++; 184 | else if (IsKeyDown(KEY_LEFT)) enemyVisionRange--; 185 | } 186 | 187 | if (IsKeyPressed(KEY_P)) pause = !pause; 188 | 189 | if (IsKeyPressed(KEY_ENTER)) currentScreen = 3; 190 | } break; 191 | case SCREEN_ENDING: 192 | { 193 | // Update ENDING screen 194 | if (IsKeyPressed(KEY_ENTER)) 195 | { 196 | //currentScreen = 1; 197 | finishGame = true; 198 | } 199 | } break; 200 | default: break; 201 | } 202 | //---------------------------------------------------------------------------------- 203 | 204 | // Draw 205 | //---------------------------------------------------------------------------------- 206 | BeginDrawing(); 207 | 208 | ClearBackground(RAYWHITE); 209 | 210 | switch (currentScreen) 211 | { 212 | case SCREEN_LOGO: 213 | { 214 | // Draw LOGO screen 215 | //DrawRectangle(0, 0, screenWidth, screenHeight, BLUE); 216 | //DrawText("SCREEN LOGO", 10, 10, 30, DARKBLUE); 217 | 218 | DrawTexture(texLogo, GetScreenWidth()/2 - texLogo.width/2, GetScreenHeight()/2 - texLogo.height/2 - 40, Fade(WHITE, alphaLogo)); 219 | } break; 220 | case SCREEN_TITLE: 221 | { 222 | // Draw TITLE screen 223 | //DrawRectangle(0, 0, screenWidth, screenHeight, GREEN); 224 | //DrawText("SCREEN TITLE", 10, 10, 30, DARKGREEN); 225 | 226 | DrawTextEx(fntTitle, "SUPER PONG", (Vector2){ 200, 100 }, fntTitle.baseSize*6, 4, LIME); 227 | 228 | if ((framesCounter/30)%2) DrawText("PRESS ENTER to START", 200, 300, 30, BLACK); 229 | 230 | } break; 231 | case SCREEN_GAMEPLAY: 232 | { 233 | DrawCircleV(ballPosition, ballRadius, RED); 234 | 235 | DrawRectangleRec(player, BLUE); 236 | 237 | DrawRectangleRec(enemy, DARKGREEN); 238 | 239 | DrawLine(enemyVisionRange, 0, enemyVisionRange, screenHeight, GRAY); 240 | 241 | // Draw hud 242 | DrawText(TextFormat("%04i", playerScore), 100, 10, 30, BLUE); 243 | DrawText(TextFormat("%04i", enemyScore), screenWidth - 200, 10, 30, DARKGREEN); 244 | 245 | if (pause) 246 | { 247 | DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(WHITE, 0.8f)); 248 | DrawText("GAME PAUSED", 320, 200, 30, RED); 249 | } 250 | } break; 251 | case SCREEN_ENDING: 252 | { 253 | // Draw ENDING screen 254 | DrawRectangle(0, 0, screenWidth, screenHeight, RED); 255 | DrawText("SCREEN ENDING", 10, 10, 30, MAROON); 256 | } break; 257 | default: break; 258 | } 259 | 260 | EndDrawing(); 261 | //---------------------------------------------------------------------------------- 262 | } 263 | 264 | // De-Initialization 265 | //-------------------------------------------------------------------------------------- 266 | UnloadTexture(texLogo); 267 | UnloadFont(fntTitle); 268 | 269 | UnloadSound(fxStart); 270 | UnloadSound(fxPong); 271 | UnloadMusicStream(ambient); 272 | 273 | CloseAudioDevice(); 274 | 275 | CloseWindow(); // Close window and OpenGL context 276 | //-------------------------------------------------------------------------------------- 277 | 278 | return 0; 279 | } -------------------------------------------------------------------------------- /pong/pong_web.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * 3 | * raylib pong web 4 | * 5 | * COMPILATION (Web - emscripten): 6 | * emcc -o pong_web.html pong_web.c -s USE_GLFW=3 -s TOTAL_MEMORY=67108864 --preload-file resources 7 | * -I../../raylib/src -L../../raylib/src -lraylib -DPLATFORM_WEB 8 | * 9 | * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 10 | * BSD-like license that allows static linking with closed source software 11 | * 12 | * Copyright (c) 2022 Ramon Santamaria (@raysan5) 13 | * 14 | ********************************************************************************************/ 15 | 16 | #include "raylib.h" 17 | 18 | #if defined(PLATFORM_WEB) 19 | #include 20 | #endif 21 | 22 | typedef enum { SCREEN_LOGO = 0, SCREEN_TITLE, SCREEN_GAMEPLAY, SCREEN_ENDING } GameScreen; 23 | 24 | static void UpdateDrawFrame(void); 25 | 26 | // Global variables 27 | static const int screenWidth = 800; 28 | static const int screenHeight = 600; 29 | 30 | static bool pause = false; 31 | static bool finishGame = false; 32 | static int framesCounter = 0; 33 | static GameScreen currentScreen = SCREEN_LOGO; // 0-LOGO, 1-TITLE, 2-GAMEPLAY, 3-ENDING 34 | 35 | // Ball 36 | static Vector2 ballPosition = { screenWidth/2, screenHeight/2 }; 37 | static float ballRadius = 20.0f; 38 | static int ballSpeedX = 6; 39 | static int ballSpeedY = -4; 40 | 41 | // Player 42 | static Rectangle player = { 10, screenHeight/2 - 50, 25, 100 }; 43 | static float playerSpeed = 8.0f; 44 | static int playerScore = 0; 45 | 46 | // Enemy 47 | static Rectangle enemy = { screenWidth - 10 - 25, screenHeight/2 - 50, 25, 100 }; 48 | static float enemySpeed = 3.0f; 49 | static int enemyVisionRange = screenWidth/2; 50 | static int enemyScore = 0; 51 | 52 | static float alphaLogo = 0.0f; 53 | static int logoState = 0; // 0-FadeIn, 1-Wait, 2-FadeOut 54 | 55 | // Resources 56 | static Texture2D texLogo = { 0 }; 57 | static Font fntTitle = { 0 }; 58 | static Sound fxStart = { 0 }; 59 | static Sound fxPong = { 0 }; 60 | static Music ambient = { 0 }; 61 | 62 | //------------------------------------------------------------------------------------ 63 | // Program main entry point 64 | //------------------------------------------------------------------------------------ 65 | int main(void) 66 | { 67 | // Initialization 68 | //-------------------------------------------------------------------------------------- 69 | //SetConfigFlags(FLAG_WINDOW_RESIZABLE | FLAG_WINDOW_UNDECORATED); 70 | InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window"); 71 | 72 | InitAudioDevice(); 73 | 74 | // Resources loading 75 | texLogo = LoadTexture("resources/logo_raylib.png"); 76 | 77 | //Image imLogo = LoadImage("resources/logo_raylib.png"); 78 | //Texture2D texLogo = LoadTextureFromImage(imLogo); 79 | //UnloadImage(imLogo); 80 | 81 | fntTitle = LoadFont("resources/pixantiqua.ttf"); 82 | SetTextureFilter(fntTitle.texture, TEXTURE_FILTER_POINT); 83 | 84 | fxStart = LoadSound("resources/start.wav"); 85 | fxPong = LoadSound("resources/pong.wav"); 86 | 87 | ambient = LoadMusicStream("resources/qt-plimp.xm"); 88 | PlayMusicStream(ambient); 89 | 90 | #if defined(PLATFORM_WEB) 91 | emscripten_set_main_loop(UpdateDrawFrame, 0, 1); 92 | #else 93 | SetTargetFPS(60); // Set our game to run at 60 frames-per-second 94 | //-------------------------------------------------------------------------------------- 95 | 96 | // Main game loop 97 | while (!WindowShouldClose()) // Detect window close button or ESC key 98 | { 99 | UpdateDrawFrame(); 100 | } 101 | #endif 102 | 103 | // De-Initialization 104 | //-------------------------------------------------------------------------------------- 105 | UnloadTexture(texLogo); 106 | UnloadFont(fntTitle); 107 | 108 | UnloadSound(fxStart); 109 | UnloadSound(fxPong); 110 | UnloadMusicStream(ambient); 111 | 112 | CloseAudioDevice(); 113 | 114 | CloseWindow(); // Close window and OpenGL context 115 | //-------------------------------------------------------------------------------------- 116 | 117 | return 0; 118 | } 119 | 120 | static void UpdateDrawFrame(void) 121 | { 122 | // Update 123 | //---------------------------------------------------------------------------------- 124 | UpdateMusicStream(ambient); 125 | 126 | switch (currentScreen) 127 | { 128 | case SCREEN_LOGO: 129 | { 130 | if (logoState == 0) 131 | { 132 | alphaLogo += (1.0f/180); 133 | if (alphaLogo > 1.0f) 134 | { 135 | alphaLogo = 1.0f; 136 | logoState = 1; 137 | } 138 | } 139 | else if (logoState == 1) 140 | { 141 | framesCounter++; 142 | if (framesCounter >= 200) 143 | { 144 | framesCounter = 0; 145 | logoState = 2; 146 | } 147 | } 148 | else if (logoState == 2) 149 | { 150 | alphaLogo -= (1.0f/180); 151 | if (alphaLogo < 0.0f) 152 | { 153 | alphaLogo = 0.0f; 154 | currentScreen = 1; 155 | } 156 | } 157 | 158 | } break; 159 | case SCREEN_TITLE: 160 | { 161 | framesCounter++; 162 | 163 | // Update TITLE screen 164 | if (IsKeyPressed(KEY_ENTER)) 165 | { 166 | PlaySound(fxStart); 167 | currentScreen = 2; 168 | } 169 | } break; 170 | case SCREEN_GAMEPLAY: 171 | { 172 | // Update GAMEPLAY screen 173 | if (!pause) 174 | { 175 | // Ball movement logic 176 | ballPosition.x += ballSpeedX; 177 | ballPosition.y += ballSpeedY; 178 | 179 | if (((ballPosition.x + ballRadius) > screenWidth) || ((ballPosition.x - ballRadius) < 0)) 180 | { 181 | PlaySound(fxPong); 182 | ballSpeedX *= -1; 183 | } 184 | 185 | if (((ballPosition.y + ballRadius) > screenHeight) || ((ballPosition.y - ballRadius) < 0)) 186 | { 187 | PlaySound(fxPong); 188 | ballSpeedY *= -1; 189 | } 190 | 191 | if ((ballPosition.x - ballRadius) <= 0) enemyScore += 1000; 192 | else if ((ballPosition.x + ballRadius) > GetScreenWidth()) playerScore += 1000; 193 | 194 | // Player movement logic 195 | if (IsKeyDown(KEY_UP)) player.y -= 8; 196 | else if (IsKeyDown(KEY_DOWN)) player.y += 8; 197 | 198 | if (player.y <= 0) player.y = 0; 199 | else if ((player.y + player.height) >= screenHeight) player.y = screenHeight - player.height; 200 | 201 | if (CheckCollisionCircleRec(ballPosition, ballRadius, player)) 202 | { 203 | PlaySound(fxPong); 204 | ballSpeedX *= -1; 205 | } 206 | 207 | // Enemy movement logic 208 | if (ballPosition.x > enemyVisionRange) 209 | { 210 | if (ballPosition.y > (enemy.y + enemy.height/2)) enemy.y += enemySpeed; 211 | else if (ballPosition.y < (enemy.y + enemy.height/2)) enemy.y -= enemySpeed; 212 | } 213 | 214 | if (CheckCollisionCircleRec(ballPosition, ballRadius, enemy)) 215 | { 216 | PlaySound(fxPong); 217 | ballSpeedX *= -1; 218 | } 219 | 220 | if (IsKeyDown(KEY_RIGHT)) enemyVisionRange++; 221 | else if (IsKeyDown(KEY_LEFT)) enemyVisionRange--; 222 | } 223 | 224 | if (IsKeyPressed(KEY_P)) pause = !pause; 225 | 226 | if (IsKeyPressed(KEY_ENTER)) currentScreen = 3; 227 | } break; 228 | case SCREEN_ENDING: 229 | { 230 | // Update ENDING screen 231 | if (IsKeyPressed(KEY_ENTER)) 232 | { 233 | //currentScreen = 1; 234 | finishGame = true; 235 | } 236 | } break; 237 | default: break; 238 | } 239 | //---------------------------------------------------------------------------------- 240 | 241 | // Draw 242 | //---------------------------------------------------------------------------------- 243 | BeginDrawing(); 244 | 245 | ClearBackground(RAYWHITE); 246 | 247 | switch (currentScreen) 248 | { 249 | case SCREEN_LOGO: 250 | { 251 | // Draw LOGO screen 252 | //DrawRectangle(0, 0, screenWidth, screenHeight, BLUE); 253 | //DrawText("SCREEN LOGO", 10, 10, 30, DARKBLUE); 254 | 255 | DrawTexture(texLogo, GetScreenWidth()/2 - texLogo.width/2, GetScreenHeight()/2 - texLogo.height/2 - 40, Fade(WHITE, alphaLogo)); 256 | } break; 257 | case SCREEN_TITLE: 258 | { 259 | // Draw TITLE screen 260 | //DrawRectangle(0, 0, screenWidth, screenHeight, GREEN); 261 | //DrawText("SCREEN TITLE", 10, 10, 30, DARKGREEN); 262 | 263 | DrawTextEx(fntTitle, "SUPER PONG", (Vector2){ 200, 100 }, fntTitle.baseSize*2, 4, RED); 264 | 265 | if ((framesCounter/30)%2) DrawText("PRESS ENTER to START", 200, 300, 30, BLACK); 266 | 267 | } break; 268 | case SCREEN_GAMEPLAY: 269 | { 270 | DrawCircleV(ballPosition, ballRadius, RED); 271 | 272 | DrawRectangleRec(player, BLUE); 273 | 274 | DrawRectangleRec(enemy, DARKGREEN); 275 | 276 | DrawLine(enemyVisionRange, 0, enemyVisionRange, screenHeight, GRAY); 277 | 278 | // Draw hud 279 | DrawText(TextFormat("%04i", playerScore), 100, 10, 30, BLUE); 280 | DrawText(TextFormat("%04i", enemyScore), screenWidth - 200, 10, 30, DARKGREEN); 281 | 282 | if (pause) 283 | { 284 | DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(WHITE, 0.8f)); 285 | DrawText("GAME PAUSED", 320, 200, 30, RED); 286 | } 287 | } break; 288 | case SCREEN_ENDING: 289 | { 290 | // Draw ENDING screen 291 | DrawRectangle(0, 0, screenWidth, screenHeight, RED); 292 | DrawText("SCREEN ENDING", 10, 10, 30, MAROON); 293 | } break; 294 | default: break; 295 | } 296 | 297 | EndDrawing(); 298 | //---------------------------------------------------------------------------------- 299 | } -------------------------------------------------------------------------------- /pong/resources/logo_raylib.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raysan5/raylib-intro-course/8a0472b753b783d1b51958003c70b1b4fedf5a51/pong/resources/logo_raylib.png -------------------------------------------------------------------------------- /pong/resources/pixantiqua.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raysan5/raylib-intro-course/8a0472b753b783d1b51958003c70b1b4fedf5a51/pong/resources/pixantiqua.ttf -------------------------------------------------------------------------------- /pong/resources/pong.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raysan5/raylib-intro-course/8a0472b753b783d1b51958003c70b1b4fedf5a51/pong/resources/pong.wav -------------------------------------------------------------------------------- /pong/resources/qt-plimp.xm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raysan5/raylib-intro-course/8a0472b753b783d1b51958003c70b1b4fedf5a51/pong/resources/qt-plimp.xm -------------------------------------------------------------------------------- /pong/resources/start.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raysan5/raylib-intro-course/8a0472b753b783d1b51958003c70b1b4fedf5a51/pong/resources/start.wav -------------------------------------------------------------------------------- /projects/VS2022/blocks.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.31912.275 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "raylib", "raylib\raylib.vcxproj", "{E89D61AC-55DE-4482-AFD4-DF7242EBC859}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blocks", "blocks\blocks.vcxproj", "{0981CA98-E4A5-4DF1-987F-A41D09131EFC}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug.DLL|x64 = Debug.DLL|x64 13 | Debug.DLL|x86 = Debug.DLL|x86 14 | Debug|x64 = Debug|x64 15 | Debug|x86 = Debug|x86 16 | Release.DLL|x64 = Release.DLL|x64 17 | Release.DLL|x86 = Release.DLL|x86 18 | Release|x64 = Release|x64 19 | Release|x86 = Release|x86 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 23 | {E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 24 | {E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 25 | {E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 26 | {E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Debug|x64.ActiveCfg = Debug|x64 27 | {E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Debug|x64.Build.0 = Debug|x64 28 | {E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Debug|x86.ActiveCfg = Debug|Win32 29 | {E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Debug|x86.Build.0 = Debug|Win32 30 | {E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 31 | {E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Release.DLL|x64.Build.0 = Release.DLL|x64 32 | {E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 33 | {E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Release.DLL|x86.Build.0 = Release.DLL|Win32 34 | {E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Release|x64.ActiveCfg = Release|x64 35 | {E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Release|x64.Build.0 = Release|x64 36 | {E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Release|x86.ActiveCfg = Release|Win32 37 | {E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Release|x86.Build.0 = Release|Win32 38 | {0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 39 | {0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 40 | {0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 41 | {0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 42 | {0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Debug|x64.ActiveCfg = Debug|x64 43 | {0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Debug|x64.Build.0 = Debug|x64 44 | {0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Debug|x86.ActiveCfg = Debug|Win32 45 | {0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Debug|x86.Build.0 = Debug|Win32 46 | {0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 47 | {0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Release.DLL|x64.Build.0 = Release.DLL|x64 48 | {0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 49 | {0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Release.DLL|x86.Build.0 = Release.DLL|Win32 50 | {0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Release|x64.ActiveCfg = Release|x64 51 | {0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Release|x64.Build.0 = Release|x64 52 | {0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Release|x86.ActiveCfg = Release|Win32 53 | {0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Release|x86.Build.0 = Release|Win32 54 | EndGlobalSection 55 | GlobalSection(SolutionProperties) = preSolution 56 | HideSolutionNode = FALSE 57 | EndGlobalSection 58 | GlobalSection(ExtensibilityGlobals) = postSolution 59 | SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} 60 | EndGlobalSection 61 | EndGlobal 62 | -------------------------------------------------------------------------------- /projects/VS2022/blocks/blocks.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug.DLL 6 | Win32 7 | 8 | 9 | Debug.DLL 10 | x64 11 | 12 | 13 | Debug 14 | Win32 15 | 16 | 17 | Debug 18 | x64 19 | 20 | 21 | Release.DLL 22 | Win32 23 | 24 | 25 | Release.DLL 26 | x64 27 | 28 | 29 | Release 30 | Win32 31 | 32 | 33 | Release 34 | x64 35 | 36 | 37 | 38 | {0981CA98-E4A5-4DF1-987F-A41D09131EFC} 39 | Win32Proj 40 | rfxgen 41 | blocks 42 | 10.0 43 | 44 | 45 | 46 | Application 47 | true 48 | $(DefaultPlatformToolset) 49 | Unicode 50 | 51 | 52 | Application 53 | true 54 | $(DefaultPlatformToolset) 55 | Unicode 56 | 57 | 58 | Application 59 | true 60 | $(DefaultPlatformToolset) 61 | Unicode 62 | 63 | 64 | Application 65 | true 66 | $(DefaultPlatformToolset) 67 | Unicode 68 | 69 | 70 | Application 71 | false 72 | $(DefaultPlatformToolset) 73 | true 74 | Unicode 75 | 76 | 77 | Application 78 | false 79 | $(DefaultPlatformToolset) 80 | true 81 | Unicode 82 | 83 | 84 | Application 85 | false 86 | $(DefaultPlatformToolset) 87 | true 88 | Unicode 89 | 90 | 91 | Application 92 | false 93 | $(DefaultPlatformToolset) 94 | true 95 | Unicode 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | true 129 | $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ 130 | $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ 131 | 132 | 133 | true 134 | $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ 135 | $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ 136 | 137 | 138 | true 139 | $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ 140 | $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ 141 | 142 | 143 | true 144 | $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ 145 | $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ 146 | 147 | 148 | false 149 | $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ 150 | $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ 151 | 152 | 153 | false 154 | $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ 155 | $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ 156 | 157 | 158 | false 159 | $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ 160 | $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ 161 | 162 | 163 | false 164 | $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ 165 | $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ 166 | 167 | 168 | 169 | 170 | 171 | Level3 172 | Disabled 173 | _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) 174 | CompileAsC 175 | $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories) 176 | 177 | 178 | Console 179 | true 180 | $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ 181 | raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 182 | 183 | 184 | 185 | 186 | 187 | 188 | Level3 189 | Disabled 190 | _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) 191 | CompileAsC 192 | $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories) 193 | /FS %(AdditionalOptions) 194 | 195 | 196 | Console 197 | true 198 | $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ 199 | raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 200 | 201 | 202 | 203 | 204 | 205 | 206 | Level3 207 | Disabled 208 | _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) 209 | CompileAsC 210 | $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories) 211 | 212 | 213 | Console 214 | true 215 | $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ 216 | raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 217 | 218 | 219 | xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" 220 | Copy Debug DLL to output directory 221 | 222 | 223 | 224 | 225 | 226 | 227 | Level3 228 | Disabled 229 | _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) 230 | CompileAsC 231 | $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories) 232 | 233 | 234 | Console 235 | true 236 | $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ 237 | raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 238 | 239 | 240 | xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" 241 | Copy Debug DLL to output directory 242 | 243 | 244 | 245 | 246 | Level3 247 | 248 | 249 | MaxSpeed 250 | true 251 | true 252 | _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) 253 | $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories) 254 | CompileAsC 255 | true 256 | MultiThreaded 257 | 258 | 259 | Console 260 | true 261 | true 262 | true 263 | raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 264 | $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ 265 | 266 | 267 | 268 | 269 | Level3 270 | 271 | 272 | MaxSpeed 273 | true 274 | true 275 | _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) 276 | $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories) 277 | CompileAsC 278 | true 279 | MultiThreaded 280 | 281 | 282 | Console 283 | true 284 | true 285 | true 286 | raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 287 | $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ 288 | 289 | 290 | 291 | 292 | Level3 293 | 294 | 295 | MaxSpeed 296 | true 297 | true 298 | _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) 299 | $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories) 300 | CompileAsC 301 | true 302 | 303 | 304 | Console 305 | true 306 | true 307 | true 308 | raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 309 | $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ 310 | 311 | 312 | xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" 313 | 314 | 315 | Copy Release DLL to output directory 316 | 317 | 318 | 319 | 320 | Level3 321 | 322 | 323 | MaxSpeed 324 | true 325 | true 326 | _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) 327 | $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories) 328 | CompileAsC 329 | true 330 | 331 | 332 | Console 333 | true 334 | true 335 | true 336 | raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 337 | $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ 338 | 339 | 340 | xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" 341 | 342 | 343 | Copy Release DLL to output directory 344 | 345 | 346 | 347 | 348 | {e89d61ac-55de-4482-afd4-df7242ebc859} 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | -------------------------------------------------------------------------------- /projects/VS2022/blocks/blocks.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(ProjectDir)..\..\..\lessons 5 | WindowsLocalDebugger 6 | 7 | 8 | $(ProjectDir)..\..\..\lessons 9 | WindowsLocalDebugger 10 | 11 | 12 | $(ProjectDir)..\..\..\lessons 13 | WindowsLocalDebugger 14 | 15 | 16 | $(ProjectDir)..\..\..\lessons 17 | WindowsLocalDebugger 18 | 19 | 20 | $(ProjectDir)..\..\..\lessons 21 | WindowsLocalDebugger 22 | 23 | 24 | $(ProjectDir)..\..\..\lessons 25 | WindowsLocalDebugger 26 | 27 | 28 | $(ProjectDir)..\..\..\lessons 29 | WindowsLocalDebugger 30 | 31 | 32 | $(ProjectDir)..\..\..\lessons 33 | WindowsLocalDebugger 34 | 35 | -------------------------------------------------------------------------------- /projects/VS2022/raylib/raylib.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug.DLL 6 | Win32 7 | 8 | 9 | Debug.DLL 10 | x64 11 | 12 | 13 | Debug 14 | Win32 15 | 16 | 17 | Debug 18 | x64 19 | 20 | 21 | Release.DLL 22 | Win32 23 | 24 | 25 | Release.DLL 26 | x64 27 | 28 | 29 | Release 30 | Win32 31 | 32 | 33 | Release 34 | x64 35 | 36 | 37 | 38 | {E89D61AC-55DE-4482-AFD4-DF7242EBC859} 39 | Win32Proj 40 | raylib 41 | 10.0 42 | 43 | 44 | 45 | StaticLibrary 46 | true 47 | $(DefaultPlatformToolset) 48 | Unicode 49 | 50 | 51 | StaticLibrary 52 | true 53 | $(DefaultPlatformToolset) 54 | Unicode 55 | 56 | 57 | DynamicLibrary 58 | true 59 | $(DefaultPlatformToolset) 60 | Unicode 61 | 62 | 63 | DynamicLibrary 64 | true 65 | $(DefaultPlatformToolset) 66 | Unicode 67 | 68 | 69 | StaticLibrary 70 | false 71 | $(DefaultPlatformToolset) 72 | Unicode 73 | 74 | 75 | StaticLibrary 76 | false 77 | $(DefaultPlatformToolset) 78 | Unicode 79 | 80 | 81 | DynamicLibrary 82 | false 83 | $(DefaultPlatformToolset) 84 | Unicode 85 | 86 | 87 | DynamicLibrary 88 | false 89 | $(DefaultPlatformToolset) 90 | Unicode 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ 124 | $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ 125 | 126 | 127 | $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ 128 | $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ 129 | 130 | 131 | $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ 132 | $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ 133 | 134 | 135 | $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ 136 | $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ 137 | 138 | 139 | $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ 140 | $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ 141 | 142 | 143 | $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ 144 | $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ 145 | 146 | 147 | $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ 148 | $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ 149 | 150 | 151 | $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ 152 | $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ 153 | 154 | 155 | 156 | 157 | 158 | Level3 159 | Disabled 160 | _CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions);GRAPHICS_API_OPENGL_33;PLATFORM_DESKTOP 161 | CompileAsC 162 | $(ProjectDir)..\..\..\..\raylib\src\external\glfw\include 163 | 164 | 165 | Windows 166 | 167 | 168 | %(AdditionalLibraryDirectories) 169 | 170 | 171 | 172 | 173 | 174 | 175 | Level3 176 | Disabled 177 | _CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions);GRAPHICS_API_OPENGL_33;PLATFORM_DESKTOP 178 | CompileAsC 179 | $(ProjectDir)..\..\..\..\raylib\src\external\glfw\include 180 | 181 | 182 | Windows 183 | 184 | 185 | %(AdditionalLibraryDirectories) 186 | 187 | 188 | 189 | 190 | 191 | 192 | Level3 193 | Disabled 194 | _CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions);GRAPHICS_API_OPENGL_33;PLATFORM_DESKTOP;BUILD_LIBTYPE_SHARED 195 | CompileAsC 196 | $(ProjectDir)..\..\..\..\raylib\src\external\glfw\include 197 | MultiThreadedDebug 198 | 199 | 200 | Windows 201 | kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 202 | 203 | 204 | %(AdditionalLibraryDirectories) 205 | 206 | 207 | 208 | 209 | 210 | 211 | Level3 212 | Disabled 213 | _CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions);GRAPHICS_API_OPENGL_33;PLATFORM_DESKTOP;BUILD_LIBTYPE_SHARED 214 | CompileAsC 215 | $(ProjectDir)..\..\..\..\raylib\src\external\glfw\include 216 | MultiThreadedDebug 217 | 218 | 219 | Windows 220 | kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 221 | 222 | 223 | %(AdditionalLibraryDirectories) 224 | 225 | 226 | 227 | 228 | Level3 229 | 230 | 231 | MaxSpeed 232 | true 233 | true 234 | _CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions);GRAPHICS_API_OPENGL_33;PLATFORM_DESKTOP 235 | $(ProjectDir)..\..\..\..\raylib\src\external\glfw\include 236 | CompileAsC 237 | MultiThreaded 238 | 239 | 240 | Windows 241 | true 242 | true 243 | 244 | 245 | 246 | 247 | Level3 248 | 249 | 250 | MaxSpeed 251 | true 252 | true 253 | _CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions);GRAPHICS_API_OPENGL_33;PLATFORM_DESKTOP 254 | $(ProjectDir)..\..\..\..\raylib\src\external\glfw\include 255 | CompileAsC 256 | 257 | MultiThreaded 258 | 259 | 260 | Windows 261 | true 262 | true 263 | 264 | 265 | 266 | 267 | Level3 268 | 269 | 270 | MaxSpeed 271 | true 272 | true 273 | _CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions);GRAPHICS_API_OPENGL_33;PLATFORM_DESKTOP;BUILD_LIBTYPE_SHARED 274 | $(ProjectDir)..\..\..\..\raylib\src\external\glfw\include 275 | CompileAsC 276 | MultiThreaded 277 | 278 | 279 | Windows 280 | true 281 | true 282 | kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 283 | 284 | 285 | 286 | 287 | Level3 288 | 289 | 290 | MaxSpeed 291 | true 292 | true 293 | _CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions);GRAPHICS_API_OPENGL_33;PLATFORM_DESKTOP;BUILD_LIBTYPE_SHARED 294 | $(ProjectDir)..\..\..\..\raylib\src\external\glfw\include 295 | CompileAsC 296 | MultiThreaded 297 | 298 | 299 | 300 | Windows 301 | true 302 | true 303 | kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | --------------------------------------------------------------------------------