GCC Code Coverage Report


Directory: src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 63 / 0 / 63
Functions: 100.0% 10 / 0 / 10
Branches: 100.0% 20 / 0 / 20

ufo/src/ufo.c
Line Branch Exec Source
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright (c) 2026 Manuel Hernández Méndez
5 *
6 * Authors:
7 * Manuel Hernández Méndez <maherme.dev@gmail.com>
8 */
9
10 #include "ufo.h"
11 #include "graph.h"
12 #include "graphGlutCallbacks.h"
13 #include "physic.h"
14 #include "utils.h"
15 #include <stdbool.h>
16 #include <stdlib.h>
17
18 #define UFO_WIDTH 16
19 #define UFO_HEIGHT 8
20
21 struct ufo_instance_t
22 {
23 sprite_t sprite;
24 direction_t direction;
25 long long time_to_appear;
26 bool alive;
27 };
28
29 static struct ufo_instance_t ufo;
30
31 static const char ufoImage[UFO_HEIGHT][UFO_WIDTH][NUM_RGBA_CHANNELS] = {
32 {B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B},
33 {B, B, B, B, R, R, R, R, R, R, R, R, B, B, B, B},
34 {B, B, B, R, R, R, R, R, R, R, R, R, R, B, B, B},
35 {B, B, B, R, B, R, B, R, R, B, R, B, R, B, B, B},
36 {B, R, R, R, R, R, R, R, R, R, R, R, R, R, R, B},
37 {R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R},
38 {B, B, B, B, B, R, R, R, R, R, R, B, B, B, B, B},
39 {B, B, B, B, B, B, B, R, R, B, B, B, B, B, B, B},
40 };
41
42 static void
43 2 calculateDirection(ufo_t ufo)
44 {
45 2 double random = (double)rand() / RAND_MAX;
46 2 int random_direction = (random < 0.5) ? 0 : 1;
47
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 1 time.
2 if (random_direction)
48 {
49 1 ufo->direction = RIGHT;
50 }
51 else
52 {
53 1 ufo->direction = LEFT;
54 }
55 2 }
56
57 static void
58 2 calculateStartingCoord(ufo_t ufo)
59 {
60
2/2
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 4 taken 1 time.
2 if (ufo->direction == RIGHT)
61 {
62 1 ufo->sprite.x = -ufo->sprite.width;
63 }
64 else
65 {
66 1 ufo->sprite.x = GAME_WIDTH;
67 }
68
69 2 ufo->sprite.y = GAME_HEIGHT - 16;
70 2 }
71
72 ufo_t
73 2 ufoCreate(void)
74 {
75 2 ufo_t inst = &ufo;
76 2 calculateDirection(inst);
77 2 inst->sprite.width = UFO_WIDTH;
78 2 inst->sprite.height = UFO_HEIGHT;
79 2 inst->sprite.image = (const char *)ufoImage;
80 2 inst->sprite.pixels_to_move = 1;
81 2 inst->sprite.time_to_move = 1000 / 60 * NS_PER_MS;
82 2 inst->time_to_appear = 5 * NS_PER_S;
83 2 calculateStartingCoord(inst);
84 2 inst->sprite.max_movement.right = GAME_WIDTH + inst->sprite.width + 1;
85 2 inst->sprite.max_movement.left = -(inst->sprite.width + 1);
86 2 inst->sprite.layer = LAYER_GAME_OBJECTS;
87 2 inst->sprite.visible = true;
88 2 graphUpdateTimeSprite(&inst->sprite);
89 2 graphRegisterPrint(&inst->sprite);
90 2 inst->alive = true;
91
92 2 return inst;
93 }
94
95 void
96 2 ufoDestroy(ufo_t ufo)
97 {
98
2/2
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 4 taken 1 time.
2 if (!ufo)
99 {
100 1 return;
101 }
102
103 1 sprite_t *ufo_sprite = graphGetSprite((base_t *)ufo);
104 1 graphUnregisterPrint(ufo_sprite);
105 1 ufo->alive = false;
106 }
107
108 bool
109 4 ufoAlive(ufo_t ufo)
110 {
111
4/4
✓ Branch 2 → 3 taken 3 times.
✓ Branch 2 → 5 taken 1 time.
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 2 times.
4 return ufo && ufo->alive;
112 }
113
114 direction_t
115 3 ufoGetDirection(const ufo_t ufo)
116 {
117
2/2
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 4 taken 2 times.
3 if (!ufo)
118 {
119 1 return INVALID_DIR;
120 }
121 2 return ufo->direction;
122 }
123
124 bool
125 6 ufoCheckForMoving(ufo_t ufo)
126 {
127
4/4
✓ Branch 2 → 3 taken 5 times.
✓ Branch 2 → 4 taken 1 time.
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 4 times.
6 if (!ufo || !ufo->alive)
128 {
129 2 return false;
130 }
131
132
2/2
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 7 taken 3 times.
4 if (ufo->time_to_appear == 0)
133 {
134 1 return true;
135 }
136
137
2/2
✓ Branch 8 → 9 taken 1 time.
✓ Branch 8 → 10 taken 2 times.
3 if (!utilsCheckTimeout(ufo->sprite.last_update, ufo->time_to_appear))
138 {
139 1 return false;
140 }
141 else
142 {
143 2 ufo->time_to_appear = 0;
144 }
145
146 2 return true;
147 }
148
149 #ifdef UNIT_TESTING
150 #include <string.h>
151
152 ufo_t
153 7 helperUT_ufoGetInstance(void)
154 {
155 7 ufo_t inst = &ufo;
156 7 memset(inst, 0, sizeof(*inst));
157
158 7 inst->alive = true;
159
160 7 return inst;
161 }
162
163 void
164 2 helperUT_ufoSetAlive(ufo_t ufo, bool alive)
165 {
166 2 ufo->alive = alive;
167 2 }
168
169 void
170 3 helperUT_ufoSetTimeToAppear(ufo_t ufo, long long time)
171 {
172 3 ufo->time_to_appear = time;
173 3 }
174 #endif /* UNIT_TESTING */
175