diff --git a/BUILD_cn.md b/BUILD_cn.md index b9d9c456..48743d96 100644 --- a/BUILD_cn.md +++ b/BUILD_cn.md @@ -15,5 +15,41 @@ # Linux 步骤: - - 安装 gcc 和 qt5 - - 使用qtcreator打开Red_Panda_CPP.pro文件 \ No newline at end of file + - 安装 gcc 和 qt5开发相关包 + - 使用qtcreator打开Red_Panda_CPP.pro文件 + + +## Ubuntu + +### 1.安装编译器 + +```text +apt install gcc g++ make gdb gdbserver +``` + +### 2.安装QT5和依赖包 + +```text +apt install qtbase5-dev qttools5-dev-tools libicu-dev libqt5svg5-dev git qterminal +``` + +### 3.下载源码 + +``` +git clone https://gitee.com/royqh1979/RedPanda-CPP.git +``` + +### 4.编译 + +``` +cd cd RedPanda-CPP/ +qmake Red_Panda_CPP.pro +make -j8 +sudo make install +``` + +### 5.运行 + +``` +RedPandaIDE +``` \ No newline at end of file diff --git a/NEWS.md b/NEWS.md index 88056b1f..7f7ec521 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,8 +2,9 @@ Red Panda C++ Version 1.2 - enhancement: Portuguese Translation ( Thanks for crcpucmg@github) - fix: files in network drive is opened in readonly mode - - change: organization structure of templates - - enhancement: create template + - change: reorganization templates in subfolders + - enhancement: create template from project + - fix: can't correctly set project icon Red Panda C++ Version 1.1.6 diff --git a/RedPandaIDE/project.cpp b/RedPandaIDE/project.cpp index c61c8b49..0bb10102 100644 --- a/RedPandaIDE/project.cpp +++ b/RedPandaIDE/project.cpp @@ -900,8 +900,8 @@ bool Project::saveAsTemplate(const QString &templateFolder, if (mOptions.execEncoding!=ENCODING_SYSTEM_DEFAULT) ini->SetValue("Project","ExecEncoding", mOptions.execEncoding); - if (!mOptions.staticLink) - ini->SetBoolValue("Project", "StaticLink",false); +// if (!mOptions.staticLink) +// ini->SetBoolValue("Project", "StaticLink",false); if (!mOptions.addCharset) ini->SetBoolValue("Project", "AddCharset",false); if (mOptions.encoding!=ENCODING_AUTO_DETECT) diff --git a/RedPandaIDE/settingsdialog/projectgeneralwidget.cpp b/RedPandaIDE/settingsdialog/projectgeneralwidget.cpp index 45bb7bc4..8276127a 100644 --- a/RedPandaIDE/settingsdialog/projectgeneralwidget.cpp +++ b/RedPandaIDE/settingsdialog/projectgeneralwidget.cpp @@ -104,9 +104,10 @@ void ProjectGeneralWidget::doSave() project->options().isCpp = ui->cbDefaultCpp->isChecked(); project->options().supportXPThemes = ui->cbSupportXPTheme->isChecked(); + qDebug()<<"iconpath"<= QT_VERSION_CHECK(5,15,0) - || !ui->lbIcon->pixmap(Qt::ReturnByValue).isNull()) { + || ui->lbIcon->pixmap(Qt::ReturnByValue).isNull()) { #else || !ui->lbIcon->pixmap() || ui->lbIcon->pixmap()->isNull()) { #endif @@ -130,7 +131,7 @@ void ProjectGeneralWidget::doSave() ui->lbIcon->pixmap()->save(iconPath,"ico"); #endif } else - QFile::copy(mIconPath, iconPath); + copyFile(mIconPath, iconPath,true); project->options().icon = iconPath; mIconPath = iconPath; refreshIcon(); @@ -148,7 +149,6 @@ void ProjectGeneralWidget::on_btnBrowse_clicked() tr("Image Files (*.ico *.png *.jpg)")); if (!fileName.isEmpty()) { mIconPath = fileName; - QPixmap icon(mIconPath); refreshIcon(); setSettingsChanged(); } diff --git a/windows/templates/sweepminer/app.ico b/windows/templates/sweepminer/app.ico new file mode 100644 index 00000000..5a076782 Binary files /dev/null and b/windows/templates/sweepminer/app.ico differ diff --git a/windows/templates/sweepminer/info.template b/windows/templates/sweepminer/info.template new file mode 100644 index 00000000..1a942512 --- /dev/null +++ b/windows/templates/sweepminer/info.template @@ -0,0 +1,22 @@ +[Template] +Ver = 3 +Name = Sweepminer +Name[zh_CN] = 鎵浄 +Category = Game +Category[zh_CN] = 娓告垙 +Description = Classic sweepminer game by raylib +Description[zh_CN] = 浣跨敤raylib缂栧啓鐨勭粡鍏告壂闆锋父鎴 +Icon = app.ico + + +[Project] +Type = 1 +Linker = -lraylib -lopengl32 -lgdi32 -lwinmm +IsCpp = true +ExecEncoding = UTF-8 +UnitCount = 1 + + +[Unit0] +C = main.c +CName = main.c diff --git a/windows/templates/sweepminer/main.c b/windows/templates/sweepminer/main.c new file mode 100644 index 00000000..e4e5495c --- /dev/null +++ b/windows/templates/sweepminer/main.c @@ -0,0 +1,324 @@ +/******************************************************************************************* +* +* raylib - classic game: arkanoid +* +* 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) +* +* Icon from https://www.flaticon.com/free-icon/arkanoid_2927802 +********************************************************************************************/ + +#include + +#include +#include +#include +#include + +#if defined(PLATFORM_WEB) +#include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define PLAYER_MAX_LIFE 5 +#define LINES_OF_BRICKS 5 +#define BRICKS_PER_LINE 20 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef enum GameScreen { LOGO, TITLE, GAMEPLAY, ENDING } GameScreen; + +typedef struct Player { + Vector2 position; + Vector2 size; + int life; +} Player; + +typedef struct Ball { + Vector2 position; + Vector2 speed; + int radius; + bool active; +} Ball; + +typedef struct Brick { + Vector2 position; + bool active; +} Brick; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static const int screenWidth = 800; +static const int screenHeight = 450; + +static bool gameOver = false; +static bool pause = false; + +static Player player = { 0 }; +static Ball ball = { 0 }; +static Brick brick[LINES_OF_BRICKS][BRICKS_PER_LINE] = { 0 }; +static Vector2 brickSize = { 0 }; + +//------------------------------------------------------------------------------------ +// 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) + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization (Note windowTitle is unused on Android) + //--------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "classic game: arkanoid"); + + 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; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +void InitGame(void) +{ + brickSize = (Vector2){ GetScreenWidth()/BRICKS_PER_LINE, 40 }; + + // Initialize player + player.position = (Vector2){ screenWidth/2, screenHeight*7/8 }; + player.size = (Vector2){ screenWidth/10, 20 }; + player.life = PLAYER_MAX_LIFE; + + // Initialize ball + ball.position = (Vector2){ screenWidth/2, screenHeight*7/8 - 30 }; + ball.speed = (Vector2){ 0, 0 }; + ball.radius = 7; + ball.active = false; + + // Initialize bricks + int initialDownPosition = 50; + + for (int i = 0; i < LINES_OF_BRICKS; i++) + { + for (int j = 0; j < BRICKS_PER_LINE; j++) + { + brick[i][j].position = (Vector2){ j*brickSize.x + brickSize.x/2, i*brickSize.y + initialDownPosition }; + brick[i][j].active = true; + } + } +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + // Player movement logic + if (IsKeyDown(KEY_LEFT)) player.position.x -= 5; + if ((player.position.x - player.size.x/2) <= 0) player.position.x = player.size.x/2; + if (IsKeyDown(KEY_RIGHT)) player.position.x += 5; + if ((player.position.x + player.size.x/2) >= screenWidth) player.position.x = screenWidth - player.size.x/2; + + // Ball launching logic + if (!ball.active) + { + if (IsKeyPressed(KEY_SPACE)) + { + ball.active = true; + ball.speed = (Vector2){ 0, -5 }; + } + } + + // Ball movement logic + if (ball.active) + { + ball.position.x += ball.speed.x; + ball.position.y += ball.speed.y; + } + else + { + ball.position = (Vector2){ player.position.x, screenHeight*7/8 - 30 }; + } + + // Collision logic: ball vs walls + if (((ball.position.x + ball.radius) >= screenWidth) || ((ball.position.x - ball.radius) <= 0)) ball.speed.x *= -1; + if ((ball.position.y - ball.radius) <= 0) ball.speed.y *= -1; + if ((ball.position.y + ball.radius) >= screenHeight) + { + ball.speed = (Vector2){ 0, 0 }; + ball.active = false; + + player.life--; + } + + // Collision logic: ball vs player + if (CheckCollisionCircleRec(ball.position, ball.radius, + (Rectangle){ player.position.x - player.size.x/2, player.position.y - player.size.y/2, player.size.x, player.size.y})) + { + if (ball.speed.y > 0) + { + ball.speed.y *= -1; + ball.speed.x = (ball.position.x - player.position.x)/(player.size.x/2)*5; + } + } + + // Collision logic: ball vs bricks + for (int i = 0; i < LINES_OF_BRICKS; i++) + { + for (int j = 0; j < BRICKS_PER_LINE; j++) + { + if (brick[i][j].active) + { + // Hit below + if (((ball.position.y - ball.radius) <= (brick[i][j].position.y + brickSize.y/2)) && + ((ball.position.y - ball.radius) > (brick[i][j].position.y + brickSize.y/2 + ball.speed.y)) && + ((fabs(ball.position.x - brick[i][j].position.x)) < (brickSize.x/2 + ball.radius*2/3)) && (ball.speed.y < 0)) + { + brick[i][j].active = false; + ball.speed.y *= -1; + } + // Hit above + else if (((ball.position.y + ball.radius) >= (brick[i][j].position.y - brickSize.y/2)) && + ((ball.position.y + ball.radius) < (brick[i][j].position.y - brickSize.y/2 + ball.speed.y)) && + ((fabs(ball.position.x - brick[i][j].position.x)) < (brickSize.x/2 + ball.radius*2/3)) && (ball.speed.y > 0)) + { + brick[i][j].active = false; + ball.speed.y *= -1; + } + // Hit left + else if (((ball.position.x + ball.radius) >= (brick[i][j].position.x - brickSize.x/2)) && + ((ball.position.x + ball.radius) < (brick[i][j].position.x - brickSize.x/2 + ball.speed.x)) && + ((fabs(ball.position.y - brick[i][j].position.y)) < (brickSize.y/2 + ball.radius*2/3)) && (ball.speed.x > 0)) + { + brick[i][j].active = false; + ball.speed.x *= -1; + } + // Hit right + else if (((ball.position.x - ball.radius) <= (brick[i][j].position.x + brickSize.x/2)) && + ((ball.position.x - ball.radius) > (brick[i][j].position.x + brickSize.x/2 + ball.speed.x)) && + ((fabs(ball.position.y - brick[i][j].position.y)) < (brickSize.y/2 + ball.radius*2/3)) && (ball.speed.x < 0)) + { + brick[i][j].active = false; + ball.speed.x *= -1; + } + } + } + } + + // Game over logic + if (player.life <= 0) gameOver = true; + else + { + gameOver = true; + + for (int i = 0; i < LINES_OF_BRICKS; i++) + { + for (int j = 0; j < BRICKS_PER_LINE; j++) + { + if (brick[i][j].active) gameOver = false; + } + } + } + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + // Draw player bar + DrawRectangle(player.position.x - player.size.x/2, player.position.y - player.size.y/2, player.size.x, player.size.y, BLACK); + + // Draw player lives + for (int i = 0; i < player.life; i++) DrawRectangle(20 + 40*i, screenHeight - 30, 35, 10, LIGHTGRAY); + + // Draw ball + DrawCircleV(ball.position, ball.radius, MAROON); + + // Draw bricks + for (int i = 0; i < LINES_OF_BRICKS; i++) + { + for (int j = 0; j < BRICKS_PER_LINE; j++) + { + if (brick[i][j].active) + { + if ((i + j) % 2 == 0) DrawRectangle(brick[i][j].position.x - brickSize.x/2, brick[i][j].position.y - brickSize.y/2, brickSize.x, brickSize.y, GRAY); + else DrawRectangle(brick[i][j].position.x - brickSize.x/2, brick[i][j].position.y - brickSize.y/2, brickSize.x, brickSize.y, DARKGRAY); + } + } + } + + 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(); +}