找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 415|回复: 6

【Raylib&C++教程01期】介绍+环境搭建+官网开源学习

[复制链接]

8

主题

39

回帖

852

积分

管理员

积分
852
发表于 2024-7-18 13:01:06 | 显示全部楼层 |阅读模式
(emm.....没想到我研究CTF几天不在CZLJ,一下子涌进来这么多用户,看来不发点干(hen)货(huo)不行了——)

Part 1:什么是Raylib
在讲Raylib之前,你需要知道森么是OpenGL。
      OpenGL(英语:Open Graphics Library,译名:开放图形库或者“开放式图形库”)是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(API)。这个接口由近350个不同的函数调用组成,用来绘制从简单的图形到比较复杂的三维景象。OpenGL常用于CAD、虚拟现实、科学可视化程序和电子游戏开发。OpenGL的高效实现(利用了图形加速硬件)存在于Windows,部分UNIX平台和Mac OS。
        当今,OpenGL是视频行业领域中用于处理2D/3D图形的最为广泛接纳的API,在此基础上,为了用于计算机视觉技术的研究,从而催生了各种计算机平台上的应用功能以及设备上的许多应用程序。其是独立于Windows操作系统以及操作系统平台,可以进行多种不同领域的开发和内容创作,简而言之,其帮助研发人员能够实现PC、工作站、超级计算机以及各种工控机等硬件设备上实现高性能、对于视觉要求极高的高视觉图形处理软件的开发。——摘自  百度百科


是不是听上去很库?OpenGL兼容了众多主流操作系统,且有多个编程语言的应用接口(API),是当今主流两个图形渲染库之一(另一个是仅用于Microsoft Windows上的Direct3D)


(注:本系列基本使用C++语言经行开发。)


