-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.c
More file actions
183 lines (148 loc) · 4.09 KB
/
Copy pathmain.c
File metadata and controls
183 lines (148 loc) · 4.09 KB
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#include <stdlib.h>
#include <unistd.h>
#include "shoot.h"
// where everything goes down
void ingame(void);
// where everything is stitched together
// to actually work
int main(int argc, char** argv) {
// check if we have any argument to
// change the amount of levels we want
if (argc > 1) levels = atoi(argv[1]);
if (levels == 0) levels = LVL_MAX; // 0 being atoi()'s error return value
// initiate our screen, but
// run some checks first
initscr();
// get the
int ymax = getmaxy(stdscr); // tallest the screen can be, and
int xmax = getmaxx(stdscr); // the widest
// there has to be enough to fit our game in, 53x85 chars
if (ymax <= 53 || xmax <= 85) {
endwin();
printf("%s\n%s\n",
"Your terminal isn't at least 53x85 characters!",
"Please resize your window and try again.");
exit(1);
}
noecho(); // do NOT show the user's keystrokes here
curs_set(0); // nor the cursor, this is a game after all
raw(); // and don't do any input buffering
// finally, render where the game itself is shown
game = create_win(50, 80, (ymax-50)/2, (xmax-80)/2, true);
// tell curses not to perform any extra cursor
// movement
leaveok(game, TRUE);
// which's where we'll first show the title screen
// for a cool little boot
titlescr();
// and now the HUDs, just a little below the main window
player.hud = create_win(2, 12, (ymax+50)/2, (xmax-12)/2, false);
enemy.hud = create_win(1, 07, (ymax-52)/2, (xmax-07)/2, false);
// then get to the game itself
ingame();
// and once the above is done, we
// are done
endgame(false);
return 0;
}
// where the actual game happens
void ingame(void) {
// start with a curtain-kind
// of transition
transition(T_CURTAIN);
// create sprites for the
player.win = newspr(player); // player
enemy.win = newspr(enemy); // and opponent
// boundary system for the player sprite
const unsigned char bound[5] = {
player.h, // upper boundary
(49 - player.h), // lower boundary
(player.w / 2) - (player.w % 2), // leftmost boundary
(79 - enemy.w), // rightmost boundary
player.h // shooting boundary
};
// show their respective HPs
health(player);
health(enemy);
// and the level display
counter();
// input setup
keypad(game, TRUE); // support for arrow keys
nodelay(game, TRUE);
// ^ "disable" the delay responsible for
// making wgetch() blocking
// now, the main loop
while (level <= levels) {
key = wgetch(game);
switch(key) {
// yes, you can use Vim keys here
case KEY_UP:
case 'k':
if (player.y > bound[0]) --player.y;
break;
case KEY_DOWN:
case 'j':
if (player.y < bound[1]) ++player.y;
break;
case KEY_LEFT:
case 'h':
if (player.x > bound[2]) --player.x;
break;
case KEY_RIGHT:
case 'l':
if (player.x < bound[3]) ++player.x;
break;
case 'z': // 'z' for shooting!
if (player.y > bound[4])
enemy.hp = shoot(player, enemy);
// ^ this function not only shoots but also kills, so
// the enemy's HP is tracked here as well
// if we killed our opponent···
if (enemy.hp == 0) {
++level; // go to the next level
newlvl(); // and render it
}
// if not, try again!
break;
case 'p': // 'p' for pausing!
pausegm();
break;
case 'q': // 'q' for exiting!
delwin(player.win);
delwin(player.hud);
delwin(enemy.win);
delwin(enemy.hud);
// ^ but end all game-related windows first
// now get back to main()
return;
break;
default: break;
}
// update the sprite
mvspr(player);
// if the player has already
// finished the game, skip all
// of this!
if (level > levels) break;
// and now it's the enemy's turn!
enemctrl();
// what to do whenever the player dies:
// NULL their sprite's window,
// and go to a nice little menu
if (player.hp == 0) gameover();
// reduce lag by discarding all
// input done within the
flushinp();
napms(50);
// small ^^ ms time frame
}
// delete the player's window for
// a clean finish
delwin(player.win);
// do a little cleanup by
// closing the HUDs
delwin(enemy.hud);
delwin(player.hud);
// and go to the end screen
ending();
}