jag

tetoris_c

public

Small block game in C

Star0
Watch0
992df8d5d7cd35b10d9905261d23cc1a04c36699
1
ssh://git@git.jaglekon.de:30/jag/tetoris_c.git
source/main.cC327 lines6.1 KB
1
#include "main.h"
2
3
4
tetromino playfield[FULL_HEIGHT][FULL_WIDTH] = {};
5
6
uint8_t graying[FULL_HEIGHT][FULL_WIDTH] = {};
7
8
9
int main () {
10
  
11
12
  /* Setting up the seed */
13
  
14
  srand(time(NULL));
15
16
17
  /* Setting up terminal with termios */
18
  
19
  struct termios old, new;
20
21
  tcgetattr(STDIN_FILENO, &old);
22
  new = old;
23
24
  new.c_lflag &= ~(ECHO | ICANON);
25
  new.c_cc[VMIN] = 0;
26
  new.c_cc[VTIME] = 0;
27
28
  tcsetattr(STDIN_FILENO, TCSANOW, &new);
29
30
  struct winsize init_size, current_size;
31
  ioctl(STDOUT_FILENO, TIOCGWINSZ, &init_size);
32
  current_size = init_size;
33
34
  printf("\033[?25l\033[?1049h\033[2J\033[H");
35
36
37
  /* Polling */
38
39
  struct pollfd polling[1];
40
41
  polling[0].fd = 0;
42
  polling[0].events = POLLIN;
43
44
45
  /* Init */
46
47
  init_field();
48
49
  bool blink[FIELD_HEIGHT] = {};
50
51
  bool is_piece = false;
52
53
  bool paused = false;
54
55
  uint64_t paused_diff;
56
57
  piece current_piece = {};
58
  piece next_piece = init_piece((rand() % Z_PIECE) + 1);
59
60
  /* Game Loop */
61
62
  struct timespec start, current;
63
  clock_gettime(CLOCK_MONOTONIC_RAW, &start);
64
65
66
  uint8_t i, j;
67
  bool is_tetris = false;
68
69
  while (true) {
70
71
    int8_t move = 0;
72
    bool down = false;
73
    bool draw = false;
74
    bool rotate = false;
75
76
    clock_gettime(CLOCK_MONOTONIC_RAW, &current);
77
78
    uint64_t time_diff = 
79
      (current.tv_sec - start.tv_sec) * 1000000000ULL + 
80
      (current.tv_nsec - start.tv_nsec);
81
82
83
    /* Take care of the input */
84
85
    int is_poll = poll(polling, 1, paused ? -1 : 17);
86
87
    if (is_poll > 0 && polling[0].revents & POLLIN) {
88
89
      char buf[10] = {};
90
91
      if (read(STDIN_FILENO, buf, sizeof(buf)) > 0) {
92
        
93
        if (tolower(buf[0]) == 'q') {
94
          break;
95
        }
96
97
        if (tolower(buf[0]) == 'p') {
98
          if (paused) {
99
100
            time_diff = paused_diff;
101
102
            paused = false;
103
          } else {
104
105
            paused_diff = time_diff;
106
107
            draw_pause();
108
109
            paused = true;
110
          }
111
        }
112
113
114
        if (buf[0] == '\033' && buf[1] == '[') {
115
          
116
          switch (buf[2]) {
117
            case 'A':
118
              rotate = true;
119
              break;
120
            case 'B':
121
              down = true;
122
              break;
123
            case 'C':
124
              move = 1;
125
              break;
126
            case 'D':
127
              move = -1;
128
              break;
129
            default:
130
              break;
131
          }
132
        }
133
      }
134
    }
135
136
137
    if (is_tetris) {
138
139
      if (time_diff >= FRAME * BLINK && i < 4) { 
140
141
        time_diff -= time_diff % (FRAME * BLINK);
142
        start.tv_sec += time_diff / 1000000000ULL;
143
        start.tv_nsec += time_diff % 1000000000ULL;
144
 
145
        draw_board(current_piece, next_piece, (i % 2 == 0) ? NULL : blink, is_piece);
146
        i++;
147
      }
148
      
149
150
      if (i == 4) {
151
      
152
        int8_t j, k;
153
154
        for (j = 0; j < FIELD_HEIGHT; j++) {
155
          if (blink[j]) {
156
157
            for (k = j; k > 0; k--) {
158
              int8_t l;
159
          
160
              for (l = 0; l < FIELD_WIDTH; l++) {
161
                playfield[k][l + BORDER_WIDTH] = playfield[k - 1][l + BORDER_WIDTH];
162
                graying[k][l + BORDER_WIDTH] = graying[k - 1][l + BORDER_WIDTH];
163
164
              }
165
            }
166
          }
167
        }
168
169
        i = 0;
170
        is_tetris = false;
171
      }
172
173
      continue;
174
    }
175
176
177
    if (paused)
178
      continue;
179
180
181
    /* Creates new piece */
182
183
    
184
    if (!is_piece) {
185
      current_piece = next_piece;
186
      next_piece = init_piece((rand() % Z_PIECE) + 1);
187
      is_piece = true;
188
      draw = true;
189
    }
190
191
192
    /* Move piece */
193
194
    if (move != 0) {
195
      if (
196
        current_piece.x + move >= 0 && 
197
        current_piece.x + move + current_piece.size <= FULL_WIDTH
198
      ) {
199
       
200
        piece moved_piece = current_piece;
201
        moved_piece.x += move;
202
203
        if (valid_position(moved_piece)) {
204
          current_piece.x += move;
205
          draw = true;
206
        }
207
      }
208
    }
209
210
211
    /* Piece rotates */
212
    
213
    if (rotate && current_piece.positions > 1) {
214
      
215
      piece rotated = current_piece;
216
217
      rotated.rotation = (current_piece.rotation + 1) % (current_piece.positions);
218
      
219
      if (valid_position(rotated)) {
220
        current_piece = rotated;
221
        draw = true;
222
      }
223
    } 
224
    
225
226
    /* Piece falls */
227
228
    if (time_diff >= (FRAME * FALL) || down) {
229
      current_piece.y++;
230
      
231
      time_diff -= time_diff % (FRAME * FALL);
232
      start.tv_sec += time_diff / 1000000000ULL;
233
      start.tv_nsec += time_diff % 1000000000ULL;
234
235
      uint8_t j, k;
236
237
      for (j = 0; j < FULL_HEIGHT; j++) {
238
        for (k = 0; k < FULL_WIDTH; k++) {
239
          if (playfield[j][k] != EMPTY) {
240
            
241
            if (graying[j][k] < 255) {
242
              graying[j][k] += 1;
243
            }
244
245
          } else {
246
            graying[j][k] = 0;
247
          }
248
249
        }
250
      }
251
252
      draw = true;
253
    }
254
    
255
256
257
    /* When a piece is stuck */
258
259
    if (!valid_position(current_piece)) {
260
261
      int8_t j, k;
262
263
      for (j = 0; j < current_piece.size; j++) {
264
        for (k = 0; k < current_piece.size; k++) {
265
          
266
          if (current_piece.piece[j][k]) {
267
            
268
            coord solid = find_direction(current_piece, k, j);
269
270
            playfield[current_piece.y - 1 + solid.y][current_piece.x + solid.x] = current_piece.name;
271
          }
272
        }
273
      }
274
      is_piece = false;
275
      draw = true;
276
    }
277
278
279
    /* Looks if there is a tetris */
280
281
    int8_t j, k;
282
283
    for (j = FIELD_HEIGHT - 1; j >= 0; j--) {
284
285
      uint8_t blocked = 0;
286
287
      for (k = 0; k < FIELD_WIDTH; k++) {
288
        if (playfield[j][k + BORDER_WIDTH] != EMPTY)
289
          blocked++;
290
      }
291
292
      if (blocked == 10) {
293
        
294
        blink[j] = true;
295
        is_tetris = true;  
296
      } else {
297
        blink[j] = false;
298
      }
299
    }
300
301
302
    /* Looks for game over */
303
304
    for (j = 0; j < FIELD_WIDTH; j++) {
305
      if (playfield[TOP_GAP][j + BORDER_WIDTH] > 0) {
306
        draw_board(current_piece, next_piece, NULL, is_piece);
307
        sleep(2);
308
        printf("\033[2J\033[H");
309
        printf("HAHA LOSER\n");
310
        sleep(1);
311
        goto end;
312
      }
313
    }
314
315
316
    if (draw)
317
      draw_board(current_piece, next_piece, NULL, is_piece);
318
  }
319
320
end:
321
322
  printf("\033[?1049l\033[?25h");
323
324
  tcsetattr(STDIN_FILENO, TCSANOW, &old);
325
326
  return 0;
327
}