不过,作者个人觉得OpenGL的函数非常友好。举个例子,下面是用OpenGL绘制一个立方体的部分程序源代码:
    glClearColor(1.0, 1.0, 1.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glColor3f(1.0, 0.0, 0.0);
    gluLookAt(0.0, 0.0, -10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
    glBegin(GL_QUADS);
    {
        glVertex3f(0.5, 0.5, 0.5);
        glVertex3f(-0.5, 0.5, 0.5);
        glVertex3f(-0.5, -0.5, 0.5);
        glVertex3f(0.5, -0.5, 0.5);
    }
    glEnd();
    //左面
    glBegin(GL_QUADS);
    {
        glVertex3f(-0.5, 0.5, 0.5);
        glVertex3f(-0.5, 0.5, -0.5);
        glVertex3f(-0.5, -0.5, -0.5);
        glVertex3f(-0.5, -0.5, 0.5);
    }
    glEnd();
    //下面
    glBegin(GL_QUADS);
    {
        glVertex3f(-0.5, -0.5, -0.5);
        glVertex3f(-0.5, -0.5, 0.5);
        glVertex3f(0.5, -0.5, 0.5);
        glVertex3f(0.5, -0.5, -0.5);
    }
    glEnd();
    //右面
    glBegin(GL_QUADS);
    {
        glVertex3f(0.5, -0.5, -0.5);
        glVertex3f(0.5, -0.5, 0.5);
        glVertex3f(0.5, 0.5, 0.5);
        glVertex3f(0.5, 0.5, -0.5);
    }
    glEnd();
    //前面
    glBegin(GL_QUADS);
    {
        glVertex3f(-0.5, 0.5, 0.5);
        glVertex3f(0.5, 0.5, 0.5);
        glVertex3f(0.5, -0.5, 0.5);
        glVertex3f(-0.5, -0.5, 0.5);
    }
    glEnd();
    //后面
    glBegin(GL_QUADS);
    {
        glVertex3f(-0.5, 0.5, -0.5);
        glVertex3f(0.5, 0.5, -0.5);
        glVertex3f(0.5, -0.5, -0.5);
        glVertex3f(-0.5, -0.5, -0.5);
    }
    glEnd();
    glFlush();


再看看用Raylib的函数画立方体:DrawCube((Vector3){0.0,0.0,0.0},1,1,1,SKYBLUE);
其实自己封装一个OpenGL画Cube的函数也可以,只要计算出Cube的八个点再用glVertex3fv传参挨个填过去就可以了。但是Raylib已经封装了大量图形绘制的函数,不用自己再麻烦了。
OpenGL的函数是最原始的“设定一个点,再设定一个点,再连线”地绘图,用它画一个立方体需要36+行代码,没有那种封装好可以直接调用的画图函数,而Raylib则是对OpenGL做了大量封装,内置有绘制各种2D/3D图形的函数,只需要设定图形的大小、位置这样的参数就能完成。
这就好比OpenGL是你摘抄时一笔一划写,而Raylib是你把文章剪下来贴在摘抄本上一样AwA
Raylib(直译为雷利卜)是一个简洁轻量的2D/3D图形库。他涵盖了OpenGL的多个库,包括

  • glut.h
  • glfw.h
  • glew.h
  • glad.h
  • std_image.h
  • ...
且可以做到轻松绘制图形、创建窗口、加载贴图、加载声音、鼠标键盘交互等等,是一个为开发游戏而生的库!
Part 2:配置Raylib环境
Raylib的环境配置不难,只要一个编辑器就可以。他就是我们的国产之光——小熊猫C++



小熊猫C++
相比于传统的Dev-C++,小熊猫C++的功能做了大改动:

操作简便
小熊猫C++无需复杂的安装和配置,打开即可直接编辑程序文件;无需创建项目,点击工具栏上按钮即可编译、运行和调试程序。


轻量高效
小熊猫C++基于QT和C++语言开发,使用内置的轻量级代码分析器进行智能语法分析,运行时无需大量的内存和CPU资源,在低配置机器上也能获得流畅的运行体验。


多平台支持
小熊猫C++支持Windows 7/8/10、Linux等操作系统。在各种操作系统下都能获得相同的高质量编程体验。



生产力提升
通过集成自动缩进、智能代码补全、智能语法高亮和实时语法检查等功能,小熊猫C++提供了流畅的代码编辑体验,可以大幅度提升代码编写的效率。


调试
小熊猫C++提供完善的调试功能,包括控制程序执行、断点、监视变量和表达式、表达式求值、查看本地变量、查看和切换调用栈、查看和修改内存、查看CPU寄存器和反编译信息等。小熊猫C++甚至还可以重定向被调试程序的输入!


多屏幕
小熊猫C++提供了完善的高分辨率和多显示器支持,能够在多个不同DPI设置的显示器间自由切换,同时提供完善的显示效果,便于教学和展示。



试题集和OJ
针对C/C++教学和竞赛需求,小熊猫C++专门提供了试题集和OJ功能:可以方便的组织管理、运行和测试C/C++练习程序;可以导入或者从OJ网站下载试题和配套的测试数据。


GIT版本管理
小熊猫C++内置git支持,可以方便对项目或工作文件夹进行版本管理(需额外安装git程序)






没错就是这个功能!
| |
||
👇





整合多种学习用库
Windows版小熊猫C++在自带gcc中整合了ege、海龟作图、raylib、freeglut、GLFW和GLEW等适合编程或者游戏开发入门者使用的库和项目模板,无需复杂的安装配置即可直接使用。



支持汇编语言
小熊猫C++支持编译C/C++程序生成对应的汇编语言程序;可以在调试时进行反汇编;支持编译、运行和调试GNU汇编语言程序;提供汇编程序的语法高亮、实时语法检查和关键字输入提示。利用这些功能,用户可以更加深入的学习操作系统和计算机硬件编程知识。



可以看出,小熊猫C++(RedPandaIDE)编辑器的优势丝毫不亚于Visual studio Code。小熊猫C++目前已升级至3.1版本。3.1版的小熊猫C++配置的Raylib为最新版的5.0版,小熊猫以前版本的Raylib均为4.5版,手感上有所差异,所以建议大家下载最新版。


注意:在官网下载时,不要下载网盘里分享的带有NoCompiler字样的安装包,要下载带有MinGW32或64的安装包,否则没法编译。下载时浏览器可能会提醒文件存在风险,请放心点保留。

下载完成后双击运行安装包,根据自己的需要安装。基本只要点“下一步”。

安装完成后运行它,选择默认语言为C++。新建一个文件,把下面的代码拷进去试一下按F11编译运行。如果没有问题会出现一个小的俄罗斯方块的游戏,那么你的Raylib开发环境已经配置完成了!

  1. /*******************************************************************************************
  2. *
  3. *   raylib - classic game: tetris
  4. *
  5. *   Sample game developed by Marc Palau and Ramon Santamaria
  6. *
  7. *   This game has been created using raylib v1.3 (www.raylib.com)
  8. *   raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
  9. *
  10. *   Copyright (c) 2015 Ramon Santamaria (@raysan5)
  11. *
  12. ********************************************************************************************/

  13. #include "raylib.h"

  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <time.h>
  17. #include <math.h>

  18. #if defined(PLATFORM_WEB)
  19.     #include <emscripten/emscripten.h>
  20. #endif

  21. //----------------------------------------------------------------------------------
  22. // Some Defines
  23. //----------------------------------------------------------------------------------
  24. #define SQUARE_SIZE             20

  25. #define GRID_HORIZONTAL_SIZE    12
  26. #define GRID_VERTICAL_SIZE      20

  27. #define LATERAL_SPEED           10
  28. #define TURNING_SPEED           12
  29. #define FAST_FALL_AWAIT_COUNTER 30

  30. #define FADING_TIME             33

  31. //----------------------------------------------------------------------------------
  32. // Types and Structures Definition
  33. //----------------------------------------------------------------------------------
  34. typedef enum GridSquare { EMPTY, MOVING, FULL, BLOCK, FADING } GridSquare;

  35. //------------------------------------------------------------------------------------
  36. // Global Variables Declaration
  37. //------------------------------------------------------------------------------------
  38. static const int screenWidth = 800;
  39. static const int screenHeight = 450;

  40. static bool gameOver = false;
  41. static bool pause = false;

  42. // Matrices
  43. static GridSquare grid [GRID_HORIZONTAL_SIZE][GRID_VERTICAL_SIZE];
  44. static GridSquare piece [4][4];
  45. static GridSquare incomingPiece [4][4];

  46. // Theese variables keep track of the active piece position
  47. static int piecePositionX = 0;
  48. static int piecePositionY = 0;

  49. // Game parameters
  50. static Color fadingColor;
  51. //static int fallingSpeed;           // In frames

  52. static bool beginPlay = true;      // This var is only true at the begining of the game, used for the first matrix creations
  53. static bool pieceActive = false;
  54. static bool detection = false;
  55. static bool lineToDelete = false;

  56. // Statistics
  57. static int level = 1;
  58. static int lines = 0;

  59. // Counters
  60. static int gravityMovementCounter = 0;
  61. static int lateralMovementCounter = 0;
  62. static int turnMovementCounter = 0;
  63. static int fastFallMovementCounter = 0;

  64. static int fadeLineCounter = 0;

  65. // Based on level
  66. static int gravitySpeed = 30;

  67. //------------------------------------------------------------------------------------
  68. // Module Functions Declaration (local)
  69. //------------------------------------------------------------------------------------
  70. static void InitGame(void);         // Initialize game
  71. static void UpdateGame(void);       // Update game (one frame)
  72. static void DrawGame(void);         // Draw game (one frame)
  73. static void UnloadGame(void);       // Unload game
  74. static void UpdateDrawFrame(void);  // Update and Draw (one frame)

  75. // Additional module functions
  76. static bool Createpiece();
  77. static void GetRandompiece();
  78. static void ResolveFallingMovement(bool *detection, bool *pieceActive);
  79. static bool ResolveLateralMovement();
  80. static bool ResolveTurnMovement();
  81. static void CheckDetection(bool *detection);
  82. static void CheckCompletion(bool *lineToDelete);
  83. static void DeleteCompleteLines();

  84. //------------------------------------------------------------------------------------
  85. // Program main entry point
  86. //------------------------------------------------------------------------------------
  87. int main(void)
  88. {
  89.     // Initialization (Note windowTitle is unused on Android)
  90.     //---------------------------------------------------------
  91.     InitWindow(screenWidth, screenHeight, "classic game: tetris");

  92.     InitGame();

  93. #if defined(PLATFORM_WEB)
  94.     emscripten_set_main_loop(UpdateDrawFrame, 60, 1);
  95. #else
  96.     SetTargetFPS(60);
  97.     //--------------------------------------------------------------------------------------

  98.     // Main game loop
  99.     while (!WindowShouldClose())    // Detect window close button or ESC key
  100.     {
  101.         // Update and Draw
  102.         //----------------------------------------------------------------------------------
  103.         UpdateDrawFrame();
  104.         //----------------------------------------------------------------------------------
  105.     }
  106. #endif
  107.     // De-Initialization
  108.     //--------------------------------------------------------------------------------------
  109.     UnloadGame();         // Unload loaded data (textures, sounds, models...)

  110.     CloseWindow();        // Close window and OpenGL context
  111.     //--------------------------------------------------------------------------------------

  112.     return 0;
  113. }

  114. //--------------------------------------------------------------------------------------
  115. // Game Module Functions Definition
  116. //--------------------------------------------------------------------------------------

  117. // Initialize game variables
  118. void InitGame(void)
  119. {
  120.     // Initialize game statistics
  121.     level = 1;
  122.     lines = 0;

  123.     fadingColor = GRAY;

  124.     piecePositionX = 0;
  125.     piecePositionY = 0;

  126.     pause = false;

  127.     beginPlay = true;
  128.     pieceActive = false;
  129.     detection = false;
  130.     lineToDelete = false;

  131.     // Counters
  132.     gravityMovementCounter = 0;
  133.     lateralMovementCounter = 0;
  134.     turnMovementCounter = 0;
  135.     fastFallMovementCounter = 0;

  136.     fadeLineCounter = 0;
  137.     gravitySpeed = 30;

  138.     // Initialize grid matrices
  139.     for (int i = 0; i < GRID_HORIZONTAL_SIZE; i++)
  140.     {
  141.         for (int j = 0; j < GRID_VERTICAL_SIZE; j++)
  142.         {
  143.             if ((j == GRID_VERTICAL_SIZE - 1) || (i == 0) || (i == GRID_HORIZONTAL_SIZE - 1)) grid[i][j] = BLOCK;
  144.             else grid[i][j] = EMPTY;
  145.         }
  146.     }

  147.     // Initialize incoming piece matrices
  148.     for (int i = 0; i < 4; i++)
  149.     {
  150.         for (int j = 0; j< 4; j++)
  151.         {
  152.             incomingPiece[i][j] = EMPTY;
  153.         }
  154.     }
  155. }

  156. // Update game (one frame)
  157. void UpdateGame(void)
  158. {
  159.     if (!gameOver)
  160.     {
  161.         if (IsKeyPressed('P')) pause = !pause;

  162.         if (!pause)
  163.         {
  164.             if (!lineToDelete)
  165.             {
  166.                 if (!pieceActive)
  167.                 {
  168.                     // Get another piece
  169.                     pieceActive = Createpiece();

  170.                     // We leave a little time before starting the fast falling down
  171.                     fastFallMovementCounter = 0;
  172.                 }
  173.                 else    // Piece falling
  174.                 {
  175.                     // Counters update
  176.                     fastFallMovementCounter++;
  177.                     gravityMovementCounter++;
  178.                     lateralMovementCounter++;
  179.                     turnMovementCounter++;

  180.                     // We make sure to move if we've pressed the key this frame
  181.                     if (IsKeyPressed(KEY_LEFT) || IsKeyPressed(KEY_RIGHT)) lateralMovementCounter = LATERAL_SPEED;
  182.                     if (IsKeyPressed(KEY_UP)) turnMovementCounter = TURNING_SPEED;

  183.                     // Fall down
  184.                     if (IsKeyDown(KEY_DOWN) && (fastFallMovementCounter >= FAST_FALL_AWAIT_COUNTER))
  185.                     {
  186.                         // We make sure the piece is going to fall this frame
  187.                         gravityMovementCounter += gravitySpeed;
  188.                     }

  189.                     if (gravityMovementCounter >= gravitySpeed)
  190.                     {
  191.                         // Basic falling movement
  192.                         CheckDetection(&detection);

  193.                         // Check if the piece has collided with another piece or with the boundings
  194.                         ResolveFallingMovement(&detection, &pieceActive);

  195.                         // Check if we fullfilled a line and if so, erase the line and pull down the the lines above
  196.                         CheckCompletion(&lineToDelete);

  197.                         gravityMovementCounter = 0;
  198.                     }

  199.                     // Move laterally at player's will
  200.                     if (lateralMovementCounter >= LATERAL_SPEED)
  201.                     {
  202.                         // Update the lateral movement and if success, reset the lateral counter
  203.                         if (!ResolveLateralMovement()) lateralMovementCounter = 0;
  204.                     }

  205.                     // Turn the piece at player's will
  206.                     if (turnMovementCounter >= TURNING_SPEED)
  207.                     {
  208.                         // Update the turning movement and reset the turning counter
  209.                         if (ResolveTurnMovement()) turnMovementCounter = 0;
  210.                     }
  211.                 }

  212.                 // Game over logic
  213.                 for (int j = 0; j < 2; j++)
  214.                 {
  215.                     for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
  216.                     {
  217.                         if (grid[i][j] == FULL)
  218.                         {
  219.                             gameOver = true;
  220.                         }
  221.                     }
  222.                 }
  223.             }
  224.             else
  225.             {
  226.                 // Animation when deleting lines
  227.                 fadeLineCounter++;

  228.                 if (fadeLineCounter%8 < 4) fadingColor = MAROON;
  229.                 else fadingColor = GRAY;

  230.                 if (fadeLineCounter >= FADING_TIME)
  231.                 {
  232.                     DeleteCompleteLines();
  233.                     fadeLineCounter = 0;
  234.                     lineToDelete = false;

  235.                     lines++;
  236.                 }
  237.             }
  238.         }
  239.     }
  240.     else
  241.     {
  242.         if (IsKeyPressed(KEY_ENTER))
  243.         {
  244.             InitGame();
  245.             gameOver = false;
  246.         }
  247.     }
  248. }

  249. // Draw game (one frame)
  250. void DrawGame(void)
  251. {
  252.     BeginDrawing();

  253.         ClearBackground(RAYWHITE);

  254.         if (!gameOver)
  255.         {
  256.             // Draw gameplay area
  257.             Vector2 offset;
  258.             offset.x = screenWidth/2 - (GRID_HORIZONTAL_SIZE*SQUARE_SIZE/2) - 50;
  259.             offset.y = screenHeight/2 - ((GRID_VERTICAL_SIZE - 1)*SQUARE_SIZE/2) + SQUARE_SIZE*2;

  260.             offset.y -= 50;     // NOTE: Harcoded position!

  261.             int controller = offset.x;

  262.             for (int j = 0; j < GRID_VERTICAL_SIZE; j++)
  263.             {
  264.                 for (int i = 0; i < GRID_HORIZONTAL_SIZE; i++)
  265.                 {
  266.                     // Draw each square of the grid
  267.                     if (grid[i][j] == EMPTY)
  268.                     {
  269.                         DrawLine(offset.x, offset.y, offset.x + SQUARE_SIZE, offset.y, LIGHTGRAY );
  270.                         DrawLine(offset.x, offset.y, offset.x, offset.y + SQUARE_SIZE, LIGHTGRAY );
  271.                         DrawLine(offset.x + SQUARE_SIZE, offset.y, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY );
  272.                         DrawLine(offset.x, offset.y + SQUARE_SIZE, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY );
  273.                         offset.x += SQUARE_SIZE;
  274.                     }
  275.                     else if (grid[i][j] == FULL)
  276.                     {
  277.                         DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, GRAY);
  278.                         offset.x += SQUARE_SIZE;
  279.                     }
  280.                     else if (grid[i][j] == MOVING)
  281.                     {
  282.                         DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, DARKGRAY);
  283.                         offset.x += SQUARE_SIZE;
  284.                     }
  285.                     else if (grid[i][j] == BLOCK)
  286.                     {
  287.                         DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, LIGHTGRAY);
  288.                         offset.x += SQUARE_SIZE;
  289.                     }
  290.                     else if (grid[i][j] == FADING)
  291.                     {
  292.                         DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, fadingColor);
  293.                         offset.x += SQUARE_SIZE;
  294.                     }
  295.                 }

  296.                 offset.x = controller;
  297.                 offset.y += SQUARE_SIZE;
  298.             }

  299.             // Draw incoming piece (hardcoded)
  300.             offset.x = 500;
  301.             offset.y = 45;

  302.             int controler = offset.x;

  303.             for (int j = 0; j < 4; j++)
  304.             {
  305.                 for (int i = 0; i < 4; i++)
  306.                 {
  307.                     if (incomingPiece[i][j] == EMPTY)
  308.                     {
  309.                         DrawLine(offset.x, offset.y, offset.x + SQUARE_SIZE, offset.y, LIGHTGRAY );
  310.                         DrawLine(offset.x, offset.y, offset.x, offset.y + SQUARE_SIZE, LIGHTGRAY );
  311.                         DrawLine(offset.x + SQUARE_SIZE, offset.y, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY );
  312.                         DrawLine(offset.x, offset.y + SQUARE_SIZE, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY );
  313.                         offset.x += SQUARE_SIZE;
  314.                     }
  315.                     else if (incomingPiece[i][j] == MOVING)
  316.                     {
  317.                         DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, GRAY);
  318.                         offset.x += SQUARE_SIZE;
  319.                     }
  320.                 }

  321.                 offset.x = controler;
  322.                 offset.y += SQUARE_SIZE;
  323.             }

  324.             DrawText("INCOMING:", offset.x, offset.y - 100, 10, GRAY);
  325.             DrawText(TextFormat("LINES:      %04i", lines), offset.x, offset.y + 20, 10, GRAY);

  326.             if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY);
  327.         }
  328.         else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY);

  329.     EndDrawing();
  330. }

  331. // Unload game variables
  332. void UnloadGame(void)
  333. {
  334.     // TODO: Unload all dynamic loaded data (textures, sounds, models...)
  335. }

  336. // Update and Draw (one frame)
  337. void UpdateDrawFrame(void)
  338. {
  339.     UpdateGame();
  340.     DrawGame();
  341. }

  342. //--------------------------------------------------------------------------------------
  343. // Additional module functions
  344. //--------------------------------------------------------------------------------------
  345. static bool Createpiece()
  346. {
  347.     piecePositionX = (int)((GRID_HORIZONTAL_SIZE - 4)/2);
  348.     piecePositionY = 0;

  349.     // If the game is starting and you are going to create the first piece, we create an extra one
  350.     if (beginPlay)
  351.     {
  352.         GetRandompiece();
  353.         beginPlay = false;
  354.     }

  355.     // We assign the incoming piece to the actual piece
  356.     for (int i = 0; i < 4; i++)
  357.     {
  358.         for (int j = 0; j< 4; j++)
  359.         {
  360.             piece[i][j] = incomingPiece[i][j];
  361.         }
  362.     }

  363.     // We assign a random piece to the incoming one
  364.     GetRandompiece();

  365.     // Assign the piece to the grid
  366.     for (int i = piecePositionX; i < piecePositionX + 4; i++)
  367.     {
  368.         for (int j = 0; j < 4; j++)
  369.         {
  370.             if (piece[i - (int)piecePositionX][j] == MOVING) grid[i][j] = MOVING;
  371.         }
  372.     }

  373.     return true;
  374. }

  375. static void GetRandompiece()
  376. {
  377.     int random = GetRandomValue(0, 6);

  378.     for (int i = 0; i < 4; i++)
  379.     {
  380.         for (int j = 0; j < 4; j++)
  381.         {
  382.             incomingPiece[i][j] = EMPTY;
  383.         }
  384.     }

  385.     switch (random)
  386.     {
  387.         case 0: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break;    //Cube
  388.         case 1: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break;    //L
  389.         case 2: { incomingPiece[1][2] = MOVING; incomingPiece[2][0] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; } break;    //L inversa
  390.         case 3: { incomingPiece[0][1] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break;    //Recta
  391.         case 4: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][1] = MOVING; } break;    //Creu tallada
  392.         case 5: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[3][2] = MOVING; } break;    //S
  393.         case 6: { incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break;    //S inversa
  394.     }
  395. }

  396. static void ResolveFallingMovement(bool *detection, bool *pieceActive)
  397. {
  398.     // If we finished moving this piece, we stop it
  399.     if (*detection)
  400.     {
  401.         for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
  402.         {
  403.             for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
  404.             {
  405.                 if (grid[i][j] == MOVING)
  406.                 {
  407.                     grid[i][j] = FULL;
  408.                     *detection = false;
  409.                     *pieceActive = false;
  410.                 }
  411.             }
  412.         }
  413.     }
  414.     else    // We move down the piece
  415.     {
  416.         for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
  417.         {
  418.             for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
  419.             {
  420.                 if (grid[i][j] == MOVING)
  421.                 {
  422.                     grid[i][j+1] = MOVING;
  423.                     grid[i][j] = EMPTY;
  424.                 }
  425.             }
  426.         }

  427.         piecePositionY++;
  428.     }
  429. }

  430. static bool ResolveLateralMovement()
  431. {
  432.     bool collision = false;

  433.     // Piece movement
  434.     if (IsKeyDown(KEY_LEFT))        // Move left
  435.     {
  436.         // Check if is possible to move to left
  437.         for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
  438.         {
  439.             for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
  440.             {
  441.                 if (grid[i][j] == MOVING)
  442.                 {
  443.                     // Check if we are touching the left wall or we have a full square at the left
  444.                     if ((i-1 == 0) || (grid[i-1][j] == FULL)) collision = true;
  445.                 }
  446.             }
  447.         }

  448.         // If able, move left
  449.         if (!collision)
  450.         {
  451.             for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
  452.             {
  453.                 for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)             // We check the matrix from left to right
  454.                 {
  455.                     // Move everything to the left
  456.                     if (grid[i][j] == MOVING)
  457.                     {
  458.                         grid[i-1][j] = MOVING;
  459.                         grid[i][j] = EMPTY;
  460.                     }
  461.                 }
  462.             }

  463.             piecePositionX--;
  464.         }
  465.     }
  466.     else if (IsKeyDown(KEY_RIGHT))  // Move right
  467.     {
  468.         // Check if is possible to move to right
  469.         for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
  470.         {
  471.             for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
  472.             {
  473.                 if (grid[i][j] == MOVING)
  474.                 {
  475.                     // Check if we are touching the right wall or we have a full square at the right
  476.                     if ((i+1 == GRID_HORIZONTAL_SIZE - 1) || (grid[i+1][j] == FULL))
  477.                     {
  478.                         collision = true;

  479.                     }
  480.                 }
  481.             }
  482.         }

  483.         // If able move right
  484.         if (!collision)
  485.         {
  486.             for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
  487.             {
  488.                 for (int i = GRID_HORIZONTAL_SIZE - 1; i >= 1; i--)             // We check the matrix from right to left
  489.                 {
  490.                     // Move everything to the right
  491.                     if (grid[i][j] == MOVING)
  492.                     {
  493.                         grid[i+1][j] = MOVING;
  494.                         grid[i][j] = EMPTY;
  495.                     }
  496.                 }
  497.             }

  498.             piecePositionX++;
  499.         }
  500.     }

  501.     return collision;
  502. }

  503. static bool ResolveTurnMovement()
  504. {
  505.     // Input for turning the piece
  506.     if (IsKeyDown(KEY_UP))
  507.     {
  508.         GridSquare aux;
  509.         bool checker = false;

  510.         // Check all turning possibilities
  511.         if ((grid[piecePositionX + 3][piecePositionY] == MOVING) &&
  512.             (grid[piecePositionX][piecePositionY] != EMPTY) &&
  513.             (grid[piecePositionX][piecePositionY] != MOVING)) checker = true;

  514.         if ((grid[piecePositionX + 3][piecePositionY + 3] == MOVING) &&
  515.             (grid[piecePositionX + 3][piecePositionY] != EMPTY) &&
  516.             (grid[piecePositionX + 3][piecePositionY] != MOVING)) checker = true;

  517.         if ((grid[piecePositionX][piecePositionY + 3] == MOVING) &&
  518.             (grid[piecePositionX + 3][piecePositionY + 3] != EMPTY) &&
  519.             (grid[piecePositionX + 3][piecePositionY + 3] != MOVING)) checker = true;

  520.         if ((grid[piecePositionX][piecePositionY] == MOVING) &&
  521.             (grid[piecePositionX][piecePositionY + 3] != EMPTY) &&
  522.             (grid[piecePositionX][piecePositionY + 3] != MOVING)) checker = true;

  523.         if ((grid[piecePositionX + 1][piecePositionY] == MOVING) &&
  524.             (grid[piecePositionX][piecePositionY + 2] != EMPTY) &&
  525.             (grid[piecePositionX][piecePositionY + 2] != MOVING)) checker = true;

  526.         if ((grid[piecePositionX + 3][piecePositionY + 1] == MOVING) &&
  527.             (grid[piecePositionX + 1][piecePositionY] != EMPTY) &&
  528.             (grid[piecePositionX + 1][piecePositionY] != MOVING)) checker = true;

  529.         if ((grid[piecePositionX + 2][piecePositionY + 3] == MOVING) &&
  530.             (grid[piecePositionX + 3][piecePositionY + 1] != EMPTY) &&
  531.             (grid[piecePositionX + 3][piecePositionY + 1] != MOVING)) checker = true;

  532.         if ((grid[piecePositionX][piecePositionY + 2] == MOVING) &&
  533.             (grid[piecePositionX + 2][piecePositionY + 3] != EMPTY) &&
  534.             (grid[piecePositionX + 2][piecePositionY + 3] != MOVING)) checker = true;

  535.         if ((grid[piecePositionX + 2][piecePositionY] == MOVING) &&
  536.             (grid[piecePositionX][piecePositionY + 1] != EMPTY) &&
  537.             (grid[piecePositionX][piecePositionY + 1] != MOVING)) checker = true;

  538.         if ((grid[piecePositionX + 3][piecePositionY + 2] == MOVING) &&
  539.             (grid[piecePositionX + 2][piecePositionY] != EMPTY) &&
  540.             (grid[piecePositionX + 2][piecePositionY] != MOVING)) checker = true;

  541.         if ((grid[piecePositionX + 1][piecePositionY + 3] == MOVING) &&
  542.             (grid[piecePositionX + 3][piecePositionY + 2] != EMPTY) &&
  543.             (grid[piecePositionX + 3][piecePositionY + 2] != MOVING)) checker = true;

  544.         if ((grid[piecePositionX][piecePositionY + 1] == MOVING) &&
  545.             (grid[piecePositionX + 1][piecePositionY + 3] != EMPTY) &&
  546.             (grid[piecePositionX + 1][piecePositionY + 3] != MOVING)) checker = true;

  547.         if ((grid[piecePositionX + 1][piecePositionY + 1] == MOVING) &&
  548.             (grid[piecePositionX + 1][piecePositionY + 2] != EMPTY) &&
  549.             (grid[piecePositionX + 1][piecePositionY + 2] != MOVING)) checker = true;

  550.         if ((grid[piecePositionX + 2][piecePositionY + 1] == MOVING) &&
  551.             (grid[piecePositionX + 1][piecePositionY + 1] != EMPTY) &&
  552.             (grid[piecePositionX + 1][piecePositionY + 1] != MOVING)) checker = true;

  553.         if ((grid[piecePositionX + 2][piecePositionY + 2] == MOVING) &&
  554.             (grid[piecePositionX + 2][piecePositionY + 1] != EMPTY) &&
  555.             (grid[piecePositionX + 2][piecePositionY + 1] != MOVING)) checker = true;

  556.         if ((grid[piecePositionX + 1][piecePositionY + 2] == MOVING) &&
  557.             (grid[piecePositionX + 2][piecePositionY + 2] != EMPTY) &&
  558.             (grid[piecePositionX + 2][piecePositionY + 2] != MOVING)) checker = true;

  559.         if (!checker)
  560.         {
  561.             aux = piece[0][0];
  562.             piece[0][0] = piece[3][0];
  563.             piece[3][0] = piece[3][3];
  564.             piece[3][3] = piece[0][3];
  565.             piece[0][3] = aux;

  566.             aux = piece[1][0];
  567.             piece[1][0] = piece[3][1];
  568.             piece[3][1] = piece[2][3];
  569.             piece[2][3] = piece[0][2];
  570.             piece[0][2] = aux;

  571.             aux = piece[2][0];
  572.             piece[2][0] = piece[3][2];
  573.             piece[3][2] = piece[1][3];
  574.             piece[1][3] = piece[0][1];
  575.             piece[0][1] = aux;

  576.             aux = piece[1][1];
  577.             piece[1][1] = piece[2][1];
  578.             piece[2][1] = piece[2][2];
  579.             piece[2][2] = piece[1][2];
  580.             piece[1][2] = aux;
  581.         }

  582.         for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
  583.         {
  584.             for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
  585.             {
  586.                 if (grid[i][j] == MOVING)
  587.                 {
  588.                     grid[i][j] = EMPTY;
  589.                 }
  590.             }
  591.         }

  592.         for (int i = piecePositionX; i < piecePositionX + 4; i++)
  593.         {
  594.             for (int j = piecePositionY; j < piecePositionY + 4; j++)
  595.             {
  596.                 if (piece[i - piecePositionX][j - piecePositionY] == MOVING)
  597.                 {
  598.                     grid[i][j] = MOVING;
  599.                 }
  600.             }
  601.         }

  602.         return true;
  603.     }

  604.     return false;
  605. }

  606. static void CheckDetection(bool *detection)
  607. {
  608.     for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
  609.     {
  610.         for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
  611.         {
  612.             if ((grid[i][j] == MOVING) && ((grid[i][j+1] == FULL) || (grid[i][j+1] == BLOCK))) *detection = true;
  613.         }
  614.     }
  615. }

  616. static void CheckCompletion(bool *lineToDelete)
  617. {
  618.     int calculator = 0;

  619.     for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
  620.     {
  621.         calculator = 0;
  622.         for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
  623.         {
  624.             // Count each square of the line
  625.             if (grid[i][j] == FULL)
  626.             {
  627.                 calculator++;
  628.             }

  629.             // Check if we completed the whole line
  630.             if (calculator == GRID_HORIZONTAL_SIZE - 2)
  631.             {
  632.                 *lineToDelete = true;
  633.                 calculator = 0;
  634.                 // points++;

  635.                 // Mark the completed line
  636.                 for (int z = 1; z < GRID_HORIZONTAL_SIZE - 1; z++)
  637.                 {
  638.                     grid[z][j] = FADING;
  639.                 }
  640.             }
  641.         }
  642.     }
  643. }

  644. static void DeleteCompleteLines()
  645. {
  646.     // Erase the completed line
  647.     for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
  648.     {
  649.         while (grid[1][j] == FADING)
  650.         {
  651.             for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
  652.             {
  653.                 grid[i][j] = EMPTY;
  654.             }

  655.             for (int j2 = j-1; j2 >= 0; j2--)
  656.             {
  657.                 for (int i2 = 1; i2 < GRID_HORIZONTAL_SIZE - 1; i2++)
  658.                 {
  659.                     if (grid[i2][j2] == FULL)
  660.                     {
  661.                         grid[i2][j2+1] = FULL;
  662.                         grid[i2][j2] = EMPTY;
  663.                     }
  664.                     else if (grid[i2][j2] == FADING)
  665.                     {
  666.                         grid[i2][j2+1] = FADING;
  667.                         grid[i2][j2] = EMPTY;
  668.                     }
  669.                 }
  670.             }
  671.         }
  672.     }
  673. }
