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

Last change on this file since 3150 was 2981, checked in by Sam Hocevar, 14 years ago

Port cacatris to the unified libcaca 0.99.beta15 API.

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