Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8185fc3032 | |||
| 74b56773d9 |
Binary file not shown.
Binary file not shown.
@@ -140,6 +140,21 @@
|
|||||||
<Image Include="..\..\..\..\Downloads\hyrax.ico" />
|
<Image Include="..\..\..\..\Downloads\hyrax.ico" />
|
||||||
<Image Include="..\..\..\..\Downloads\hyrax.jpeg" />
|
<Image Include="..\..\..\..\Downloads\hyrax.jpeg" />
|
||||||
<Image Include="hyrax.bmp" />
|
<Image Include="hyrax.bmp" />
|
||||||
|
<Image Include="hyrax_scream.jpeg" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Media Include="hyrax1.wav" />
|
||||||
|
<Media Include="hyrax2.wav" />
|
||||||
|
<Media Include="hyrax3.wav" />
|
||||||
|
<Media Include="hyrax4.wav" />
|
||||||
|
<Media Include="hyrax5.wav" />
|
||||||
|
<Media Include="hyrax6.wav" />
|
||||||
|
<Media Include="hyrax7.wav" />
|
||||||
|
<Media Include="hyrax8.wav" />
|
||||||
|
<Media Include="hyrax9.wav" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\..\..\..\downloads\wave3.bin" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
|||||||
@@ -39,5 +39,42 @@
|
|||||||
<Image Include="..\..\..\..\Downloads\hyrax.ico">
|
<Image Include="..\..\..\..\Downloads\hyrax.ico">
|
||||||
<Filter>Resource Files</Filter>
|
<Filter>Resource Files</Filter>
|
||||||
</Image>
|
</Image>
|
||||||
|
<Image Include="hyrax_scream.jpeg">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</Image>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Media Include="hyrax1.wav">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</Media>
|
||||||
|
<Media Include="hyrax2.wav">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</Media>
|
||||||
|
<Media Include="hyrax3.wav">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</Media>
|
||||||
|
<Media Include="hyrax4.wav">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</Media>
|
||||||
|
<Media Include="hyrax5.wav">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</Media>
|
||||||
|
<Media Include="hyrax6.wav">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</Media>
|
||||||
|
<Media Include="hyrax7.wav">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</Media>
|
||||||
|
<Media Include="hyrax8.wav">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</Media>
|
||||||
|
<Media Include="hyrax9.wav">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</Media>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\..\..\..\downloads\wave3.bin">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.0 MiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 207 KiB |
+404
-167
@@ -1,275 +1,512 @@
|
|||||||
#include <windows.h>
|
/*
|
||||||
|
Anytime I edit any C++ Code, in specifically Win32 code i get acute seizures cause of the naming
|
||||||
|
conventions. I hope that whoever came up with these fuckass names gets fucked by a femboy. idk.
|
||||||
|
|
||||||
|
Anyways this is under the AGPL3.0 License so do whatever you want under that license terms.
|
||||||
|
|
||||||
|
Quick description of the app:
|
||||||
|
- A hyrax picture which bounces around your desktop, like bonzi buddy but not destructive, more of a fun thing which you can open
|
||||||
|
when you get bored.
|
||||||
|
- Run the exe youll find out.
|
||||||
|
|
||||||
|
This is not malware or a virus, its purely for fun and entertainment purpouses.
|
||||||
|
|
||||||
|
rattatwinko - 04/05/26
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <windowsx.h>
|
||||||
#include <gdiplus.h>
|
#include <gdiplus.h>
|
||||||
#include <cstring>
|
|
||||||
#include <math.h>
|
|
||||||
#include <objidl.h>
|
#include <objidl.h>
|
||||||
|
#include <mmsystem.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <ctime>
|
||||||
|
#include <cstdint>
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
#pragma comment(lib, "gdiplus.lib")
|
#pragma comment(lib, "gdiplus.lib")
|
||||||
|
#pragma comment(lib, "winmm.lib")
|
||||||
|
|
||||||
using namespace Gdiplus;
|
using namespace Gdiplus;
|
||||||
|
|
||||||
Image* LoadImageFromResource(int resId) {
|
// consts
|
||||||
HRSRC hRes = FindResource(NULL, MAKEINTRESOURCE(resId), RT_RCDATA);
|
static constexpr double GRAVITY = 1200.0;
|
||||||
if (!hRes) return NULL;
|
static constexpr double RESTITUTION = 0.6;
|
||||||
|
static constexpr double AIR_DRAG = 0.999;
|
||||||
|
static constexpr double GROUND_FRICTION = 0.8;
|
||||||
|
static constexpr double REST_THRESHOLD = 5.0;
|
||||||
|
static constexpr UINT TIMER_MS = 10;
|
||||||
|
static constexpr int IMAGE_RESOURCE = 111;
|
||||||
|
static constexpr int RESIZE_BORDER = 12; // make wider so easier grab
|
||||||
|
static constexpr int DRAG_THRESHOLD = 5; // pixels before its a drag not a click
|
||||||
|
static constexpr int WAV_COUNT = 9;
|
||||||
|
static constexpr int MAX_PEAKS = 64; // max screams per sound
|
||||||
|
static constexpr double PEAK_HOLD = 0.10; // seconds which we hold the awawa face
|
||||||
|
static constexpr double PEAK_THRESH = 0.65; // fraction of max amplitude to count as a peak
|
||||||
|
|
||||||
DWORD size = SizeofResource(NULL, hRes);
|
// globals
|
||||||
if (size == 0) return NULL;
|
static ULONG_PTR g_gdiplusToken = 0;
|
||||||
|
static Image* g_image = nullptr; // normal hyrax
|
||||||
|
static Image* g_imageScream = nullptr; // awawa hyrax
|
||||||
|
static int g_winW = 640;
|
||||||
|
static int g_winH = 480;
|
||||||
|
static LARGE_INTEGER g_freq = {};
|
||||||
|
|
||||||
HGLOBAL hData = LoadResource(NULL, hRes);
|
// physics states
|
||||||
if (!hData) return NULL;
|
static double g_x = 200.0, g_y = 50.0;
|
||||||
|
static double g_vx = 0.0, g_vy = 0.0;
|
||||||
|
static double g_lastTime = 0.0;
|
||||||
|
|
||||||
|
// resize / drag status
|
||||||
|
static bool g_resizing = false;
|
||||||
|
static bool g_dragging = false;
|
||||||
|
static bool g_didDrag = false;
|
||||||
|
static int g_dragOffsetX = 0;
|
||||||
|
static int g_dragOffsetY = 0;
|
||||||
|
static POINT g_lastMouse = {};
|
||||||
|
static POINT g_clickOrigin = {};
|
||||||
|
static double g_lastMouseTime = 0.0;
|
||||||
|
|
||||||
|
// scream face stuff
|
||||||
|
static bool g_screaming = false;
|
||||||
|
static double g_screamUntil = 0.0; // timestamp to stop screaming
|
||||||
|
static double g_soundStart = 0.0; // when playback began
|
||||||
|
static double g_peakTimes[MAX_PEAKS] = {};
|
||||||
|
static int g_peakCount = 0;
|
||||||
|
static int g_peakIdx = 0; // next peak we havent fired yet
|
||||||
|
|
||||||
|
// helper definitions
|
||||||
|
static double Now() {
|
||||||
|
LARGE_INTEGER t;
|
||||||
|
QueryPerformanceCounter(&t);
|
||||||
|
return static_cast<double>(t.QuadPart) / static_cast<double>(g_freq.QuadPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
// load any image from any rc resource type
|
||||||
|
static Image* LoadImageFromResource(HINSTANCE hInst, int resId, LPCWSTR resType) {
|
||||||
|
HRSRC hRes = FindResource(hInst, MAKEINTRESOURCE(resId), resType);
|
||||||
|
if (!hRes) return nullptr;
|
||||||
|
|
||||||
|
DWORD size = SizeofResource(hInst, hRes);
|
||||||
|
if (!size) return nullptr;
|
||||||
|
|
||||||
|
HGLOBAL hData = LoadResource(hInst, hRes);
|
||||||
|
if (!hData) return nullptr;
|
||||||
|
|
||||||
void* pData = LockResource(hData);
|
void* pData = LockResource(hData);
|
||||||
if (!pData) return NULL;
|
if (!pData) return nullptr;
|
||||||
|
|
||||||
HGLOBAL hBuffer = GlobalAlloc(GMEM_MOVEABLE, size);
|
HGLOBAL hBuf = GlobalAlloc(GMEM_MOVEABLE, size);
|
||||||
if (!hBuffer) return NULL;
|
if (!hBuf) return nullptr;
|
||||||
|
|
||||||
void* pBuffer = GlobalLock(hBuffer);
|
void* pBuf = GlobalLock(hBuf);
|
||||||
if (!pBuffer) {
|
if (!pBuf) { GlobalFree(hBuf); return nullptr; }
|
||||||
GlobalFree(hBuffer);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(pBuffer, pData, size);
|
memcpy(pBuf, pData, size);
|
||||||
GlobalUnlock(hBuffer);
|
GlobalUnlock(hBuf);
|
||||||
|
|
||||||
IStream* stream = NULL;
|
IStream* stream = nullptr;
|
||||||
HRESULT hr = CreateStreamOnHGlobal(hBuffer, TRUE, &stream);
|
if (FAILED(CreateStreamOnHGlobal(hBuf, TRUE, &stream)) || !stream) {
|
||||||
if (FAILED(hr) || !stream) {
|
GlobalFree(hBuf);
|
||||||
GlobalFree(hBuffer);
|
return nullptr;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Image* img = Image::FromStream(stream);
|
Image* img = Image::FromStream(stream);
|
||||||
stream->Release();
|
stream->Release();
|
||||||
|
|
||||||
if (!img || img->GetLastStatus() != Ok) {
|
if (!img || img->GetLastStatus() != Ok) {
|
||||||
if (img) delete img;
|
delete img;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// walk RAW fucking PCM data and check for peaks
|
||||||
|
static void FindWavPeaks(const BYTE* buf, DWORD size) {
|
||||||
|
g_peakCount = 0;
|
||||||
|
g_peakIdx = 0;
|
||||||
|
|
||||||
double x = 200.0, y = 50.0;
|
if (size < 44) return;
|
||||||
double vx = 0.0, vy = 0.0;
|
if (memcmp(buf, "RIFF", 4) != 0 || memcmp(buf + 8, "WAVE", 4) != 0) return;
|
||||||
|
|
||||||
double gravity = 1200.0;
|
WORD channels = 0;
|
||||||
double restitution = 0.6;
|
DWORD sampleRate = 0;
|
||||||
double air_drag = 0.999;
|
WORD bitsPerSample = 0;
|
||||||
double ground_friction = 0.8;
|
const BYTE* pcm = nullptr;
|
||||||
|
DWORD pcmSize = 0;
|
||||||
|
|
||||||
int win_w = 640;
|
// walk the chunks
|
||||||
int win_h = 480;
|
DWORD pos = 12;
|
||||||
|
while (pos + 8 <= size) {
|
||||||
|
DWORD chunkSize = *reinterpret_cast<const DWORD*>(buf + pos + 4);
|
||||||
|
|
||||||
int dragging = 0;
|
if (memcmp(buf + pos, "fmt ", 4) == 0 && chunkSize >= 16) {
|
||||||
int offset_x = 0, offset_y = 0;
|
channels = *reinterpret_cast<const WORD*> (buf + pos + 10);
|
||||||
|
sampleRate = *reinterpret_cast<const DWORD*>(buf + pos + 12);
|
||||||
|
bitsPerSample = *reinterpret_cast<const WORD*> (buf + pos + 22);
|
||||||
|
}
|
||||||
|
else if (memcmp(buf + pos, "data", 4) == 0) {
|
||||||
|
pcm = buf + pos + 8;
|
||||||
|
pcmSize = chunkSize;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
POINT last_mouse;
|
pos += 8 + chunkSize;
|
||||||
double last_mouse_time = 0.0;
|
if (chunkSize & 1) pos++; // align word cause microsoft likes to fuck my ass
|
||||||
double last_time = 0.0;
|
}
|
||||||
|
|
||||||
LARGE_INTEGER freq;
|
// only 16bit PCM cause everything else is just stoopid
|
||||||
|
if (!pcm || !sampleRate || bitsPerSample != 16) return;
|
||||||
|
|
||||||
ULONG_PTR gdiplusToken;
|
DWORD totalSamples = pcmSize / (channels * sizeof(int16_t));
|
||||||
Image* img = NULL;
|
|
||||||
|
|
||||||
|
// global maximum
|
||||||
|
int maxAmp = 1;
|
||||||
|
for (DWORD i = 0; i < pcmSize / sizeof(int16_t); i++) {
|
||||||
|
int s = abs((int)*reinterpret_cast<const int16_t*>(pcm + i * sizeof(int16_t)));
|
||||||
|
if (s > maxAmp) maxAmp = s;
|
||||||
|
}
|
||||||
|
|
||||||
double now_time() {
|
int threshold = static_cast<int>(maxAmp * PEAK_THRESH);
|
||||||
LARGE_INTEGER t;
|
DWORD windowSamples = sampleRate / 50; // 20ms windows
|
||||||
QueryPerformanceCounter(&t);
|
DWORD debounce = sampleRate / 8; // 125ms min gap so we dont spam
|
||||||
return (double)t.QuadPart / (double)freq.QuadPart;
|
DWORD lastPeak = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
// stupid fucking logic. scan for loud moments
|
||||||
|
for (DWORD s = 0; s + windowSamples <= totalSamples; s += windowSamples / 2) {
|
||||||
|
int winMax = 0;
|
||||||
|
for (DWORD j = 0; j < windowSamples * channels; j++) {
|
||||||
|
DWORD byteOff = (s * channels + j) * sizeof(int16_t);
|
||||||
|
if (byteOff + sizeof(int16_t) > pcmSize) break;
|
||||||
|
int amp = abs((int)*reinterpret_cast<const int16_t*>(pcm + byteOff));
|
||||||
|
if (amp > winMax) winMax = amp;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gapOk = (lastPeak == 0xFFFFFFFF) || (s - lastPeak >= debounce);
|
||||||
|
if (winMax >= threshold && gapOk && g_peakCount < MAX_PEAKS) {
|
||||||
|
g_peakTimes[g_peakCount++] = static_cast<double>(s) / sampleRate;
|
||||||
|
lastPeak = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// play a random hyrax sound and prep the scream timeline
|
||||||
|
static void PlayRandomSound(HINSTANCE hInst) {
|
||||||
|
int id = IDR_WAVE1 + (rand() % WAV_COUNT);
|
||||||
|
|
||||||
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
|
// grab raw wave data and look for peaks ; possible cause of .rc WAVE type
|
||||||
|
HRSRC hRes = FindResource(hInst, MAKEINTRESOURCE(id), L"WAVE");
|
||||||
|
HGLOBAL hData = hRes ? LoadResource(hInst, hRes) : nullptr;
|
||||||
|
BYTE* pData = hData ? static_cast<BYTE*>(LockResource(hData)) : nullptr;
|
||||||
|
DWORD sz = hRes ? SizeofResource(hInst, hRes) : 0;
|
||||||
|
|
||||||
|
if (pData && sz)
|
||||||
|
FindWavPeaks(pData, sz);
|
||||||
|
|
||||||
|
g_soundStart = Now();
|
||||||
|
|
||||||
|
PlaySoundW(MAKEINTRESOURCEW(id), hInst, SND_RESOURCE | SND_ASYNC | SND_NODEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// physics "engine"
|
||||||
|
static void StepPhysics(double dt) {
|
||||||
|
const int screenW = GetSystemMetrics(SM_CXSCREEN);
|
||||||
|
const int screenH = GetSystemMetrics(SM_CYSCREEN);
|
||||||
|
|
||||||
|
g_vy += GRAVITY * dt;
|
||||||
|
g_vx *= AIR_DRAG;
|
||||||
|
g_vy *= AIR_DRAG;
|
||||||
|
|
||||||
|
g_x += g_vx * dt;
|
||||||
|
g_y += g_vy * dt;
|
||||||
|
|
||||||
|
// left / right monitor borders
|
||||||
|
if (g_x < 0.0) {
|
||||||
|
g_x = 0.0;
|
||||||
|
g_vx = -g_vx * RESTITUTION;
|
||||||
|
}
|
||||||
|
else if (g_x > screenW - g_winW) {
|
||||||
|
g_x = static_cast<double>(screenW - g_winW);
|
||||||
|
g_vx = -g_vx * RESTITUTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// top
|
||||||
|
if (g_y < 0.0) {
|
||||||
|
g_y = 0.0;
|
||||||
|
g_vy = -g_vy * RESTITUTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// bottom
|
||||||
|
if (g_y > screenH - g_winH) {
|
||||||
|
g_y = static_cast<double>(screenH - g_winH);
|
||||||
|
g_vy = -g_vy * RESTITUTION;
|
||||||
|
g_vx *= GROUND_FRICTION;
|
||||||
|
if (fabs(g_vy) < REST_THRESHOLD)
|
||||||
|
g_vy = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// win api window proc
|
||||||
|
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
|
||||||
switch (msg) {
|
switch (msg) {
|
||||||
|
|
||||||
|
// init the window
|
||||||
case WM_CREATE: {
|
case WM_CREATE: {
|
||||||
QueryPerformanceFrequency(&freq);
|
QueryPerformanceFrequency(&g_freq);
|
||||||
|
srand(static_cast<unsigned>(time(nullptr)));
|
||||||
|
|
||||||
GdiplusStartupInput gdiplusStartupInput;
|
GdiplusStartupInput si;
|
||||||
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
|
GdiplusStartup(&g_gdiplusToken, &si, nullptr);
|
||||||
|
|
||||||
img = LoadImageFromResource(111);
|
HINSTANCE hInst = reinterpret_cast<CREATESTRUCT*>(lParam)->hInstance;
|
||||||
|
|
||||||
if (!img || img->GetLastStatus() != Ok) {
|
g_image = LoadImageFromResource(hInst, IDR_RCDATA1, RT_RCDATA);
|
||||||
// MessageBoxA(NULL, "Image failed to load", "Error", MB_OK);
|
g_imageScream = LoadImageFromResource(hInst, IDB_BITMAP1, L"JPG");
|
||||||
}
|
|
||||||
else {
|
if (g_image) {
|
||||||
win_w = 640;
|
g_winW = static_cast<int>(g_image->GetWidth());
|
||||||
win_h = 480;
|
g_winH = static_cast<int>(g_image->GetHeight());
|
||||||
SetWindowPos(hwnd, NULL, 0, 0, win_w, win_h, SWP_NOMOVE);
|
SetWindowPos(hwnd, nullptr, 0, 0, g_winW, g_winH,
|
||||||
|
SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetTimer(hwnd, 1, 10, NULL);
|
g_lastTime = Now();
|
||||||
|
g_lastMouseTime = g_lastTime;
|
||||||
|
|
||||||
last_time = now_time();
|
SetTimer(hwnd, 1, TIMER_MS, nullptr);
|
||||||
last_mouse_time = last_time;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// drag start
|
||||||
case WM_LBUTTONDOWN: {
|
case WM_LBUTTONDOWN: {
|
||||||
dragging = 1;
|
g_dragging = true;
|
||||||
offset_x = LOWORD(lParam);
|
g_didDrag = false;
|
||||||
offset_y = HIWORD(lParam);
|
g_dragOffsetX = GET_X_LPARAM(lParam);
|
||||||
|
g_dragOffsetY = GET_Y_LPARAM(lParam);
|
||||||
|
g_vx = g_vy = 0.0;
|
||||||
|
|
||||||
vx = vy = 0;
|
GetCursorPos(&g_lastMouse);
|
||||||
|
g_clickOrigin = g_lastMouse;
|
||||||
GetCursorPos(&last_mouse);
|
g_lastMouseTime = Now();
|
||||||
last_mouse_time = now_time();
|
|
||||||
|
|
||||||
SetCapture(hwnd);
|
SetCapture(hwnd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case WM_SETCURSOR:
|
|
||||||
if (dragging)
|
|
||||||
SetCursor(LoadCursor(NULL, IDC_SIZEALL));
|
|
||||||
else
|
|
||||||
SetCursor(LoadCursor(NULL, IDC_HAND));
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
case WM_MOUSEMOVE:
|
// drag move
|
||||||
if (dragging) {
|
case WM_MOUSEMOVE: {
|
||||||
POINT p;
|
if (!g_dragging) break;
|
||||||
GetCursorPos(&p);
|
|
||||||
|
|
||||||
double now = now_time();
|
POINT p;
|
||||||
double dt = now - last_mouse_time;
|
GetCursorPos(&p);
|
||||||
|
|
||||||
if (dt > 0) {
|
if (abs(p.x - g_clickOrigin.x) > DRAG_THRESHOLD ||
|
||||||
vx = (p.x - last_mouse.x) / dt;
|
abs(p.y - g_clickOrigin.y) > DRAG_THRESHOLD)
|
||||||
vy = (p.y - last_mouse.y) / dt;
|
g_didDrag = true;
|
||||||
}
|
|
||||||
|
|
||||||
last_mouse = p;
|
const double now = Now();
|
||||||
last_mouse_time = now;
|
const double dt = now - g_lastMouseTime;
|
||||||
|
|
||||||
x = p.x - offset_x;
|
if (dt > 0.0) {
|
||||||
y = p.y - offset_y;
|
g_vx = (p.x - g_lastMouse.x) / dt;
|
||||||
|
g_vy = (p.y - g_lastMouse.y) / dt;
|
||||||
SetWindowPos(hwnd, NULL, (int)x, (int)y, 0, 0,
|
|
||||||
SWP_NOSIZE | SWP_NOZORDER);
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_LBUTTONUP:
|
g_lastMouse = p;
|
||||||
dragging = 0;
|
g_lastMouseTime = now;
|
||||||
ReleaseCapture();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_TIMER: {
|
g_x = p.x - g_dragOffsetX;
|
||||||
double now = now_time();
|
g_y = p.y - g_dragOffsetY;
|
||||||
double dt = now - last_time;
|
|
||||||
last_time = now;
|
|
||||||
|
|
||||||
int screen_w = GetSystemMetrics(SM_CXSCREEN);
|
SetWindowPos(hwnd, nullptr, static_cast<int>(g_x), static_cast<int>(g_y),
|
||||||
int screen_h = GetSystemMetrics(SM_CYSCREEN);
|
0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
|
||||||
|
|
||||||
if (!dragging) {
|
|
||||||
vy += gravity * dt;
|
|
||||||
|
|
||||||
vx *= air_drag;
|
|
||||||
vy *= air_drag;
|
|
||||||
|
|
||||||
x += vx * dt;
|
|
||||||
y += vy * dt;
|
|
||||||
|
|
||||||
if (x <= 0) {
|
|
||||||
x = 0;
|
|
||||||
vx = -vx * restitution;
|
|
||||||
}
|
|
||||||
else if (x >= screen_w - win_w) {
|
|
||||||
x = screen_w - win_w;
|
|
||||||
vx = -vx * restitution;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y >= screen_h - win_h) {
|
|
||||||
y = screen_h - win_h;
|
|
||||||
vy = -vy * restitution;
|
|
||||||
vx *= ground_friction;
|
|
||||||
|
|
||||||
if (fabs(vy) < 5)
|
|
||||||
vy = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y <= 0) {
|
|
||||||
y = 0;
|
|
||||||
vy = -vy * restitution;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetWindowPos(hwnd, NULL, (int)x, (int)y, 0, 0,
|
|
||||||
SWP_NOSIZE | SWP_NOZORDER);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// drag end or click
|
||||||
|
case WM_LBUTTONUP: {
|
||||||
|
if (!g_didDrag) {
|
||||||
|
HINSTANCE hInst = reinterpret_cast<HINSTANCE>(GetWindowLongPtrW(hwnd, GWLP_HINSTANCE));
|
||||||
|
PlayRandomSound(hInst);
|
||||||
|
}
|
||||||
|
g_dragging = false;
|
||||||
|
ReleaseCapture();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// while dragging nutz accross fohead disable OS from doing shit
|
||||||
|
case WM_ENTERSIZEMOVE:
|
||||||
|
g_resizing = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_EXITSIZEMOVE: {
|
||||||
|
g_resizing = false;
|
||||||
|
g_vx = g_vy = 0.0;
|
||||||
|
|
||||||
|
// sync gx/y with resized cords
|
||||||
|
RECT r;
|
||||||
|
GetWindowRect(hwnd, &r);
|
||||||
|
g_x = static_cast<double>(r.left);
|
||||||
|
g_y = static_cast<double>(r.top);
|
||||||
|
|
||||||
|
g_lastTime = Now(); // after everything is clean then redraw
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// weird asf logic
|
||||||
|
case WM_NCHITTEST: {
|
||||||
|
POINT p = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
|
||||||
|
RECT r;
|
||||||
|
GetWindowRect(hwnd, &r);
|
||||||
|
|
||||||
|
const bool left = p.x < r.left + RESIZE_BORDER;
|
||||||
|
const bool right = p.x >= r.right - RESIZE_BORDER;
|
||||||
|
const bool top = p.y < r.top + RESIZE_BORDER;
|
||||||
|
const bool bottom = p.y >= r.bottom - RESIZE_BORDER;
|
||||||
|
|
||||||
|
if (top && left) return HTTOPLEFT;
|
||||||
|
if (top && right) return HTTOPRIGHT;
|
||||||
|
if (bottom && left) return HTBOTTOMLEFT;
|
||||||
|
if (bottom && right) return HTBOTTOMRIGHT;
|
||||||
|
if (left) return HTLEFT;
|
||||||
|
if (right) return HTRIGHT;
|
||||||
|
if (top) return HTTOP;
|
||||||
|
if (bottom) return HTBOTTOM;
|
||||||
|
return HTCLIENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sync dimensions after resizing
|
||||||
|
case WM_SIZE:
|
||||||
|
g_winW = LOWORD(lParam);
|
||||||
|
g_winH = HIWORD(lParam);
|
||||||
|
InvalidateRect(hwnd, nullptr, FALSE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// cursor, bunch of this dont work
|
||||||
|
case WM_SETCURSOR:
|
||||||
|
if (LOWORD(lParam) == HTCLIENT) {
|
||||||
|
SetCursor(LoadCursor(nullptr, g_dragging ? IDC_SIZEALL : IDC_HAND));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return DefWindowProcW(hwnd, msg, wParam, lParam);
|
||||||
|
|
||||||
|
// phyisks tick and scream face check
|
||||||
|
case WM_TIMER: {
|
||||||
|
const double now = Now();
|
||||||
|
const double dt = now - g_lastTime;
|
||||||
|
g_lastTime = now;
|
||||||
|
|
||||||
|
if (!g_dragging && !g_resizing) {
|
||||||
|
StepPhysics(dt);
|
||||||
|
SetWindowPos(hwnd, nullptr, static_cast<int>(g_x), static_cast<int>(g_y),
|
||||||
|
0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// extend scream hold
|
||||||
|
if (g_peakCount > 0) {
|
||||||
|
double elapsed = now - g_soundStart;
|
||||||
|
while (g_peakIdx < g_peakCount && elapsed >= g_peakTimes[g_peakIdx]) {
|
||||||
|
g_screamUntil = now + PEAK_HOLD;
|
||||||
|
g_peakIdx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// flip face state
|
||||||
|
bool shouldScream = (g_imageScream && now < g_screamUntil);
|
||||||
|
if (shouldScream != g_screaming) {
|
||||||
|
g_screaming = shouldScream;
|
||||||
|
InvalidateRect(hwnd, nullptr, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pablo picasso
|
||||||
case WM_PAINT: {
|
case WM_PAINT: {
|
||||||
PAINTSTRUCT ps;
|
PAINTSTRUCT ps;
|
||||||
HDC hdc = BeginPaint(hwnd, &ps);
|
HDC hdc = BeginPaint(hwnd, &ps);
|
||||||
|
|
||||||
Graphics g(hdc);
|
// db to avoid me floppin on the floor like a fish (cause of flashing lights)
|
||||||
|
HDC memDC = CreateCompatibleDC(hdc);
|
||||||
|
HBITMAP memBmp = CreateCompatibleBitmap(hdc, g_winW, g_winH);
|
||||||
|
HGDIOBJ old = SelectObject(memDC, memBmp);
|
||||||
|
|
||||||
if (img)
|
Graphics g(memDC);
|
||||||
g.DrawImage(img, 0, 0, win_w, win_h);
|
g.SetInterpolationMode(InterpolationModeHighQualityBicubic);
|
||||||
|
|
||||||
|
// swap to scream face on peaks
|
||||||
|
Image* frame = (g_screaming && g_imageScream) ? g_imageScream : g_image;
|
||||||
|
if (frame)
|
||||||
|
g.DrawImage(frame, 0, 0, g_winW, g_winH);
|
||||||
|
|
||||||
|
BitBlt(hdc, 0, 0, g_winW, g_winH, memDC, 0, 0, SRCCOPY);
|
||||||
|
|
||||||
|
SelectObject(memDC, old);
|
||||||
|
DeleteObject(memBmp);
|
||||||
|
DeleteDC(memDC);
|
||||||
|
|
||||||
EndPaint(hwnd, &ps);
|
EndPaint(hwnd, &ps);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// escape destroy
|
||||||
case WM_KEYDOWN:
|
case WM_KEYDOWN:
|
||||||
if (wParam == VK_ESCAPE)
|
if (wParam == VK_ESCAPE)
|
||||||
DestroyWindow(hwnd);
|
DestroyWindow(hwnd);
|
||||||
|
else if (wParam == VK_SPACE)
|
||||||
|
DestroyWindow(hwnd);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
// consuela
|
||||||
case WM_DESTROY:
|
case WM_DESTROY:
|
||||||
if (img) delete img;
|
KillTimer(hwnd, 1);
|
||||||
GdiplusShutdown(gdiplusToken);
|
delete g_image;
|
||||||
|
delete g_imageScream;
|
||||||
|
g_image = g_imageScream = nullptr;
|
||||||
|
GdiplusShutdown(g_gdiplusToken);
|
||||||
PostQuitMessage(0);
|
PostQuitMessage(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return DefWindowProcW(hwnd, msg, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
return DefWindowProcW(hwnd, msg, wParam, lParam);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// right around the entry point (reference to asshair guy)
|
||||||
static int WINAPI wWinMain(
|
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR, int nCmdShow) {
|
||||||
HINSTANCE hInstance,
|
WNDCLASSW wc = {};
|
||||||
HINSTANCE,
|
|
||||||
PWSTR,
|
|
||||||
int nCmdShow
|
|
||||||
) {
|
|
||||||
|
|
||||||
if (IsDebuggerPresent())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
WNDCLASSW wc = { 0 };
|
|
||||||
wc.lpfnWndProc = WndProc;
|
wc.lpfnWndProc = WndProc;
|
||||||
wc.hInstance = hInstance;
|
wc.hInstance = hInstance;
|
||||||
wc.lpszClassName = L"Hyrax";
|
wc.lpszClassName = L"Hyrax";
|
||||||
wc.hCursor = LoadCursor(NULL, IDC_HAND);
|
wc.hCursor = LoadCursor(nullptr, IDC_HAND);
|
||||||
|
|
||||||
RegisterClassW(&wc);
|
RegisterClassW(&wc);
|
||||||
|
|
||||||
HWND hwnd = CreateWindowExW(
|
HWND hwnd = CreateWindowExW(
|
||||||
WS_EX_TOPMOST,
|
WS_EX_TOPMOST,
|
||||||
L"Hyrax",
|
L"Hyrax", L"",
|
||||||
L"",
|
|
||||||
WS_POPUP,
|
WS_POPUP,
|
||||||
(int)x, (int)y,
|
static_cast<int>(g_x), static_cast<int>(g_y),
|
||||||
win_w, win_h,
|
g_winW, g_winH,
|
||||||
NULL, NULL, hInstance, NULL
|
nullptr, nullptr, hInstance, nullptr
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!hwnd)
|
||||||
|
return 1;
|
||||||
|
|
||||||
ShowWindow(hwnd, nCmdShow);
|
ShowWindow(hwnd, nCmdShow);
|
||||||
|
UpdateWindow(hwnd);
|
||||||
|
|
||||||
MSG msg;
|
MSG msg;
|
||||||
while (GetMessageW(&msg, NULL, 0, 0)) {
|
while (GetMessageW(&msg, nullptr, 0, 0)) {
|
||||||
TranslateMessage(&msg);
|
TranslateMessage(&msg);
|
||||||
DispatchMessageW(&msg);
|
DispatchMessageW(&msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return static_cast<int>(msg.wParam);
|
||||||
}
|
}
|
||||||
+11
-1
@@ -4,12 +4,22 @@
|
|||||||
//
|
//
|
||||||
#define IDR_RCDATA1 111
|
#define IDR_RCDATA1 111
|
||||||
#define IDI_ICON1 114
|
#define IDI_ICON1 114
|
||||||
|
#define IDR_WAVE1 115
|
||||||
|
#define IDR_WAVE2 116
|
||||||
|
#define IDR_WAVE3 118
|
||||||
|
#define IDR_WAVE4 119
|
||||||
|
#define IDR_WAVE5 120
|
||||||
|
#define IDR_WAVE6 121
|
||||||
|
#define IDR_WAVE7 122
|
||||||
|
#define IDR_WAVE8 123
|
||||||
|
#define IDR_WAVE9 124
|
||||||
|
#define IDB_BITMAP1 126
|
||||||
|
|
||||||
// Next default values for new objects
|
// Next default values for new objects
|
||||||
//
|
//
|
||||||
#ifdef APSTUDIO_INVOKED
|
#ifdef APSTUDIO_INVOKED
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 115
|
#define _APS_NEXT_RESOURCE_VALUE 127
|
||||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||||
#define _APS_NEXT_SYMED_VALUE 101
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
|
|||||||
Reference in New Issue
Block a user