jag

tetoris_c

public

Small block game in C

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