-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSGRenderUART0Term.c
247 lines (224 loc) · 6.47 KB
/
SGRenderUART0Term.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
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
/// Space Game (name not final)
/// @file SGRenderUART0Term.c
/// Responsible for the terminal backend for rendering. TODO make the output buffered and modify SGRender interface for this chg
/// @author Koen Komeya <[email protected]>
/// @date 11/30/2017 ~
/// [Final project for CMPE-250 (Section 4: Thursday 11 AM - 1 PM)]
//-----------------------------------------------------------------------------
/// Imports
#include <string.h>
#include "SGRender.h"
#include "SpaceGame.h"
#include "UART0CharIO.h"
///----------------------------------------------------------------------------
/// @addtogroup Defines
/// @{
/// Escape character 0x1B (ESC)
#define ESCAPE_CHAR '\x1B'
/// Escape character 0x1B (ESC) as string
#define ESCAPE_STR "\x1B"
/// ANSI CSI Sequence start
#define ANSI_CSI ESCAPE_STR "["
/// Terminal Width
#define TERM_WIDTH 80
/// Terminal Width minus 1
#define TWM1 79
/// Terminal Height
#define TERM_HEIGHT 40
/// Terminal Height minus 1
#define THM1 39
/// @}
///----------------------------------------------------------------------------
/// @addtogroup Functional Macros
/// @{
/// Helper functional macro to #STRINGIFY
/// Don't use.
#define STRINGIFY_HELP(x) #x
///Stringifies x.
///@param x token to stringify
#define STRINGIFY(x) STRINGIFY_HELP(x)
/// @}
///----------------------------------------------------------------------------
/// @addtogroup Functions
/// @{
/// Moves the terminal cursor to the specified location.
/// @param xc the x position of the terminal.
/// @param yc the y position of the terminal. (0 is top)
static void setCursorPos(int xc, int yc){
PutChar(ESCAPE_CHAR);
PutChar('[');
PutNumU(yc);
PutChar(';');
PutNumU(xc);
PutChar('f');
}
/// Initializes the renderer.
/// @pre Requires Button to be functional.
void initRenderer(void){
Init_UART0_IRQ();
while (0){
PUTSTRLIT(ANSI_CSI "3J"); //Clear Screen
PUTSTRLIT(ANSI_CSI "H"); //Position cursor at top left.
PUTSTRLIT(ANSI_CSI STRINGIFY(TWM1) "C"); //Move TWM1 right
PUTSTRLIT(ANSI_CSI STRINGIFY(THM1) "B"); //Move THM1 down
PUTSTRLIT(ANSI_CSI "6n"); //Request cursor position
PUTSTRLIT(ANSI_CSI "H"); //Position cursor at top left.
PUTSTRLIT("If this message does not disappear shortly, this terminal " \
"does not support ANSI escape sequences. PuTTY is an example " \
"of a terminal that supports ANSI escape sequences.");
char curbuf[16]; //Read cursor position
GETSTRLIN(curbuf);
clearScreen(); //Clear Screen
PUTSTRLIT(ANSI_CSI "H"); //Position cursor at top left.
if (strcmp(curbuf, ANSI_CSI STRINGIFY(TERM_WIDTH) ";" \
STRINGIFY(TERM_HEIGHT) "R") != 0){
PUTSTRLIT("Please resize your terminal window to be 80x40 then press " \
"either button.");
while (!CheckAndClearPress()); //Wait for button press
continue;
}
//TODO Check for too large screens
}
}
static inline char returnAngled(pos_t xd, pos_t yd, char up, char down, char left, char right){
if (yd > 0){
if (xd > 0){
if (xd > yd) return right;
else return up;
} else {
if (-xd > yd) return left;
else return up;
}
} else {
if (xd > 0){
if (xd > -yd) return right;
else return down;
} else {
if (xd < yd) return left;
else return down;
}
}
}
/// Draw an alien
/// @param a Alien to draw
/// @param x x-ccordinate of cluster location
/// @param y y-coordinate of clusterlocation
void drawAlien(Alien *a, pos_t x, pos_t y){
uint8_t f1 = a->flags1;
if (!(f1 & AL_F1_ALIVE_MASK)) return;
//TODO better sprites
uint8_t t = a->type;
if (f1 & (AL_F1_ATTACK_MASK | AL_F1_SWOOP_MASK)) { //Swooping or attacking
int xt = (a->xPos >> 8) + 1;
int yt = 40 - (a->yPos >> 8);
setCursorPos(xt, yt);
if (f1 & AL_F1_DYING_MASK){ //Exploding?
PUTSTRLIT(ANSI_CSI "37m");
PutChar('X');
return;
}
PUTSTRLIT(ANSI_CSI "31m");
char alienChar; //@ & % - potential chars
if (t == AT_Grunt) alienChar = returnAngled(a->xPos, a->yPos, 'A', 'V', '<', '>');
else if (t == AT_Cruiser) alienChar = returnAngled(a->xPos, a->yPos, 'M', 'W', 'E', '3');
else if (t == AT_Battleship) alienChar = '#';
PutChar(alienChar);
} else {
int xt = (x >> 8) + 1;
int yt = 40 - (y >> 8);
setCursorPos(xt, yt);
if (f1 & AL_F1_DYING_MASK){ //Exploding?
PUTSTRLIT(ANSI_CSI "37m");
PutChar('X');
return;
}
PUTSTRLIT(ANSI_CSI "31m");
char alienChar; //@ & % - potential chars
if (t == AT_Grunt) alienChar = 'V';
else if (t == AT_Cruiser) alienChar = 'W';
else if (t == AT_Battleship) alienChar = '#';
PutChar(alienChar);
}
}
// A
//Player sprite: <H>
/// Draw player at the specified position
/// It is assumed the player is positioned so there will be no clipping
void drawPlayer(pos_t x, pos_t y){
int xt = (x >> 8) + 1;
int yt = 40 - ((y - 0x80) >> 8);
PUTSTRLIT(ANSI_CSI "34m");
setCursorPos(xt, yt - 1);
PutChar('A');
setCursorPos(xt - 1, yt);
PutChar('<');
PutChar('H');
PutChar('>');
}
/// @brief Draw an E1 at the specified position and direction
void drawE1(int8_t e1flags1, pos_t x, pos_t y, pos_t xd, pos_t yd){
int xt = (x >> 8) + 1;
int yt = 40 - (y >> 8);
if (e1flags1 & E1_F1_SIDE_MASK)
PUTSTRLIT(ANSI_CSI "1;36m");
else
PUTSTRLIT(ANSI_CSI "1;33m");
setCursorPos(xt, yt);
if (yd < 0){
xd = -xd;
yd = -yd;
}
if (xd > yd * 2 || xd < -yd * 2) PutChar('-');
else if ( yd <= 4 * xd) PutChar('/');
else if (-yd >= 4 * xd) PutChar('\\');
else PutChar('|');
}
void drawLevelScreen(int level, int lives, int score){
clearScreen();
PUTSTRLIT(ANSI_CSI "0m");
setCursorPos(34, 15);
PUTSTRLIT("LEVEL");
setCursorPos(44, 15);
PutNumU(level);
setCursorPos(32, 16);
PUTSTRLIT("------------------");
setCursorPos(50, 38);
PUTSTRLIT("Lives");
setCursorPos(57, 38);
PutNumU(lives);
setCursorPos(50, 39);
PUTSTRLIT("Score");
setCursorPos(57, 39);
PutNumU(score);
}
void drawMainMenu(void);
void drawGameOverScreen(int score){
clearScreen();
setCursorPos(36, 15);
PUTSTRLIT(ANSI_CSI "31m");
PUTSTRLIT("GAME OVER");
setCursorPos(36, 15);
setCursorPos(35, 39);
PUTSTRLIT(ANSI_CSI "0m");
PUTSTRLIT("Score");
setCursorPos(42, 39);
PutNumU(score);
}
void drawIntroduction1(void);
void drawInstructions(void);
void clearScreen(void){
PUTSTRLIT(ANSI_CSI "2J"); //Clear Screen
}
void flushScreen(void){
__asm("CPSID I");
Flush();
__asm("CPSIE I");
}
void drawScore(int score){
setCursorPos(68, 40);
PUTSTRLIT(ANSI_CSI "0m");
PUTSTRLIT("Score");
setCursorPos(74, 40);
PutNumU(score);
}
/// @}