source: cacatris/trunk/src/main.c @ 1213

Last change on this file since 1213 was 1213, checked in by Sam Hocevar, 16 years ago
  • Restore terminal properties upon program exit.
  • Property svn:keywords set to Id
File size: 8.9 KB
Line 
1/*
2 *   $Id: main.c 1213 2006-10-22 13:28:34Z sam $
3 *
4 *   This program is free software; you can redistribute it and/or
5 *   modify it under the terms of the Do What The Fuck You Want To
6 *   Public License, Version 2, as published by Sam Hocevar. See
7 *   http://sam.zoy.org/wtfpl/COPYING for more details.
8 */
9
10#include "config.h"
11#include "cacatris.h"
12
13int main(int argc, char *argv[])
14{
15    static caca_display_t *dp;
16    signed   int x=(FIELD_WIDTH/2)-1, y=0, rotation=0, old_x=0, old_y=0, old_rotation=0;
17    unsigned int current_piece, next_piece, baseTime = 0;
18    unsigned char last_has_landed = 1;
19    unsigned char left = 0, right = 0, down = 0;
20    unsigned long long int curTime = 0;
21    unsigned int speed = 16;
22    unsigned int fixed_y = 0;
23    unsigned char lost = 0;
24    unsigned int  score = 0;
25    unsigned int lines = 0;
26    unsigned char level = 0;
27    unsigned char total_lines = 0;
28
29    field = cucul_create_canvas(0, 0);
30    infos = cucul_create_canvas(0, 0);
31    screen = cucul_create_canvas(0, 0);
32
33    dp = caca_create_display(screen);
34    if(!dp)
35        return 1;
36
37    cucul_set_canvas_size(infos, INFO_WIDTH, cucul_get_canvas_height(screen));
38    cucul_set_canvas_size(field, FIELD_CANVAS_WIDTH, FIELD_CANVAS_HEIGHT);
39
40    caca_set_display_time(dp, 20000);
41
42    /* Our playfied */
43    memset(playfield, 0, FIELD_WIDTH*FIELD_HEIGHT);
44
45
46    /* Set current and next piece to random */
47    current_piece = cucul_rand(0, 6);
48    next_piece = cucul_rand(0, 6);
49
50
51    for(;;)
52    {
53        caca_event_t ev;
54        left = 0; right = 0; down = 0;
55
56        /* Handle events */
57        while(caca_get_event(dp, CACA_EVENT_KEY_PRESS
58                             | CACA_EVENT_QUIT, &ev, 0))
59        {
60            if(ev.type == CACA_EVENT_QUIT)
61                goto end;
62            switch(ev.data.key.ch)
63            {
64            case CACA_KEY_ESCAPE:
65                goto end;
66                break;
67            case CACA_KEY_UP:
68                if(movable(current_piece, x, y, (rotation+1)&0x03))
69                {
70                    rotation++;
71                    rotation = rotation&0x03;
72                }
73                break;
74            case CACA_KEY_DOWN:
75                down = 1;
76                break;
77            case CACA_KEY_LEFT:
78                left = 1;
79                break;
80            case CACA_KEY_RIGHT:
81                right = 1;
82                break;
83            }
84        }
85
86        if(lost) continue;
87
88
89        if(y==0 && has_landed(current_piece, x ,y, rotation)) {
90            lost = 1;
91            continue;
92        }
93
94        if(left)
95        {
96            if(movable(current_piece, x-1, y, rotation))
97                x--;
98        }
99        if(right)
100        {
101            if(movable(current_piece, x+1, y, rotation))
102                x++;
103        }
104        if(down)
105        {
106            while((movable(current_piece, x, y, rotation)) && (!has_landed(current_piece, x, y, rotation)))
107            {
108                fixed_y+=speed;
109                y = fixed_y>>8;
110            }
111        }
112
113        if(!last_has_landed)
114        {
115            last_has_landed = 0;
116        }
117        else
118        {
119            last_has_landed = 0;
120        }
121
122
123        old_x = x;
124        old_y = y;
125        old_rotation = rotation;
126
127        fixed_y+=speed; /* Fixed point */
128        y = fixed_y>>8;
129
130
131
132        /* Populate info canvas */
133        infos_populate(infos, score, level, total_lines);
134        /* Draw everything on playfield */
135        put_piece(current_piece, x ,y, rotation);
136        playfield_draw(field);
137        remove_piece(current_piece, x ,y, rotation);
138        /* blit infos canvas into general one */
139        cucul_blit(screen, (cucul_get_canvas_width(screen))  - INFO_WIDTH, 0, infos, NULL);
140        /* blit playfield canvas into general one */
141        cucul_blit(screen, 18, 0, field, NULL);
142
143        caca_refresh_display(dp);
144
145
146        if(has_landed(current_piece, x ,y, rotation))
147        {
148            put_piece(current_piece, x ,y, rotation);
149            fixed_y = 0;
150            x = (FIELD_WIDTH/2)-1;
151            current_piece = next_piece;
152            rotation = 0;
153            next_piece = cucul_rand(0, 6);
154            last_has_landed = 1;
155            old_x = x;
156            old_y = 0;
157        }
158
159        lines = maybe_remove_line();
160        if(lines)
161        {
162            score += points[level+(lines-1)*LEVEL_COUNT];
163            total_lines += lines;
164            if(total_lines >=10 && level<=10)
165            {
166                level++;
167                total_lines = 0;
168                speed+=4;
169                memset(playfield, 0, FIELD_WIDTH*FIELD_HEIGHT);
170            }
171        }
172
173        if(!baseTime)
174        {
175            baseTime = caca_get_display_time(dp);
176        }
177        curTime+=caca_get_display_time(dp);
178    }
179
180 end:
181    caca_free_display(dp);
182    cucul_free_canvas(field);
183    cucul_free_canvas(infos);
184    cucul_free_canvas(screen);
185
186    return 0;
187}
188
189
190void infos_populate(cucul_canvas_t *inf, unsigned int score,
191                    unsigned char level, unsigned char total)
192{
193    unsigned int i;
194    char scoreline[256];
195    char levelline[256];
196    char totalline[256];
197
198    sprintf(scoreline, " Score    :   %05d ", score);
199    sprintf(levelline, " Level    :   %02d    ", level);
200    sprintf(totalline, " Lines    :   %02d    ", total);
201
202    cucul_set_color(inf, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLUE);
203    cucul_putstr(inf, 0, 0, "      =Cacatris=    ");
204    cucul_putstr(inf, 0, 1, "  Arrows  :    move ");
205    cucul_putstr(inf, 0, 2, "  Space :      pouf ");
206    cucul_putstr(inf, 0, 3, " __________________ ");
207    cucul_putstr(inf, 0, 4, "                    ");
208    cucul_putstr(inf, 0, 5, levelline);
209    cucul_putstr(inf, 0, 6, scoreline);
210    cucul_putstr(inf, 0, 7, totalline);
211    cucul_putstr(inf, 0, 8, " Time     :   XX:XX ");
212
213    for(i = 8; i < cucul_get_canvas_height(inf); i++)
214    {
215        cucul_putstr(inf, 0, i,"                     ");
216    }
217}
218
219
220void playfield_draw(cucul_canvas_t *canvas)
221{
222    unsigned int x, y;
223    float ox=0, oy=0;
224    float incx = (float)FIELD_WIDTH / (float)FIELD_CANVAS_WIDTH;
225    float incy = (float)FIELD_HEIGHT / (float)FIELD_CANVAS_HEIGHT;
226
227    for(y = 0; y < FIELD_CANVAS_WIDTH; y++)
228    {
229        for(x = 0; x < FIELD_CANVAS_WIDTH; x++)
230        {
231            unsigned int oxi = (unsigned int) ox;
232            unsigned int oyi = (unsigned int) oy;
233            unsigned int c = playfield[oxi+oyi*FIELD_WIDTH];
234            if(c) {
235                cucul_set_color(canvas, CUCUL_COLOR_BLACK, blocks_palette[c-1]);
236                cucul_putchar(canvas, x, y, ' ');
237            } else {
238                cucul_set_color(canvas, CUCUL_COLOR_BLACK, CUCUL_COLOR_DARKGRAY);
239                cucul_putchar(canvas, x, y, ' ');
240
241            }
242            ox+=incx;
243        }
244        ox = 0;
245        oy+=incy;
246    }
247}
248
249
250void put_piece(unsigned int id, unsigned int x, unsigned int y, unsigned int rot)
251{
252    unsigned int ix, iy;
253    piece_t *p = &pieces[(id*4)+rot];
254
255    for(iy = 0; iy < p->h; iy++)
256        for(ix = 0; ix < p->w; ix++)
257            if(p->data[ix+iy*4])
258                playfield[(ix+x)+(iy+y)*FIELD_WIDTH] = p->data[ix+iy*4]*p->color;
259}
260
261void remove_piece(unsigned int id, unsigned int x, unsigned int y, unsigned int rot)
262{
263    unsigned int ix, iy;
264    piece_t *p = &pieces[(id*4)+rot];
265
266    for(iy = 0; iy < p->h; iy++)
267        for(ix = 0; ix < p->w; ix++)
268            if(ix<p->w && iy<p->h)
269                if(p->data[ix+iy*4])
270                    playfield[(ix+x)+(iy+y)*FIELD_WIDTH] = 0;
271}
272
273unsigned char movable(unsigned int id, int x, int y, unsigned int rot)
274{
275    piece_t *p = &pieces[(id*4)+rot];
276    unsigned int ix, iy;
277    int w, h;
278
279    w = p->w;
280    h = p->h;
281
282
283    if(y>=(signed)(FIELD_HEIGHT-p->h)) {
284        return 0;
285    }
286
287
288    if(x>=0 && (x+w<=FIELD_WIDTH) && y<(FIELD_HEIGHT-(signed)h))
289    {
290        for(iy = 0; iy < p->h; iy++)
291            for(ix = 0; ix < p->w; ix++)
292                if((p->data[ix+iy*4]!=0) && (playfield[(ix+x)+(iy+y)*FIELD_WIDTH]!=0)) {
293                    return 0;
294                }
295
296        return 1;
297    }
298
299    return 0;
300}
301
302unsigned char has_landed(unsigned int id, unsigned int x, unsigned int y, unsigned int rot)
303{
304    piece_t *p = &pieces[(id*4)+rot];
305    unsigned int ix, iy;
306    unsigned int w, h;
307
308    w = p->w;
309    h = p->h;
310
311    if(y>=(FIELD_HEIGHT-p->h)) {
312        return 1;
313    }
314    y++;
315    if(x>=0 && (x+w<=FIELD_WIDTH) && y<=(FIELD_HEIGHT-h))
316    {
317        for(iy = 0; iy < p->h && (iy+y<FIELD_HEIGHT) ; iy++)
318            for(ix = 0; (ix < p->w) && (ix+x<FIELD_WIDTH); ix++)
319                if((p->data[ix+iy*4]!=0) && (playfield[(ix+x)+(iy+y)*FIELD_WIDTH]!=0)) {
320                    return 1;
321                }
322
323        return 0;
324    }
325    return 1;
326}
327
328
329unsigned char maybe_remove_line(void)
330{
331    int y, x, v=0;
332    unsigned char *p = playfield;
333    int ret = 0;
334
335    for(y = 0; y < FIELD_HEIGHT ; y++)
336    {
337        for(x = 0; x < FIELD_WIDTH ; x++)
338            if(*p++)
339                v++;
340        if(v==FIELD_WIDTH) {
341            memmove(&playfield[FIELD_WIDTH], playfield, (y)*FIELD_WIDTH);
342            ret++;
343        }
344        v=0;
345    }
346
347    return ret;
348}
Note: See TracBrowser for help on using the repository browser.