1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
#include "raylib.h"
#include <math.h>
#define STAR_COUNT 200
typedef struct
{
int x;
int y;
float brightness;
float phase;
} Star;
typedef enum
{
PAUSE_NONE,
PAUSE_RESUME,
PAUSE_QUIT
} PauseAction;
/* --- INIT --- */
static void InitStars(Star *stars, int count, int width, int height)
{
for (int i = 0; i < count; i++)
{
stars[i].x = GetRandomValue(0, width);
stars[i].y = GetRandomValue(0, height * 2 / 3); /* Upper sky. */
stars[i].brightness = (float)GetRandomValue(30, 100) / 100.0f;
stars[i].phase = (float)GetRandomValue(0, 628) / 100.0f; /* ~0..2pi */
}
}
/* --- DRAW: 2D BACKGROUND --- */
static void DrawSky(int width, int height)
{
/* Two vertical gradients: white->blue (top), blue->black (bottom).
Replaces 480 DrawLine calls — fixes the tearing. */
Color white = { 255, 255, 255, 255 };
Color blue = { 40, 80, 160, 255 };
Color black = { 0, 0, 0, 255 };
DrawRectangleGradientV(0, 0, width, height / 2, white, blue);
DrawRectangleGradientV(0, height / 2, width, height - height / 2, blue, black);
}
static void DrawStars(const Star *stars, int count, float time)
{
for (int i = 0; i < count; i++)
{
float twinkle = 0.5f + 0.5f * sinf(time * 2.0f + stars[i].phase);
unsigned char a = (unsigned char)(255.0f * stars[i].brightness * twinkle);
DrawCircle(stars[i].x, stars[i].y, 2.0f * twinkle,
(Color){ 255, 255, 255, (unsigned char)(a / 3) });
DrawPixel(stars[i].x, stars[i].y, (Color){ 255, 255, 255, a });
}
}
static void DrawCrosshair(int width, int height)
{
int cx = width / 2;
int cy = height / 2;
Color c = { 255, 255, 255, 120 };
DrawLine(cx - 8, cy, cx - 3, cy, c);
DrawLine(cx + 3, cy, cx + 8, cy, c);
DrawLine(cx, cy - 8, cx, cy - 3, c);
DrawLine(cx, cy + 3, cx, cy + 8, c);
}
/* --- DRAW: PAUSE MENU --- */
static PauseAction DrawPauseMenu(int width, int height)
{
/* Dim overlay. */
DrawRectangle(0, 0, width, height, (Color){ 0, 0, 0, 160 });
/* Title. */
const char *title = "PAUSED";
int title_size = 60;
int title_w = MeasureText(title, title_size);
DrawText(title, (width - title_w) / 2, height / 2 - 130, title_size, RAYWHITE);
/* Resume button. */
Rectangle resume_btn = { width / 2 - 100, height / 2 - 20, 200, 50 };
bool resume_hover = CheckCollisionPointRec(GetMousePosition(), resume_btn);
DrawRectangleRec(resume_btn,
resume_hover ? (Color){ 80, 80, 130, 255 } : (Color){ 50, 50, 90, 255 });
DrawRectangleLinesEx(resume_btn, 2, RAYWHITE);
DrawText("RESUME", resume_btn.x + 53, resume_btn.y + 12, 30, RAYWHITE);
/* Quit button. */
Rectangle quit_btn = { width / 2 - 100, height / 2 + 50, 200, 50 };
bool quit_hover = CheckCollisionPointRec(GetMousePosition(), quit_btn);
DrawRectangleRec(quit_btn,
quit_hover ? (Color){ 130, 50, 50, 255 } : (Color){ 90, 30, 30, 255 });
DrawRectangleLinesEx(quit_btn, 2, RAYWHITE);
DrawText("QUIT", quit_btn.x + 68, quit_btn.y + 12, 30, RAYWHITE);
/* Handle clicks. */
if (resume_hover && IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
return PAUSE_RESUME;
if (quit_hover && IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
return PAUSE_QUIT;
return PAUSE_NONE;
}
/* --- MAIN --- */
int main(int argc, char *argv[])
{
(void)argc;
(void)argv;
const int screen_width = 720;
const int screen_height = 480;
InitWindow(screen_width, screen_height, "prj tiny");
SetTargetFPS(60);
SetExitKey(KEY_NULL); /* Take over ESC ourselves. */
/* 3D Camera. */
Camera3D camera = { 0 };
camera.position = (Vector3){ 0.0f, 2.0f, 8.0f };
camera.target = (Vector3){ 0.0f, 1.0f, 0.0f };
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
camera.fovy = 60.0f;
camera.projection = CAMERA_PERSPECTIVE;
Star stars[STAR_COUNT];
InitStars(stars, STAR_COUNT, screen_width, screen_height);
bool paused = false;
DisableCursor(); /* Capture mouse for camera look. */
while (!WindowShouldClose())
{
/* --- INPUT --- */
if (IsKeyPressed(KEY_ESCAPE))
{
paused = !paused;
if (paused)
EnableCursor();
else
DisableCursor();
}
if (!paused)
UpdateCamera(&camera, CAMERA_FIRST_PERSON);
/* --- DRAW --- */
float time = (float)GetTime();
BeginDrawing();
ClearBackground(BLACK);
DrawSky(screen_width, screen_height);
DrawStars(stars, STAR_COUNT, time);
BeginMode3D(camera);
DrawPlane((Vector3){ 0, 0, 0 }, (Vector2){ 256, 256 }, BEIGE);
DrawCube((Vector3){ 0, 1.05f, 0 }, 2, 2, 2, RED);
EndMode3D();
if (!paused)
{
DrawCrosshair(screen_width, screen_height);
DrawText("prj tiny - ESC to pause", 10, 10, 20, DARKGRAY);
}
else
{
PauseAction action = DrawPauseMenu(screen_width, screen_height);
if (action == PAUSE_RESUME)
{
paused = false;
DisableCursor();
}
else if (action == PAUSE_QUIT)
break;
}
EndDrawing();
}
CloseWindow();
return 0;
}
|