Skip to content

Commit

Permalink
Spawn new cat every time a meow key is hit
Browse files Browse the repository at this point in the history
  • Loading branch information
User9684 committed Jan 24, 2025
1 parent bd99bcc commit c288cbe
Show file tree
Hide file tree
Showing 11 changed files with 136 additions and 30 deletions.
117 changes: 94 additions & 23 deletions cats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,53 @@
#include <gdiplus.h>
#include <iostream>
#include <map>
#include <random>
#include <string>
#include <vector>
#include <windows.h>


#pragma comment(lib, "gdiplus.lib")

struct CatWindowData {
Gdiplus::Bitmap *image;
int scaleRatio;
int x;
int y;
int dx;
int dy;
};

const std::map<std::string, int> catRatios = {
{"CAT1", 2},
{"CAT1", 3},
{"CAT2", 2},
{"CAT3", 3},
{"CAT4", 3},
};

const std::vector<std::string> cats = {
"CAT1",
"CAT2",
"CAT3",
"CAT4",
};

std::string gen_random(const int len) {
static const char characters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
std::string tmp_s;
tmp_s.reserve(len);

for (int i = 0; i < len; ++i) {
tmp_s += characters[rand() % (sizeof(characters) - 1)];
}

return tmp_s;
}

void SpawnCat(HINSTANCE hInstance) {
const LPCSTR CLASS_NAME = "CatWindow";
std::string catIdentifier = "CatWindow_" + gen_random(8);

const LPCSTR CLASS_NAME = catIdentifier.c_str();
const std::string catName = cats[rand() % cats.size()];
const std::wstring resourceName(catName.begin(), catName.end());
HRSRC hRes = nullptr;
Expand Down Expand Up @@ -82,42 +112,74 @@ void SpawnCat(HINSTANCE hInstance) {
int imageWidth = catImage->GetWidth() / scaleRatio;
int imageHeight = catImage->GetHeight() / scaleRatio;

CatWindowData *catData = new CatWindowData;
catData->image = catImage;
catData->scaleRatio = scaleRatio;

// Register a window class for the cat
WNDCLASS wc = {};
wc.lpfnWndProc = [](HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam) -> LRESULT {
static Gdiplus::Bitmap *image = nullptr;
static int x = 100, y = 100, dx = 5, dy = 5;
static CatWindowData *data = nullptr;

switch (uMsg) {
case WM_CREATE: {
image = (Gdiplus::Bitmap *)((LPCREATESTRUCT)lParam)->lpCreateParams;
CREATESTRUCT *cs = (CREATESTRUCT *)lParam;
CatWindowData *data = (CatWindowData *)cs->lpCreateParams;

SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)data);

POINT randomPosition = GetRandomPositionOnScreen();

data->x = randomPosition.x;
data->y = randomPosition.y;
;
data->dx = randomBetween(5, 10);
data->dy = randomBetween(5, 10);

SetTimer(hwnd, 1, 16, NULL);
return 0;
}
case WM_TIMER: {
CatWindowData *data =
(CatWindowData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (!data)
return 0;

int imageWidth =
static_cast<int>(data->image->GetWidth()) / data->scaleRatio;
int imageHeight =
static_cast<int>(data->image->GetHeight()) / data->scaleRatio;

RECT totalScreen = GetTotalScreenArea();

// Update the cat's position
x += dx;
y += dy;
data->x += data->dx;
data->y += data->dy;

// Reverse direction on hitting screen boundaries
if (x < totalScreen.left || x + image->GetWidth() > totalScreen.right) {
dx = -dx;
if (data->x < totalScreen.left ||
data->x + imageWidth > totalScreen.right) {
data->dx = -data->dx;
}
if (y < totalScreen.top || y + image->GetHeight() > totalScreen.bottom) {
dy = -dy;
if (data->y < totalScreen.top ||
data->y + imageWidth > totalScreen.bottom) {
data->dy = -data->dy;
}

// Move the window to the new position
SetWindowPos(hwnd, NULL, x, y, 0, 0,
SetWindowPos(hwnd, NULL, data->x, data->y, 0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);

return 0;
}

case WM_PAINT: {
CatWindowData *data =
(CatWindowData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (!data)
return 0;

PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);

Expand All @@ -127,24 +189,30 @@ void SpawnCat(HINSTANCE hInstance) {
int windowHeight = rect.bottom - rect.top;

// Get the dimensions of the image
int imageWidth = image->GetWidth();
int imageHeight = image->GetHeight();
int scaledWidth = data->image->GetWidth() / data->scaleRatio;
int scaledHeight = data->image->GetHeight() / data->scaleRatio;

// Calculate the top-left position to center the image
int xPos = (windowWidth - imageWidth) / 2;
int yPos = (windowHeight - imageHeight) / 2;
int xPos = (windowWidth - scaledWidth) / 2;
int yPos = (windowHeight - scaledHeight) / 2;

Gdiplus::Graphics graphics(hdc);
graphics.DrawImage(image, xPos, yPos, imageWidth, imageHeight);
graphics.DrawImage(data->image, xPos, yPos, scaledWidth, scaledHeight);

EndPaint(hwnd, &ps);
return 0;
}
case WM_DESTROY:
KillTimer(hwnd, 1);
delete image;
case WM_DESTROY: {
CatWindowData *data =
(CatWindowData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (data) {
KillTimer(hwnd, 1);
delete data->image;
delete data;
}
PostQuitMessage(0);
return 0;
}
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
Expand All @@ -155,6 +223,7 @@ void SpawnCat(HINSTANCE hInstance) {
if (!RegisterClass(&wc)) {
std::cerr << "Failed to register cat window class!" << std::endl;
delete catImage;
delete catData;
GlobalFree(hMem);
Gdiplus::GdiplusShutdown(gdiplusToken);
return;
Expand All @@ -164,17 +233,19 @@ void SpawnCat(HINSTANCE hInstance) {
HWND hwnd = CreateWindowEx(WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TOOLWINDOW |
WS_EX_TRANSPARENT,
CLASS_NAME, "", WS_POPUP, 0, 0, imageWidth,
imageHeight, NULL, NULL, hInstance, catImage);
imageHeight, NULL, NULL, hInstance, catData);

SetLayeredWindowAttributes(hwnd, 0, 255, LWA_ALPHA);

if (!hwnd) {
std::cerr << "Failed to create cat window!" << std::endl;
delete catImage;
delete catData;
GlobalFree(hMem);
Gdiplus::GdiplusShutdown(gdiplusToken);
return;
}

ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
}
}
4 changes: 3 additions & 1 deletion cats.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@

int FindResourceByNameAcrossAllTypes(const std::wstring &targetName,
HRSRC &resourceOut);
RECT GetTotalScreenArea();
RECT GetTotalScreenArea();
POINT GetRandomPositionOnScreen();
int randomBetween(int min, int max);
11 changes: 8 additions & 3 deletions keyboardhook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <vector>
#include <windows.h>

HINSTANCE rootHInstance;
HHOOK keyboardHook;
HRSRC resource;

Expand Down Expand Up @@ -63,10 +64,12 @@ LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode == HC_ACTION) {
KBDLLHOOKSTRUCT *keyInfo = (KBDLLHOOKSTRUCT *)lParam;

if (std::find(kitties.begin(), kitties.end(), keyInfo->vkCode) !=
kitties.end()) {
if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) &&
std::find(kitties.begin(), kitties.end(), keyInfo->vkCode) !=
kitties.end()) {
std::thread soundThread(Meow);
soundThread.detach();
SpawnCat(rootHInstance);
}

if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) &&
Expand All @@ -84,7 +87,9 @@ LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
return 1;
}

int InitKeyboardHook() {
int InitKeyboardHook(HINSTANCE hInstance) {
rootHInstance = hInstance;

const std::wstring resourceName = L"IDR_SOUND1";
if (FindResourceByNameAcrossAllTypes(resourceName, resource) != 0) {
std::cerr << "Resource not found: " << WStringToString(resourceName)
Expand Down
3 changes: 2 additions & 1 deletion keyboardhook.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@

int FindResourceByNameAcrossAllTypes(const std::wstring &targetName,
HRSRC &resourceOut);
void PlayResource(const HRSRC resource);
void PlayResource(const HRSRC resource);
void SpawnCat(HINSTANCE hInstance);
2 changes: 1 addition & 1 deletion main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow) {

InitKeyboardHook();
InitKeyboardHook(hInstance);
ApplyHueOverlay(hInstance);
SpawnCat(hInstance);

Expand Down
Binary file added resources/cat2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/cat3.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/cat4.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/cat5.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 4 additions & 1 deletion resources/resources.rc
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#include "windows.h"

IDR_SOUND1 RT_RCDATA "meow.wav"
CAT1 RT_RCDATA "cat1.jpeg"
CAT1 RT_RCDATA "cat1.jpeg"
CAT2 RT_RCDATA "cat2.png"
CAT3 RT_RCDATA "cat3.jpeg"
CAT4 RT_RCDATA "cat4.jpeg"
24 changes: 24 additions & 0 deletions screenarea.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <random>
#include <windows.h>

RECT GetTotalScreenArea() {
Expand All @@ -18,4 +19,27 @@ RECT GetTotalScreenArea() {
reinterpret_cast<LPARAM>(&totalArea));

return totalArea;
}

int randomBetween(int min, int max) {
std::random_device rdev;
std::mt19937 rgen(rdev());
std::uniform_int_distribution<int> idist(min, max);

return idist(rgen);
}

POINT GetRandomPositionOnScreen() {
RECT screenArea = GetTotalScreenArea();

std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<int> distX(screenArea.left, screenArea.right);
std::uniform_int_distribution<int> distY(screenArea.top, screenArea.bottom);

POINT randomPoint;
randomPoint.x = distX(gen);
randomPoint.y = distY(gen);

return randomPoint;
}

0 comments on commit c288cbe

Please sign in to comment.