From 4ab28fffb42bc3104bca48166ea4d7712450852d Mon Sep 17 00:00:00 2001 From: Gianni Alessandroni <45824238+NotManyIdeasDev@users.noreply.github.com> Date: Mon, 10 May 2021 20:16:12 +0200 Subject: [PATCH] Added smooth pixel-perfect camera example + Small typo fix in examples_template.c (#1760) * Typo fix Changed "bsasic" to "basic" in the comments. * Added pixel-perfect camera example Added pixel-perfect camera example, both the .c file and the cover .png image. The example works with any resolution you want, as long as the ratio stays the same (ex. 16:9, 4:3) ecc. * Fixed Typecasts Fixed compiler errors (implicit conversions) * Precomputed rectangles, time-based movement and whitespace fix Moved the source and destination rectangles for the renderTexture into their own variables, modified the animation to be time-based instead of frame-based, fixed the bug with whitespaces. * Fixed spacing and added more consistency with sinf() and cosf() * Fixed *= operator spacing --- .../core/core_2d_camera_smooth_pixelperfect.c | 136 ++++++++++++++++++ .../core_2d_camera_smooth_pixelperfect.png | Bin 0 -> 6365 bytes examples/examples_template.c | 4 +- 3 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 examples/core/core_2d_camera_smooth_pixelperfect.c create mode 100644 examples/core/core_2d_camera_smooth_pixelperfect.png diff --git a/examples/core/core_2d_camera_smooth_pixelperfect.c b/examples/core/core_2d_camera_smooth_pixelperfect.c new file mode 100644 index 00000000..3594c4ab --- /dev/null +++ b/examples/core/core_2d_camera_smooth_pixelperfect.c @@ -0,0 +1,136 @@ +/******************************************************************************************* +* +* raylib [core] example - smooth pixel-perfect camera +* +* This example has been created using raylib 3.7 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Example contributed by Giancamillo Alessandroni ([discord]NotManyIdeas#9972 - [github]NotManyIdeasDev) and +* reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2021 Giancamillo Alessandroni (NotManyIdeas#9972) and Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" +#include + +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + const int virualScreenWidth = 160; + const int virtualScreenHeight = 90; + + const float virtualRatio = (float)screenWidth/(float)virualScreenWidth; + + InitWindow(screenWidth, screenHeight, "raylib [core] example - smooth pixel-perfect camera"); + + Camera2D worldSpaceCamera = { 0 }; // Game world camera + worldSpaceCamera.zoom = 1.0f; + + Camera2D screenSpaceCamera = { 0 }; //Smoothing camera + screenSpaceCamera.zoom = 1.0f; + + RenderTexture2D renderTexture = LoadRenderTexture(virualScreenWidth, virtualScreenHeight); //This is where we'll draw all our objects. + + Rectangle firstRectangle = { 70.0f, 35.0f, 20.0f, 20.0f }; + Rectangle secondRectangle = { 90.0f, 55.0f, 30.0f, 10.0f }; + Rectangle thirdRectangle = { 80.0f, 65.0f, 15.0f, 25.0f }; + + //The renderTexture's height is flipped (in the source Rectangle), due to OpenGL reasons. + Rectangle renderTextureSource = { 0.0f, 0.0f, (float)renderTexture.texture.width, (float)-renderTexture.texture.height }; + Rectangle renderTextureDest = { -virtualRatio, -virtualRatio, screenWidth + (virtualRatio*2), screenHeight + (virtualRatio*2) }; + + Vector2 origin = { 0.0f, 0.0f }; + + float rotation = 0.0f; + float degreesPerSecond = 60.0f; + + float cameraX = 0.0f; + float cameraY = 0.0f; + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + rotation += degreesPerSecond*GetFrameTime(); // Rotate the rectangles. + + // Make the camera move to demonstrate the effect. + cameraX = (sinf(GetTime())*50.0f) - 10.0f; + cameraY = cosf(GetTime())*30.0f; + + // Set the camera's target to the values computed above. + screenSpaceCamera.target = (Vector2){ cameraX, cameraY }; + + // Round worldCamera's X, keep the decimals on screenSpaceCamera. + if (screenSpaceCamera.target.x >= 1 || screenSpaceCamera.target.x <= -1) + { + worldSpaceCamera.target.x = (int)screenSpaceCamera.target.x; + screenSpaceCamera.target.x -= worldSpaceCamera.target.x; + screenSpaceCamera.target.x *= virtualRatio; + } + + // Round worldCamera's Y, keep the decimals on screenSpaceCamera. + if (screenSpaceCamera.target.y >= 1 || screenSpaceCamera.target.y <= -1) + { + worldSpaceCamera.target.y = (int)screenSpaceCamera.target.y; + screenSpaceCamera.target.y -= worldSpaceCamera.target.y; + screenSpaceCamera.target.y *= virtualRatio; + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + ClearBackground(RED); // This is for debug purposes. If you see red, then you've probably done something wrong. + + BeginTextureMode(renderTexture); + BeginMode2D(worldSpaceCamera); + ClearBackground(RAYWHITE); // This is the color you should see as background color. + + // Draw the rectangles + DrawRectanglePro(firstRectangle, origin, rotation, BLACK); + DrawRectanglePro(secondRectangle, origin, -rotation, RED); + DrawRectanglePro(thirdRectangle, origin, rotation + 45.0f, BLUE); + + EndMode2D(); + EndTextureMode(); + + BeginMode2D(screenSpaceCamera); + + // Draw the render texture with an offset of 1 worldSpace unit/pixel, so that the content behind the renderTexture is not shown. + DrawTexturePro( + renderTexture.texture, + renderTextureSource, + renderTextureDest, + origin, + 0.0f, + WHITE + ); + + EndMode2D(); + + //Debug info + DrawText("Screen resolution: 800x450", 5, 0, 20, DARKBLUE); + DrawText("World resolution: 160x90", 5, 20, 20, DARKGREEN); + DrawFPS(screenWidth - 75, 0); + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadRenderTexture(renderTexture); // RenderTexture unloading + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/core/core_2d_camera_smooth_pixelperfect.png b/examples/core/core_2d_camera_smooth_pixelperfect.png new file mode 100644 index 0000000000000000000000000000000000000000..aeac7944688c34c2a38b299721cf90915fb22084 GIT binary patch literal 6365 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 - Lower case filename, words separated by underscore, @@ -95,4 +95,4 @@ int main() //-------------------------------------------------------------------------------------- return 0; -} \ No newline at end of file +}