复制代码
效果如图:


如有需要,可以在此下载exe文件:



Part 3:官网安装包学习

Raylib官网有一个安装包,内含有一个配置好了Raylib5.0的MinGw64,一个Notepad++,还有一大堆官网上有的示例程序源代码。就像官网上说的那样:raylib 不提供典型的 API 文档或大量教程。该库被设计为简约主义,只需从包含所有必需功能的备忘单和大量示例中学习,即可了解如何使用该功能。学习编码的最好方法是阅读代码。安装包下载时还有一个坑:英文页面上有显示让你付钱的字,不要害怕,开了翻译才发现只是说可以自愿捐款。如果仔细看会发现网站建设者狡猾地写了一个非常小的链接说:不,带我去下载。链接如下:安装包下载直达:安装包
安装包下载下来运行后是一个Raylib编的界面,但它可以下载文件,每次运行时窗口的背景颜色是随机的。额,用Raylib编的Raylib安装包会默认把上面Raylib的文件下载到C:\Raylib里面去。(好像改不了路径ToT)
下载时进度条上方还有一个小小的走迷宫的3D游戏,WSAD键操纵角色前后左右,↑↓←→键操纵视角,在迷宫的各个角落里有分散开的文件样的类似金币的东西要找,总共十个,在所有文件下载完成前在迷宫里找到这些文件就算赢。(我只找到3个就晕了)还是很有创意的设计。可以让你在安装时少些无聊。(就很银杏化AwA)
回归正题,安装完后找到C:\raylib文件夹里有README.txt的详细说明(暂且不管)。npp文件夹是Notepad++的目录,是个加强版编辑器(暂且不管);进入C:\raylib\raylib文件夹,重点来了:
重点是examples文件夹:

