Hi @Daniel1985
I am sorry for the delay. Thank you so much for the code. It’s a pleasure to look at it.
I’ve played around with it and managed to make it work with a texture too.
It probably needs more attention to be generalized. Here is the new code (I am using SDL2_Image library, note the include statements, but it should work with BMP image).
I’ll be happy if you have time to look at it and let me know your opinion.
#include <stdio.h>
#include <string>
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
using namespace std;
#define WINDOW_WIDTH (800)
#define WINDOW_HEIGHT (600)
SDL_Window* pWindow = nullptr;
SDL_Renderer* pRenderer = nullptr;
SDL_Rect Rects[4] = {0};
//the 4th rect will hold the image
SDL_Surface* tempSurface = IMG_Load("assets/image.png");
SDL_Texture* tex = NULL;
SDL_Rect srcRect = {306, 102, WINDOW_WIDTH/2, WINDOW_HEIGHT/2};
SDL_Rect RectMouse = {0, 0, 0, 0};
SDL_Color RectColors[3] =
{
{25, 255, 90, 255},
{25, 150, 255, 255},
{255, 100, 25, 255},
};
double OldTime = 0.0;
double NewTime = 0.0;
double DeltaTime = 0.0;
float Border = 50.0f;
bool Running = true;
bool InitSDL()
{
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("Error: SDL could not initialize! %s\n", SDL_GetError());
return false;
}
pWindow = SDL_CreateWindow("SDL clipping", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN);
if(!pWindow)
{
printf("Error: SDL window could not be created! %s\n", SDL_GetError());
return false;
}
pRenderer = SDL_CreateRenderer(pWindow, -1, SDL_RENDERER_ACCELERATED);
if(!pRenderer)
{
printf("Error: SDL renderer could not be created! %s\n", SDL_GetError());
return false;
}
tex = SDL_CreateTextureFromSurface(pRenderer, tempSurface);
if(tex == NULL){
cout << "No texture loaded\n";
}
if (tempSurface == NULL){
cout << "No surface created\n";
}
SDL_FreeSurface(tempSurface); //can't be outside of a function? ***************
SDL_SetRenderDrawColor(pRenderer, 0, 0, 0, 255);
SDL_SetRenderDrawBlendMode(pRenderer, SDL_BLENDMODE_BLEND);
SDL_RenderClear(pRenderer);
SDL_RenderPresent(pRenderer);
return true;
}
void DeinitSDL()
{
SDL_DestroyRenderer(pRenderer);
SDL_DestroyWindow(pWindow);
SDL_Quit();
}
void InitAssets()
{
Rects[0] = {0, 0, WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2};
Rects[1] = {WINDOW_WIDTH / 2, 0, WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2};
Rects[2] = {0, WINDOW_HEIGHT / 2, WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2};
Rects[3] = {WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2, WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2}; //image
RectMouse = {0, 0, 350, 250};
}
void HandleEvents()
{
SDL_Event Event = {0};
while(SDL_PollEvent(&Event))
{
switch(Event.type)
{
case SDL_QUIT:
{
Running = false;
break;
}
default:
break;
}
}
}
void Update()
{
NewTime = (double)SDL_GetTicks();
DeltaTime = (NewTime - OldTime) * 0.001;
OldTime = NewTime;
int32_t MouseX = 0;
int32_t MouseY = 0;
SDL_GetMouseState(&MouseX, &MouseY);
// The mouse rect follows the mouse pointer
RectMouse.x = MouseX - (RectMouse.w / 2);
RectMouse.y = MouseY - (RectMouse.h / 2);
// Hold the up/down key on the keyboard to increase/decrease the border size (clamped between 'Lowest' and 'Highest')
const Uint8* pKeyboardState = SDL_GetKeyboardState(nullptr);
const float Speed = 64.0f;
const float Lowest = 5.0f;
const float Highest = 50.0f;
if (pKeyboardState[SDL_SCANCODE_UP])
{
Border += Speed * (float)DeltaTime;
if(Border > Highest)
Border = Highest;
}
else if (pKeyboardState[SDL_SCANCODE_DOWN])
{
Border -= Speed * (float)DeltaTime;
if(Border < Lowest)
Border = Lowest;
}
}
void Render()
{
SDL_SetRenderDrawColor(pRenderer, 0, 0, 0, 255);
SDL_RenderClear(pRenderer);
//////////////////////////////////////////////////////////////////////////
// First render the three colored rects that the mouse rect should check intersection against
for (uint32_t i = 0; i < 3; ++i)
{
SDL_SetRenderDrawColor(pRenderer, RectColors[i].r, RectColors[i].g, RectColors[i].b, RectColors[i].a);
SDL_RenderFillRect(pRenderer, &Rects[i]);
}
//
SDL_RenderCopy(pRenderer, tex, &srcRect, &Rects[3]);
// Render the mouse rect
SDL_SetRenderDrawColor(pRenderer, 200, 0, 0, 255);
SDL_RenderFillRect(pRenderer, &RectMouse);
for (uint32_t i = 0; i < 4; ++i)
{
const SDL_Point BorderSize = {(int32_t)Border, (int32_t)Border};
const SDL_Rect IntersectingRect = {RectMouse.x + BorderSize.x, RectMouse.y + BorderSize.y, RectMouse.w - (BorderSize.x * 2), RectMouse.h - (BorderSize.y * 2)};
SDL_Rect Intersection = {0, 0, 0, 0};
// Do intersection test between the mouse rect (minus the border size, see 'IntersectionRect' above) and the colored rects
if(SDL_IntersectRect(&Rects[i], &IntersectingRect, &Intersection) == SDL_TRUE)
{
// If an intersection occurs, the intersection part is rendered on top of the mouse rect, in the same color as the rect that the mouse rect is intersecting with
SDL_SetRenderDrawColor(pRenderer, RectColors[i].r, RectColors[i].g, RectColors[i].b, RectColors[i].a);
//SDL_SetRenderDrawColor(pRenderer, 89, 12, 126, 255); // renders aditional rectangles with color of the intersected ones
SDL_RenderFillRect(pRenderer, &Intersection);
if (i == 3){
SDL_Rect crop = {srcRect.x - (WINDOW_WIDTH/2 - Intersection.x), srcRect.y - (WINDOW_HEIGHT/2 - Intersection.y), Intersection.w, Intersection.h};
SDL_RenderCopy(pRenderer, tex, &crop, &Intersection);
}
}
}
//////////////////////////////////////////////////////////////////////////
SDL_RenderPresent(pRenderer);
}
int main(int argc, char** argv)
{
if(!InitSDL() )
return -1;
InitAssets();
while(Running)
{
HandleEvents();
Update();
Render();
}
DeinitSDL();
return 0;
}