|
(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开发环境已经配置完成了!
- /*******************************************************************************************
- *
- * raylib - classic game: tetris
- *
- * Sample game developed by Marc Palau and Ramon Santamaria
- *
- * This game has been created using raylib v1.3 (www.raylib.com)
- * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
- *
- * Copyright (c) 2015 Ramon Santamaria (@raysan5)
- *
- ********************************************************************************************/
- #include "raylib.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <math.h>
- #if defined(PLATFORM_WEB)
- #include <emscripten/emscripten.h>
- #endif
- //----------------------------------------------------------------------------------
- // Some Defines
- //----------------------------------------------------------------------------------
- #define SQUARE_SIZE 20
- #define GRID_HORIZONTAL_SIZE 12
- #define GRID_VERTICAL_SIZE 20
- #define LATERAL_SPEED 10
- #define TURNING_SPEED 12
- #define FAST_FALL_AWAIT_COUNTER 30
- #define FADING_TIME 33
- //----------------------------------------------------------------------------------
- // Types and Structures Definition
- //----------------------------------------------------------------------------------
- typedef enum GridSquare { EMPTY, MOVING, FULL, BLOCK, FADING } GridSquare;
- //------------------------------------------------------------------------------------
- // Global Variables Declaration
- //------------------------------------------------------------------------------------
- static const int screenWidth = 800;
- static const int screenHeight = 450;
- static bool gameOver = false;
- static bool pause = false;
- // Matrices
- static GridSquare grid [GRID_HORIZONTAL_SIZE][GRID_VERTICAL_SIZE];
- static GridSquare piece [4][4];
- static GridSquare incomingPiece [4][4];
- // Theese variables keep track of the active piece position
- static int piecePositionX = 0;
- static int piecePositionY = 0;
- // Game parameters
- static Color fadingColor;
- //static int fallingSpeed; // In frames
- static bool beginPlay = true; // This var is only true at the begining of the game, used for the first matrix creations
- static bool pieceActive = false;
- static bool detection = false;
- static bool lineToDelete = false;
- // Statistics
- static int level = 1;
- static int lines = 0;
- // Counters
- static int gravityMovementCounter = 0;
- static int lateralMovementCounter = 0;
- static int turnMovementCounter = 0;
- static int fastFallMovementCounter = 0;
- static int fadeLineCounter = 0;
- // Based on level
- static int gravitySpeed = 30;
- //------------------------------------------------------------------------------------
- // Module Functions Declaration (local)
- //------------------------------------------------------------------------------------
- static void InitGame(void); // Initialize game
- static void UpdateGame(void); // Update game (one frame)
- static void DrawGame(void); // Draw game (one frame)
- static void UnloadGame(void); // Unload game
- static void UpdateDrawFrame(void); // Update and Draw (one frame)
- // Additional module functions
- static bool Createpiece();
- static void GetRandompiece();
- static void ResolveFallingMovement(bool *detection, bool *pieceActive);
- static bool ResolveLateralMovement();
- static bool ResolveTurnMovement();
- static void CheckDetection(bool *detection);
- static void CheckCompletion(bool *lineToDelete);
- static void DeleteCompleteLines();
- //------------------------------------------------------------------------------------
- // Program main entry point
- //------------------------------------------------------------------------------------
- int main(void)
- {
- // Initialization (Note windowTitle is unused on Android)
- //---------------------------------------------------------
- InitWindow(screenWidth, screenHeight, "classic game: tetris");
- InitGame();
- #if defined(PLATFORM_WEB)
- emscripten_set_main_loop(UpdateDrawFrame, 60, 1);
- #else
- SetTargetFPS(60);
- //--------------------------------------------------------------------------------------
- // Main game loop
- while (!WindowShouldClose()) // Detect window close button or ESC key
- {
- // Update and Draw
- //----------------------------------------------------------------------------------
- UpdateDrawFrame();
- //----------------------------------------------------------------------------------
- }
- #endif
- // De-Initialization
- //--------------------------------------------------------------------------------------
- UnloadGame(); // Unload loaded data (textures, sounds, models...)
- CloseWindow(); // Close window and OpenGL context
- //--------------------------------------------------------------------------------------
- return 0;
- }
- //--------------------------------------------------------------------------------------
- // Game Module Functions Definition
- //--------------------------------------------------------------------------------------
- // Initialize game variables
- void InitGame(void)
- {
- // Initialize game statistics
- level = 1;
- lines = 0;
- fadingColor = GRAY;
- piecePositionX = 0;
- piecePositionY = 0;
- pause = false;
- beginPlay = true;
- pieceActive = false;
- detection = false;
- lineToDelete = false;
- // Counters
- gravityMovementCounter = 0;
- lateralMovementCounter = 0;
- turnMovementCounter = 0;
- fastFallMovementCounter = 0;
- fadeLineCounter = 0;
- gravitySpeed = 30;
- // Initialize grid matrices
- for (int i = 0; i < GRID_HORIZONTAL_SIZE; i++)
- {
- for (int j = 0; j < GRID_VERTICAL_SIZE; j++)
- {
- if ((j == GRID_VERTICAL_SIZE - 1) || (i == 0) || (i == GRID_HORIZONTAL_SIZE - 1)) grid[i][j] = BLOCK;
- else grid[i][j] = EMPTY;
- }
- }
- // Initialize incoming piece matrices
- for (int i = 0; i < 4; i++)
- {
- for (int j = 0; j< 4; j++)
- {
- incomingPiece[i][j] = EMPTY;
- }
- }
- }
- // Update game (one frame)
- void UpdateGame(void)
- {
- if (!gameOver)
- {
- if (IsKeyPressed('P')) pause = !pause;
- if (!pause)
- {
- if (!lineToDelete)
- {
- if (!pieceActive)
- {
- // Get another piece
- pieceActive = Createpiece();
- // We leave a little time before starting the fast falling down
- fastFallMovementCounter = 0;
- }
- else // Piece falling
- {
- // Counters update
- fastFallMovementCounter++;
- gravityMovementCounter++;
- lateralMovementCounter++;
- turnMovementCounter++;
- // We make sure to move if we've pressed the key this frame
- if (IsKeyPressed(KEY_LEFT) || IsKeyPressed(KEY_RIGHT)) lateralMovementCounter = LATERAL_SPEED;
- if (IsKeyPressed(KEY_UP)) turnMovementCounter = TURNING_SPEED;
- // Fall down
- if (IsKeyDown(KEY_DOWN) && (fastFallMovementCounter >= FAST_FALL_AWAIT_COUNTER))
- {
- // We make sure the piece is going to fall this frame
- gravityMovementCounter += gravitySpeed;
- }
- if (gravityMovementCounter >= gravitySpeed)
- {
- // Basic falling movement
- CheckDetection(&detection);
- // Check if the piece has collided with another piece or with the boundings
- ResolveFallingMovement(&detection, &pieceActive);
- // Check if we fullfilled a line and if so, erase the line and pull down the the lines above
- CheckCompletion(&lineToDelete);
- gravityMovementCounter = 0;
- }
- // Move laterally at player's will
- if (lateralMovementCounter >= LATERAL_SPEED)
- {
- // Update the lateral movement and if success, reset the lateral counter
- if (!ResolveLateralMovement()) lateralMovementCounter = 0;
- }
- // Turn the piece at player's will
- if (turnMovementCounter >= TURNING_SPEED)
- {
- // Update the turning movement and reset the turning counter
- if (ResolveTurnMovement()) turnMovementCounter = 0;
- }
- }
- // Game over logic
- for (int j = 0; j < 2; j++)
- {
- for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
- {
- if (grid[i][j] == FULL)
- {
- gameOver = true;
- }
- }
- }
- }
- else
- {
- // Animation when deleting lines
- fadeLineCounter++;
- if (fadeLineCounter%8 < 4) fadingColor = MAROON;
- else fadingColor = GRAY;
- if (fadeLineCounter >= FADING_TIME)
- {
- DeleteCompleteLines();
- fadeLineCounter = 0;
- lineToDelete = false;
- lines++;
- }
- }
- }
- }
- else
- {
- if (IsKeyPressed(KEY_ENTER))
- {
- InitGame();
- gameOver = false;
- }
- }
- }
- // Draw game (one frame)
- void DrawGame(void)
- {
- BeginDrawing();
- ClearBackground(RAYWHITE);
- if (!gameOver)
- {
- // Draw gameplay area
- Vector2 offset;
- offset.x = screenWidth/2 - (GRID_HORIZONTAL_SIZE*SQUARE_SIZE/2) - 50;
- offset.y = screenHeight/2 - ((GRID_VERTICAL_SIZE - 1)*SQUARE_SIZE/2) + SQUARE_SIZE*2;
- offset.y -= 50; // NOTE: Harcoded position!
- int controller = offset.x;
- for (int j = 0; j < GRID_VERTICAL_SIZE; j++)
- {
- for (int i = 0; i < GRID_HORIZONTAL_SIZE; i++)
- {
- // Draw each square of the grid
- if (grid[i][j] == EMPTY)
- {
- DrawLine(offset.x, offset.y, offset.x + SQUARE_SIZE, offset.y, LIGHTGRAY );
- DrawLine(offset.x, offset.y, offset.x, offset.y + SQUARE_SIZE, LIGHTGRAY );
- DrawLine(offset.x + SQUARE_SIZE, offset.y, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY );
- DrawLine(offset.x, offset.y + SQUARE_SIZE, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY );
- offset.x += SQUARE_SIZE;
- }
- else if (grid[i][j] == FULL)
- {
- DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, GRAY);
- offset.x += SQUARE_SIZE;
- }
- else if (grid[i][j] == MOVING)
- {
- DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, DARKGRAY);
- offset.x += SQUARE_SIZE;
- }
- else if (grid[i][j] == BLOCK)
- {
- DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, LIGHTGRAY);
- offset.x += SQUARE_SIZE;
- }
- else if (grid[i][j] == FADING)
- {
- DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, fadingColor);
- offset.x += SQUARE_SIZE;
- }
- }
- offset.x = controller;
- offset.y += SQUARE_SIZE;
- }
- // Draw incoming piece (hardcoded)
- offset.x = 500;
- offset.y = 45;
- int controler = offset.x;
- for (int j = 0; j < 4; j++)
- {
- for (int i = 0; i < 4; i++)
- {
- if (incomingPiece[i][j] == EMPTY)
- {
- DrawLine(offset.x, offset.y, offset.x + SQUARE_SIZE, offset.y, LIGHTGRAY );
- DrawLine(offset.x, offset.y, offset.x, offset.y + SQUARE_SIZE, LIGHTGRAY );
- DrawLine(offset.x + SQUARE_SIZE, offset.y, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY );
- DrawLine(offset.x, offset.y + SQUARE_SIZE, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY );
- offset.x += SQUARE_SIZE;
- }
- else if (incomingPiece[i][j] == MOVING)
- {
- DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, GRAY);
- offset.x += SQUARE_SIZE;
- }
- }
- offset.x = controler;
- offset.y += SQUARE_SIZE;
- }
- DrawText("INCOMING:", offset.x, offset.y - 100, 10, GRAY);
- DrawText(TextFormat("LINES: %04i", lines), offset.x, offset.y + 20, 10, GRAY);
- if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY);
- }
- else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY);
- EndDrawing();
- }
- // Unload game variables
- void UnloadGame(void)
- {
- // TODO: Unload all dynamic loaded data (textures, sounds, models...)
- }
- // Update and Draw (one frame)
- void UpdateDrawFrame(void)
- {
- UpdateGame();
- DrawGame();
- }
- //--------------------------------------------------------------------------------------
- // Additional module functions
- //--------------------------------------------------------------------------------------
- static bool Createpiece()
- {
- piecePositionX = (int)((GRID_HORIZONTAL_SIZE - 4)/2);
- piecePositionY = 0;
- // If the game is starting and you are going to create the first piece, we create an extra one
- if (beginPlay)
- {
- GetRandompiece();
- beginPlay = false;
- }
- // We assign the incoming piece to the actual piece
- for (int i = 0; i < 4; i++)
- {
- for (int j = 0; j< 4; j++)
- {
- piece[i][j] = incomingPiece[i][j];
- }
- }
- // We assign a random piece to the incoming one
- GetRandompiece();
- // Assign the piece to the grid
- for (int i = piecePositionX; i < piecePositionX + 4; i++)
- {
- for (int j = 0; j < 4; j++)
- {
- if (piece[i - (int)piecePositionX][j] == MOVING) grid[i][j] = MOVING;
- }
- }
- return true;
- }
- static void GetRandompiece()
- {
- int random = GetRandomValue(0, 6);
- for (int i = 0; i < 4; i++)
- {
- for (int j = 0; j < 4; j++)
- {
- incomingPiece[i][j] = EMPTY;
- }
- }
- switch (random)
- {
- case 0: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //Cube
- case 1: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //L
- case 2: { incomingPiece[1][2] = MOVING; incomingPiece[2][0] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; } break; //L inversa
- case 3: { incomingPiece[0][1] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //Recta
- case 4: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][1] = MOVING; } break; //Creu tallada
- case 5: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[3][2] = MOVING; } break; //S
- case 6: { incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //S inversa
- }
- }
- static void ResolveFallingMovement(bool *detection, bool *pieceActive)
- {
- // If we finished moving this piece, we stop it
- if (*detection)
- {
- for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
- {
- for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
- {
- if (grid[i][j] == MOVING)
- {
- grid[i][j] = FULL;
- *detection = false;
- *pieceActive = false;
- }
- }
- }
- }
- else // We move down the piece
- {
- for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
- {
- for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
- {
- if (grid[i][j] == MOVING)
- {
- grid[i][j+1] = MOVING;
- grid[i][j] = EMPTY;
- }
- }
- }
- piecePositionY++;
- }
- }
- static bool ResolveLateralMovement()
- {
- bool collision = false;
- // Piece movement
- if (IsKeyDown(KEY_LEFT)) // Move left
- {
- // Check if is possible to move to left
- for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
- {
- for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
- {
- if (grid[i][j] == MOVING)
- {
- // Check if we are touching the left wall or we have a full square at the left
- if ((i-1 == 0) || (grid[i-1][j] == FULL)) collision = true;
- }
- }
- }
- // If able, move left
- if (!collision)
- {
- for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
- {
- for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) // We check the matrix from left to right
- {
- // Move everything to the left
- if (grid[i][j] == MOVING)
- {
- grid[i-1][j] = MOVING;
- grid[i][j] = EMPTY;
- }
- }
- }
- piecePositionX--;
- }
- }
- else if (IsKeyDown(KEY_RIGHT)) // Move right
- {
- // Check if is possible to move to right
- for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
- {
- for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
- {
- if (grid[i][j] == MOVING)
- {
- // Check if we are touching the right wall or we have a full square at the right
- if ((i+1 == GRID_HORIZONTAL_SIZE - 1) || (grid[i+1][j] == FULL))
- {
- collision = true;
- }
- }
- }
- }
- // If able move right
- if (!collision)
- {
- for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
- {
- for (int i = GRID_HORIZONTAL_SIZE - 1; i >= 1; i--) // We check the matrix from right to left
- {
- // Move everything to the right
- if (grid[i][j] == MOVING)
- {
- grid[i+1][j] = MOVING;
- grid[i][j] = EMPTY;
- }
- }
- }
- piecePositionX++;
- }
- }
- return collision;
- }
- static bool ResolveTurnMovement()
- {
- // Input for turning the piece
- if (IsKeyDown(KEY_UP))
- {
- GridSquare aux;
- bool checker = false;
- // Check all turning possibilities
- if ((grid[piecePositionX + 3][piecePositionY] == MOVING) &&
- (grid[piecePositionX][piecePositionY] != EMPTY) &&
- (grid[piecePositionX][piecePositionY] != MOVING)) checker = true;
- if ((grid[piecePositionX + 3][piecePositionY + 3] == MOVING) &&
- (grid[piecePositionX + 3][piecePositionY] != EMPTY) &&
- (grid[piecePositionX + 3][piecePositionY] != MOVING)) checker = true;
- if ((grid[piecePositionX][piecePositionY + 3] == MOVING) &&
- (grid[piecePositionX + 3][piecePositionY + 3] != EMPTY) &&
- (grid[piecePositionX + 3][piecePositionY + 3] != MOVING)) checker = true;
- if ((grid[piecePositionX][piecePositionY] == MOVING) &&
- (grid[piecePositionX][piecePositionY + 3] != EMPTY) &&
- (grid[piecePositionX][piecePositionY + 3] != MOVING)) checker = true;
- if ((grid[piecePositionX + 1][piecePositionY] == MOVING) &&
- (grid[piecePositionX][piecePositionY + 2] != EMPTY) &&
- (grid[piecePositionX][piecePositionY + 2] != MOVING)) checker = true;
- if ((grid[piecePositionX + 3][piecePositionY + 1] == MOVING) &&
- (grid[piecePositionX + 1][piecePositionY] != EMPTY) &&
- (grid[piecePositionX + 1][piecePositionY] != MOVING)) checker = true;
- if ((grid[piecePositionX + 2][piecePositionY + 3] == MOVING) &&
- (grid[piecePositionX + 3][piecePositionY + 1] != EMPTY) &&
- (grid[piecePositionX + 3][piecePositionY + 1] != MOVING)) checker = true;
- if ((grid[piecePositionX][piecePositionY + 2] == MOVING) &&
- (grid[piecePositionX + 2][piecePositionY + 3] != EMPTY) &&
- (grid[piecePositionX + 2][piecePositionY + 3] != MOVING)) checker = true;
- if ((grid[piecePositionX + 2][piecePositionY] == MOVING) &&
- (grid[piecePositionX][piecePositionY + 1] != EMPTY) &&
- (grid[piecePositionX][piecePositionY + 1] != MOVING)) checker = true;
- if ((grid[piecePositionX + 3][piecePositionY + 2] == MOVING) &&
- (grid[piecePositionX + 2][piecePositionY] != EMPTY) &&
- (grid[piecePositionX + 2][piecePositionY] != MOVING)) checker = true;
- if ((grid[piecePositionX + 1][piecePositionY + 3] == MOVING) &&
- (grid[piecePositionX + 3][piecePositionY + 2] != EMPTY) &&
- (grid[piecePositionX + 3][piecePositionY + 2] != MOVING)) checker = true;
- if ((grid[piecePositionX][piecePositionY + 1] == MOVING) &&
- (grid[piecePositionX + 1][piecePositionY + 3] != EMPTY) &&
- (grid[piecePositionX + 1][piecePositionY + 3] != MOVING)) checker = true;
- if ((grid[piecePositionX + 1][piecePositionY + 1] == MOVING) &&
- (grid[piecePositionX + 1][piecePositionY + 2] != EMPTY) &&
- (grid[piecePositionX + 1][piecePositionY + 2] != MOVING)) checker = true;
- if ((grid[piecePositionX + 2][piecePositionY + 1] == MOVING) &&
- (grid[piecePositionX + 1][piecePositionY + 1] != EMPTY) &&
- (grid[piecePositionX + 1][piecePositionY + 1] != MOVING)) checker = true;
- if ((grid[piecePositionX + 2][piecePositionY + 2] == MOVING) &&
- (grid[piecePositionX + 2][piecePositionY + 1] != EMPTY) &&
- (grid[piecePositionX + 2][piecePositionY + 1] != MOVING)) checker = true;
- if ((grid[piecePositionX + 1][piecePositionY + 2] == MOVING) &&
- (grid[piecePositionX + 2][piecePositionY + 2] != EMPTY) &&
- (grid[piecePositionX + 2][piecePositionY + 2] != MOVING)) checker = true;
- if (!checker)
- {
- aux = piece[0][0];
- piece[0][0] = piece[3][0];
- piece[3][0] = piece[3][3];
- piece[3][3] = piece[0][3];
- piece[0][3] = aux;
- aux = piece[1][0];
- piece[1][0] = piece[3][1];
- piece[3][1] = piece[2][3];
- piece[2][3] = piece[0][2];
- piece[0][2] = aux;
- aux = piece[2][0];
- piece[2][0] = piece[3][2];
- piece[3][2] = piece[1][3];
- piece[1][3] = piece[0][1];
- piece[0][1] = aux;
- aux = piece[1][1];
- piece[1][1] = piece[2][1];
- piece[2][1] = piece[2][2];
- piece[2][2] = piece[1][2];
- piece[1][2] = aux;
- }
- for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
- {
- for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
- {
- if (grid[i][j] == MOVING)
- {
- grid[i][j] = EMPTY;
- }
- }
- }
- for (int i = piecePositionX; i < piecePositionX + 4; i++)
- {
- for (int j = piecePositionY; j < piecePositionY + 4; j++)
- {
- if (piece[i - piecePositionX][j - piecePositionY] == MOVING)
- {
- grid[i][j] = MOVING;
- }
- }
- }
- return true;
- }
- return false;
- }
- static void CheckDetection(bool *detection)
- {
- for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
- {
- for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
- {
- if ((grid[i][j] == MOVING) && ((grid[i][j+1] == FULL) || (grid[i][j+1] == BLOCK))) *detection = true;
- }
- }
- }
- static void CheckCompletion(bool *lineToDelete)
- {
- int calculator = 0;
- for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
- {
- calculator = 0;
- for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
- {
- // Count each square of the line
- if (grid[i][j] == FULL)
- {
- calculator++;
- }
- // Check if we completed the whole line
- if (calculator == GRID_HORIZONTAL_SIZE - 2)
- {
- *lineToDelete = true;
- calculator = 0;
- // points++;
- // Mark the completed line
- for (int z = 1; z < GRID_HORIZONTAL_SIZE - 1; z++)
- {
- grid[z][j] = FADING;
- }
- }
- }
- }
- }
- static void DeleteCompleteLines()
- {
- // Erase the completed line
- for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
- {
- while (grid[1][j] == FADING)
- {
- for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
- {
- grid[i][j] = EMPTY;
- }
- for (int j2 = j-1; j2 >= 0; j2--)
- {
- for (int i2 = 1; i2 < GRID_HORIZONTAL_SIZE - 1; i2++)
- {
- if (grid[i2][j2] == FULL)
- {
- grid[i2][j2+1] = FULL;
- grid[i2][j2] = EMPTY;
- }
- else if (grid[i2][j2] == FADING)
- {
- grid[i2][j2+1] = FADING;
- grid[i2][j2] = EMPTY;
- }
- }
- }
- }
- }
- }
复制代码效果如图:
如有需要,可以在此下载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效果的源代码,看看他是怎么编出来的。不是很酷吗?
下一帖,我将教大家基础框架和绘图知识!(ง •_•)ง |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|