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

Last change on this file since 1125 was 1125, checked in by Jean-Yves Lamoureux, 14 years ago
  • Scoring and levels implementation (following standard Tetris(c)(tm) rules)
  • Property svn:keywords set to Id
File size: 8.6 KB
Line 
1/*
2 *   $Id: main.c 1125 2006-09-28 08:29:45Z jylam $
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);
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+=2;
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
182
183    return 0;
184}
185
186
187void infos_populate(cucul_canvas_t *inf, unsigned int score, unsigned char level)
188{
189    unsigned int i;
190    char scoreline[1024];
191    char levelline[1024];
192
193    sprintf(scoreline, " Score    :   %05d ", score);
194    sprintf(levelline, " Level    :   %02d    ", level);
195
196    cucul_set_color(inf, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLUE);
197    cucul_putstr(inf, 0, 0, "      =Cacatris=    ");
198    cucul_putstr(inf, 0, 1, "  Arrows  :    move ");
199    cucul_putstr(inf, 0, 2, "  Space :      pouf ");
200    cucul_putstr(inf, 0, 3, " __________________ ");
201    cucul_putstr(inf, 0, 4, "                    ");
202    cucul_putstr(inf, 0, 5, levelline);
203    cucul_putstr(inf, 0, 6, scoreline);
204    cucul_putstr(inf, 0, 7, " Time     :   XX:XX ");
205
206    for(i = 7; i < cucul_get_canvas_height(inf); i++)
207    {
208        cucul_putstr(inf, 0, i,"                     ");
209    }
210}
211
212
213void playfield_draw(cucul_canvas_t *canvas)
214{
215    unsigned int x, y;
216    float ox=0, oy=0;
217    float incx = (float)FIELD_WIDTH / (float)FIELD_CANVAS_WIDTH;
218    float incy = (float)FIELD_HEIGHT / (float)FIELD_CANVAS_HEIGHT;
219
220    for(y = 0; y < FIELD_CANVAS_WIDTH; y++)
221    {
222        for(x = 0; x < FIELD_CANVAS_WIDTH; x++)
223        {
224            unsigned int oxi = (unsigned int) ox;
225            unsigned int oyi = (unsigned int) oy;
226            unsigned int c = playfield[oxi+oyi*FIELD_WIDTH];
227            if(c) {
228                cucul_set_color(canvas, CUCUL_COLOR_BLACK, blocks_palette[c-1]);
229                cucul_putchar(canvas, x, y, ' ');
230            } else {
231                cucul_set_color(canvas, CUCUL_COLOR_BLACK, CUCUL_COLOR_DARKGRAY);
232                cucul_putchar(canvas, x, y, ' ');
233
234            }
235            ox+=incx;
236        }
237        ox = 0;
238        oy+=incy;
239    }
240}
241
242
243void put_piece(unsigned int id, unsigned int x, unsigned int y, unsigned int rot)
244{
245    unsigned int ix, iy;
246    piece_t *p = &pieces[(id*4)+rot];
247
248    for(iy = 0; iy < p->h; iy++)
249        for(ix = 0; ix < p->w; ix++)
250            if(p->data[ix+iy*4])
251                playfield[(ix+x)+(iy+y)*FIELD_WIDTH] = p->data[ix+iy*4]*p->color;
252}
253
254void remove_piece(unsigned int id, unsigned int x, unsigned int y, unsigned int rot)
255{
256    unsigned int ix, iy;
257    piece_t *p = &pieces[(id*4)+rot];
258
259    for(iy = 0; iy < p->h; iy++)
260        for(ix = 0; ix < p->w; ix++)
261            if(ix<p->w && iy<p->h)
262                if(p->data[ix+iy*4])
263                    playfield[(ix+x)+(iy+y)*FIELD_WIDTH] = 0;
264}
265
266unsigned char movable(unsigned int id, int x, int y, unsigned int rot)
267{
268    piece_t *p = &pieces[(id*4)+rot];
269    unsigned int ix, iy;
270    int w, h;
271
272    w = p->w;
273    h = p->h;
274
275
276    if(y>=(signed)(FIELD_HEIGHT-p->h)) {
277        return 0;
278    }
279
280
281    if(x>=0 && (x+w<=FIELD_WIDTH) && y<(FIELD_HEIGHT-(signed)h))
282    {
283        for(iy = 0; iy < p->h; iy++)
284            for(ix = 0; ix < p->w; ix++)
285                if((p->data[ix+iy*4]!=0) && (playfield[(ix+x)+(iy+y)*FIELD_WIDTH]!=0)) {
286                    return 0;
287                }
288
289        return 1;
290    }
291
292    return 0;
293}
294
295unsigned char has_landed(unsigned int id, unsigned int x, unsigned int y, unsigned int rot)
296{
297    piece_t *p = &pieces[(id*4)+rot];
298    unsigned int ix, iy;
299    unsigned int w, h;
300
301    w = p->w;
302    h = p->h;
303
304    if(y>=(FIELD_HEIGHT-p->h)) {
305        return 1;
306    }
307    y++;
308    if(x>=0 && (x+w<=FIELD_WIDTH) && y<=(FIELD_HEIGHT-h))
309    {
310        for(iy = 0; iy < p->h && (iy+y<FIELD_HEIGHT) ; iy++)
311            for(ix = 0; (ix < p->w) && (ix+x<FIELD_WIDTH); ix++)
312                if((p->data[ix+iy*4]!=0) && (playfield[(ix+x)+(iy+y)*FIELD_WIDTH]!=0)) {
313                    return 1;
314                }
315
316        return 0;
317    }
318    return 1;
319}
320
321
322unsigned char maybe_remove_line(void)
323{
324    int y, x, v=0;
325    unsigned char *p = playfield;
326    int ret = 0;
327
328    for(y = 0; y < FIELD_HEIGHT ; y++)
329    {
330        for(x = 0; x < FIELD_WIDTH ; x++)
331            if(*p++)
332                v++;
333        if(v==FIELD_WIDTH) {
334            memmove(&playfield[FIELD_WIDTH], playfield, (y)*FIELD_WIDTH);
335            ret++;
336        }
337        v=0;
338    }
339
340    return ret;
341}
Note: See TracBrowser for help on using the repository browser.