-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdisplay.c
105 lines (93 loc) · 3.05 KB
/
display.c
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
/* A small graphics module for line drawing, based on SDL.
SDL_MAIN_HANDLED is defined before including SDL.h, and a setbuf call is
included in newDisplay, in case this is used as the starting point for a
program in a difficult environmaent. */
#include "display.h"
#define SDL_MAIN_HANDLED
#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
// Set safe mode to true for environments with poor OpenGL support.
// Set it to false otherwise for greater efficiency.
enum { safe = true };
// If SDL fails, print the SDL error message, and stop the program.
void fail() {
fprintf(stderr, "Error: %s\n", SDL_GetError());
SDL_Quit();
exit(1);
}
// Check return values from SDL functions (Integer and Pointer versions). These
// make error handling less intrusive.
int I(int n) { if (n < 0) fail(); return n; }
void *P(void *p) { if (p == NULL) fail(); return p; }
// Create a renderer - in software for safety or hardware for efficiency.
void createRenderer(display *d) {
if (safe) {
SDL_Surface *surface = P(SDL_GetWindowSurface(d->window));
d->renderer = P(SDL_CreateSoftwareRenderer(surface));
}
else d->renderer = P(SDL_CreateRenderer(d->window, -1, 0));
}
// Make recent changes appear on screen.
void show(display *d) {
if (safe) I(SDL_UpdateWindowSurface(d->window));
else SDL_RenderPresent(d->renderer);
}
// Create a new display object.
display *newDisplay(char *title, int width, int height) {
setbuf(stdout, NULL);
display *d = malloc(sizeof(display));
I(SDL_Init(SDL_INIT_VIDEO));
int x = SDL_WINDOWPOS_UNDEFINED, y = SDL_WINDOWPOS_UNDEFINED;
d->window = P(SDL_CreateWindow(title, x, y, width, height, 0));
createRenderer(d);
I(SDL_SetRenderDrawColor(d->renderer, 255, 255, 255, 255));
I(SDL_RenderClear(d->renderer));
show(d);
I(SDL_SetRenderDrawColor(d->renderer, 0, 0, 0, 255));
return d;
}
void line(display *d, int x0, int y0, int x1, int y1) {
I(SDL_RenderDrawLine(d->renderer, x0, y0, x1, y1));
show(d);
}
void colour(display *d, int rgba) {
Uint8 r = (rgba >> 24) & 0xFF;
Uint8 g = (rgba >> 16) & 0xFF;
Uint8 b = (rgba >> 8) & 0xFF;
Uint8 a = rgba & 0xFF;
I(SDL_SetRenderDrawColor(d->renderer, r, g, b, a));
}
void clear(display *d) {
Uint8 r, g, b, a;
I(SDL_GetRenderDrawColor(d->renderer, &r, &g, &b, &a));
I(SDL_SetRenderDrawColor(d->renderer, 255, 255, 255, 255));
I(SDL_RenderClear(d->renderer));
show(d);
I(SDL_SetRenderDrawColor(d->renderer, r, g, b, a));
}
void pause(display *d, int ms) {
if (ms > 0) SDL_Delay(ms);
}
char key(display *d) {
SDL_Event event_structure;
SDL_Event *event = &event_structure;
while (true) {
int r = SDL_WaitEvent(event);
if (r == 0) fail();
if (event->type == SDL_QUIT) {
SDL_Quit();
exit(0);
}
else if (event->type == SDL_KEYUP) {
int sym = event->key.keysym.sym;
return (char)sym;
}
}
}
void end(display *d) {
SDL_Delay(500);
SDL_Quit();
}