├── .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 | 
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 | 
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 | 
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 |
--------------------------------------------------------------------------------