jag

tetoris_c

public

Small block game in C

Star0
Watch0
1f869eaffc8c1c2781cecc1ddc3acdfa35e03eca
1
ssh://git@git.jaglekon.de:30/jag/tetoris_c.git
main.cC277 lines5.1 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
  piece current_piece = {};
52
53
54
  /* Game Loop */
55
56
  struct timespec start, current;
57
  clock_gettime(CLOCK_MONOTONIC_RAW, &start);
58
59
60
  uint8_t i;
61
  bool is_tetris = false;
62
63
  while (true) {
64
65
    int8_t move = 0;
66
    bool down = false;
67
    bool draw = false;
68
    bool rotate = false;
69
70
    clock_gettime(CLOCK_MONOTONIC_RAW, &current);
71
72
    uint64_t time_diff = (current.tv_sec - start.tv_sec) * 1000000000ULL + (current.tv_nsec - start.tv_nsec);
73
74
75
    /* Take care of the input */
76
77
    int is_poll = poll(polling, 1, 17);
78
79
    if (is_poll > 0 && polling[0].revents & POLLIN) {
80
81
      char buf[10] = {};
82
83
      if (read(STDIN_FILENO, buf, sizeof(buf)) > 0) {
84
        if (buf[0] == 'q') {
85
          break;
86
        }
87
88
        if (buf[0] == '\033' && buf[1] == '[') {
89
          
90
          switch (buf[2]) {
91
            case 'A':
92
              rotate = true;
93
              break;
94
            case 'B':
95
              down = true;
96
              break;
97
            case 'C':
98
              move = 1;
99
              break;
100
            case 'D':
101
              move = -1;
102
              break;
103
            default:
104
              break;
105
          }
106
        }
107
      }
108
    }
109
110
111
    if (is_tetris) {
112
113
      if (time_diff >= FRAME * BLINK && i < 4) { 
114
115
        time_diff -= time_diff % (FRAME * BLINK);
116
        start.tv_sec += time_diff / 1000000000ULL;
117
        start.tv_nsec += time_diff % 1000000000ULL;
118
 
119
        draw_board(current_piece, (i % 2 == 0) ? NULL : blink, is_piece);
120
        i++;
121
      }
122
123
      if (i == 4) {
124
      
125
        int8_t j, k;
126
127
        for (j = 0; j < FIELD_HEIGHT; j++) {
128
          if (blink[j]) {
129
130
            for (k = j; k > 0; k--) {
131
              int8_t l;
132
          
133
              for (l = 0; l < FIELD_WIDTH; l++) {
134
                playfield[k][l + BORDER_WIDTH] = playfield[k - 1][l + BORDER_WIDTH];
135
              }
136
            }
137
          }
138
        }
139
140
        i = 0;
141
        is_tetris = false;
142
      }
143
144
      continue;
145
    }
146
147
148
149
    /* Creates new piece */
150
151
    
152
    if (!is_piece) {
153
      current_piece = init_piece((rand() % Z_PIECE) + 1);
154
      is_piece = true;
155
      draw = true;
156
    }
157
158
159
    /* Move piece */
160
161
    if (move != 0) {
162
      if (
163
        current_piece.x + move >= 0 && 
164
        current_piece.x + move + current_piece.size <= FULL_WIDTH
165
      ) {
166
       
167
        piece moved_piece = current_piece;
168
        moved_piece.x += move;
169
170
        if (valid_position(moved_piece)) {
171
          current_piece.x += move;
172
          draw = true;
173
        }
174
      }
175
    }
176
177
178
    /* Piece rotates */
179
    
180
    if (rotate && current_piece.positions > 1) {
181
      
182
      piece rotated = current_piece;
183
184
      rotated.rotation = (current_piece.rotation + 1) % (current_piece.positions);
185
      
186
      if (valid_position(rotated)) {
187
        current_piece = rotated;
188
        draw = true;
189
      }
190
    } 
191
    
192
193
    /* Piece falls */
194
195
    if (time_diff >= (FRAME * FALL) || down) {
196
      current_piece.y++;
197
      
198
      time_diff -= time_diff % (FRAME * FALL);
199
      start.tv_sec += time_diff / 1000000000ULL;
200
      start.tv_nsec += time_diff % 1000000000ULL;
201
    
202
203
      draw = true;
204
    }
205
206
207
    /* When a piece is stuck */
208
209
    if (!valid_position(current_piece)) {
210
211
      int8_t j, k;
212
213
      for (j = 0; j < current_piece.size; j++) {
214
        for (k = 0; k < current_piece.size; k++) {
215
          
216
          if (current_piece.piece[j][k]) {
217
            
218
            coord solid = find_direction(current_piece, k, j);
219
220
            playfield[current_piece.y - 1 + solid.y][current_piece.x + solid.x] = current_piece.name;
221
          }
222
        }
223
      }
224
      is_piece = false;
225
      draw = true;
226
    }
227
228
229
    /* Looks if there is a tetris */
230
231
    int8_t j, k;
232
233
    for (j = FIELD_HEIGHT - 1; j >= 0; j--) {
234
235
      uint8_t blocked = 0;
236
237
      for (k = 0; k < FIELD_WIDTH; k++) {
238
        if (playfield[j][k + BORDER_WIDTH] != EMPTY)
239
          blocked++;
240
      }
241
242
      if (blocked == 10) {
243
        
244
        blink[j] = true;
245
        is_tetris = true;  
246
      } else {
247
        blink[j] = false;
248
      }
249
    }
250
251
252
    /* Looks for game over */
253
254
    for (j = 0; j < FIELD_WIDTH; j++) {
255
      if (playfield[TOP_GAP][j + BORDER_WIDTH] > 0) {
256
        draw_board(current_piece, NULL, is_piece);
257
        sleep(2);
258
        printf("\033[2J\033[H");
259
        printf("HAHA LOSER\n");
260
        sleep(1);
261
        goto end;
262
      }
263
    }
264
265
266
    if (draw)
267
      draw_board(current_piece, NULL, is_piece);
268
  }
269
270
end:
271
272
  printf("\033[?1049l\033[?25h");
273
274
  tcsetattr(STDIN_FILENO, TCSANOW, &old);
275
276
  return 0;
277
}