双击运行两个批处理文件后需要耐心等待一下,打开上面的文件加就会看到每个源代码下方都有一个对应的可执行文件,全部在上面几个文件夹里。
下面展示各个示例代码编译后的效果(均为Raylib&c++编写):

还有3D的Hello world!

学习编码的最好方法是阅读代码。你可以查看想学习的3D效果的源代码,看看他是怎么编出来的。不是很酷吗?
下一帖,我将教大家基础框架和绘图知识!(ง •_•)ง

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×

8

主题

39

回帖

852

积分

管理员

积分
852
 楼主| 发表于 2024-7-18 13:03:18 | 显示全部楼层
哈哈哈哈哈哈哈哈哈哈上传附件给了190金钱+190经验+190贡献哈哈哈哈哈哈哈
回复

使用道具 举报

8

主题

39

回帖

852

积分

管理员

积分
852
 楼主| 发表于 2024-7-18 13:06:58 | 显示全部楼层
好肝啊啊啊啊不知道下一期什么时候鉼出来
回复

使用道具 举报

8

主题

39

回帖

852

积分

管理员

积分
852
 楼主| 发表于 2024-7-20 12:02:56 | 显示全部楼层
@_CX_ 看我新帖
回复

使用道具 举报

8

主题

39

回帖

852

积分

管理员

积分
852
 楼主| 发表于 2024-11-27 22:32:46 | 显示全部楼层
@ZSJ20110121 see it

看中间那个俄罗斯方块,源码可以拿去参考和改价进
回复

使用道具 举报

8

主题

39

回帖

852

积分

管理员

积分
852
 楼主| 发表于 2024-12-1 15:42:46 | 显示全部楼层
@ZSJ20110121
回复

使用道具 举报

8

主题

39

回帖

852

积分

管理员

积分
852
 楼主| 发表于 2024-12-1 15:43:26 | 显示全部楼层
@ZSJ20110121
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

站点统计|Archiver|手机版|小黑屋|CZLJ

GMT+8, 2025-1-29 06:19 , Processed in 0.077905 second(s), 20 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表