]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/services/gfx/mw/v2_0/src/demos/nanox/slider.c
Initial revision
[karo-tx-redboot.git] / packages / services / gfx / mw / v2_0 / src / demos / nanox / slider.c
1 /* Copyright (c) 2000 Simon Wood <simon@mungewell.uklinux.net>
2  *
3  * This program is licensed under the same terms that Microwindows
4  * and Nano-X are licensed under.  See the file LICENSE accompanying
5  * this distribution.
6  */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12
13 #define MWINCLUDECOLORS
14 #include "nano-X.h"
15
16 /* set up size of the grid */
17 #define WIDTH_IN_TILES  4
18 #define HEIGHT_IN_TILES 4
19 #define MAX_TILES       (WIDTH_IN_TILES * HEIGHT_IN_TILES)
20 #define USE_IMAGE       1
21
22 static  int     value[WIDTH_IN_TILES][HEIGHT_IN_TILES];
23 static  int     calc_width, calc_height;
24 static  int     tile_width = 40;
25 static  int     tile_height = 40;
26
27 #if USE_IMAGE
28 static  void *  image_addr;
29 static  int     using_image = 1;
30 static  GR_WINDOW_ID    image;          /* storage area for image */
31 #endif
32
33 static  GR_WINDOW_ID    master;         /* id for whole window */
34 static  GR_WINDOW_ID    buttons;        /* id for buttons */
35 static  GR_WINDOW_ID    tiles;          /* id for play area */
36 static  GR_GC_ID        gc1;            /* graphics context for text */
37
38 static  int     value[WIDTH_IN_TILES][HEIGHT_IN_TILES];
39
40 /* function prototypes */
41 static  void    HandleEvents();
42 static  void    RefreshWindow();
43 static  void    RandomiseTiles();
44 static  void    MoveTile();
45 static  void    DrawTile();
46
47 int
48 main(int argc,char **argv)
49 {
50         if (GrOpen() < 0) {
51                 fprintf(stderr, "cannot open graphics\n");
52                 exit(1);
53         }
54                 
55         gc1 = GrNewGC();
56
57 #if USE_IMAGE
58         image = GrNewWindow(GR_ROOT_WINDOW_ID, 300, 0, (WIDTH_IN_TILES * tile_width),
59                 (HEIGHT_IN_TILES * tile_height), 4, BLACK, WHITE);
60
61         if(argc != 2)
62                 /* No image specified, use numered tiles */
63                 using_image = 0;
64         else {
65                 /* need to find out image size.... */
66                 image_addr = malloc(4 * (WIDTH_IN_TILES * tile_width) *
67                         (HEIGHT_IN_TILES * tile_height) );
68
69                 image = GrNewPixmap((WIDTH_IN_TILES * tile_width),
70                         (HEIGHT_IN_TILES * tile_height), image_addr);
71  
72                 GrDrawImageFromFile(image, gc1, 0, 0,
73                         GR_IMAGE_MAX_SIZE, GR_IMAGE_MAX_SIZE, argv[1], 0);
74         }
75 #endif
76         
77         /* calculate size of tile area */
78         calc_width = 10 + (WIDTH_IN_TILES * tile_width);
79         calc_height = 15 + 35 + (HEIGHT_IN_TILES * tile_height);
80 #if 0
81         /* enforce minimum size */
82         if (calc_width < 240) calc_width=240;
83         if (calc_height < 320) calc_height=320;
84 #endif
85         master = GrNewWindow(GR_ROOT_WINDOW_ID, 0, 0, calc_width, calc_height, 1, RED, WHITE);
86         buttons = GrNewWindow((GR_WINDOW_ID) master, 5, 5, (calc_width - 5), 35, 1, RED, RED);
87
88         tiles = GrNewWindow((GR_WINDOW_ID) master, (calc_width/2) - (WIDTH_IN_TILES * tile_width /2),
89                 45 + ((calc_height - 50)/2) - (HEIGHT_IN_TILES * tile_height /2),
90                 (WIDTH_IN_TILES * tile_width), (HEIGHT_IN_TILES * tile_height), 1, RED, RED);
91
92         GrMapWindow(master);
93         GrMapWindow(buttons);
94         GrMapWindow(tiles);
95
96         /* set random seed */
97         srandom((int) getpid());
98
99         RandomiseTiles();
100         
101         GrSelectEvents(master, GR_EVENT_MASK_EXPOSURE|GR_EVENT_MASK_CLOSE_REQ);
102         GrSelectEvents(buttons, GR_EVENT_MASK_BUTTON_DOWN); 
103         GrSelectEvents(tiles, GR_EVENT_MASK_BUTTON_DOWN);
104
105         RefreshWindow();
106
107         while (GR_TRUE) {
108                 GR_EVENT event;
109
110                 GrGetNextEvent(&event);
111                 HandleEvents(&event);
112         }
113 }
114
115
116 /*
117  * Read the next event and handle it.
118  */
119 void
120 HandleEvents(GR_EVENT *ep)
121 {
122         switch (ep->type) {
123                 case GR_EVENT_TYPE_BUTTON_DOWN:
124                         if (ep->button.wid == buttons) {
125                                 if (ep->button.x < (calc_width/2)) {
126                                         /* 'Again' */
127                                         RandomiseTiles();
128                                         RefreshWindow();
129                                 } else {
130                                         /* 'Quit' */
131                                         GrClose();
132 #if USE_IMAGE
133                                         if (using_image)
134                                                 free(image_addr);
135 #endif
136                                         exit(0);
137                                 }
138                         }
139
140                         if (ep->button.wid == tiles) {
141                                 /* Try to move selected tile */
142                                 MoveTile( (int)(ep->button.x / tile_width),
143                                         (int)(ep->button.y / tile_height) );
144                         }
145                         break;
146
147                 case GR_EVENT_TYPE_EXPOSURE:
148                         RefreshWindow();
149                         break;
150                 case GR_EVENT_TYPE_CLOSE_REQ:
151                         GrClose();
152                         exit(0);
153         }
154
155 }
156
157 void
158 RefreshWindow()
159 {
160         int xpos, ypos;
161
162         GrSetGCForeground(gc1, WHITE);
163         GrSetGCBackground(gc1, RED);
164
165         /* draw the buttons */
166         GrRect(buttons, gc1, 0, 0, (calc_width - 12)/2, 34);
167         GrRect(buttons, gc1, (calc_width - 8)/2, 0, (calc_width - 12)/2, 34);
168
169 #if 0   /* for when center align text works */
170         GrText(buttons, gc1, (calc_width - 10)/4, 22, "Again", 5, 0);
171         GrText(buttons, gc1, (calc_width - 10)*3/4, 22, "Quit", 4, 0);
172 #else
173         GrText(buttons, gc1, 5, 22, "Again", 5, 0);
174         GrText(buttons, gc1, (calc_width / 2) + 5, 22, "Quit", 4, 0);
175 #endif
176         
177         /* draw the tiles */
178         for (ypos=0; ypos< HEIGHT_IN_TILES; ypos++){
179                 for (xpos=0; xpos< WIDTH_IN_TILES; xpos++){
180                         DrawTile(xpos, ypos);
181                 }
182         }
183 }
184
185 void
186 RandomiseTiles()
187 {
188         int count, xpos, ypos;
189
190         /* allocate all the numbers in order  1..MAX_TILES */
191         for (ypos=0; ypos< HEIGHT_IN_TILES; ypos++){
192                 for (xpos=0; xpos< WIDTH_IN_TILES; xpos++){
193                         value[xpos][ypos] = 1 + xpos + (WIDTH_IN_TILES * ypos);
194                 }
195         }
196
197         /* position of 'hole' */
198         xpos = WIDTH_IN_TILES - 1;
199         ypos = HEIGHT_IN_TILES - 1;
200
201         /* randomly slide them around, ALL games can therefore solved - so no excusses!! */
202         for (count=0; count< MAX_TILES * 1000; count++){
203                 switch(random() % 4) {
204                         case 0:
205                                 if (ypos < HEIGHT_IN_TILES - 1) {
206                                         value[xpos][ypos] = value[xpos][ypos+1];
207                                         ypos++;
208                                         value[xpos][ypos] = MAX_TILES;
209                                 }
210                                 break;
211                         case 1:
212                                 if (xpos > 0) {
213                                         value[xpos][ypos] = value[xpos - 1][ypos];
214                                         xpos--;
215                                         value[xpos][ypos] = MAX_TILES;
216                                 }
217                                 break;
218                         case 2:
219                                 if (ypos > 0) {
220                                         value[xpos][ypos] = value[xpos][ypos - 1];
221                                         ypos--;
222                                         value[xpos][ypos] = MAX_TILES;
223                                 }
224                                 break;
225                         case 3:
226                                 if (xpos < WIDTH_IN_TILES - 1) {
227                                         value[xpos][ypos] = value[xpos + 1][ypos];
228                                         xpos++;
229                                         value[xpos][ypos] = MAX_TILES;
230                                 }
231                                 break;
232                 }
233         }
234 }
235
236 void
237 MoveTile(xpos, ypos)
238         int xpos, ypos;
239 {
240         /* check all possible moves to see if there is the blank (N,E,S,W) */
241         if (ypos > 0 && value[xpos][ypos - 1] == MAX_TILES) {
242                 value[xpos][ypos - 1] = value[xpos][ypos];
243                 value[xpos][ypos] = MAX_TILES;
244                 DrawTile(xpos, ypos - 1);
245                 DrawTile(xpos, ypos);
246         }
247
248         if (xpos < (WIDTH_IN_TILES - 1) && value[xpos + 1][ypos] == MAX_TILES) {
249                 value[xpos + 1][ypos] = value[xpos][ypos];
250                 value[xpos][ypos] = MAX_TILES;
251                 DrawTile(xpos + 1, ypos);
252                 DrawTile(xpos, ypos);
253         }
254
255         if (ypos < (HEIGHT_IN_TILES - 1) && value[xpos][ypos + 1] == MAX_TILES) {
256                 value[xpos][ypos + 1] = value[xpos][ypos];
257                 value[xpos][ypos] = MAX_TILES;
258                 DrawTile(xpos, ypos + 1);
259                 DrawTile(xpos, ypos);
260         }
261
262         if (xpos > 0 && value[xpos - 1][ypos] == MAX_TILES) {
263                 value[xpos - 1][ypos] = value[xpos][ypos];
264                 value[xpos][ypos] = MAX_TILES;
265                 DrawTile(xpos - 1, ypos);
266                 DrawTile(xpos, ypos);
267         }
268
269         /* check for a winner */
270         if (value[WIDTH_IN_TILES - 1][HEIGHT_IN_TILES - 1] == MAX_TILES) {
271                 int winner = 0;
272                 for (ypos=0; ypos< HEIGHT_IN_TILES; ypos++){
273                         for (xpos=0; xpos< WIDTH_IN_TILES; xpos++){
274                                 if (value[xpos][ypos] == winner + 1)
275                                         winner++;
276                                 else 
277                                         winner=0;
278                         }
279                 }
280                 if (winner == MAX_TILES) {
281                         /* Do winning screen */
282                         int loop = MAX_TILES;
283                         for(loop=0; loop < MAX_TILES; loop++) {
284                                 for(winner=0; winner < (MAX_TILES - loop) ; winner++) {
285
286                                         /* move tiles around */
287                                         xpos = winner % WIDTH_IN_TILES;
288                                         ypos = (int)(winner/WIDTH_IN_TILES);
289                                         value[xpos][ypos] = loop + winner + 1; 
290                                         DrawTile(winner % WIDTH_IN_TILES, (int)(winner/WIDTH_IN_TILES));
291                                 }
292                                 GrFlush();
293                                 for(winner=0; winner < 10000000 ; winner++);
294                                         /* delay loop */
295                         }
296                         /* Print message */
297                         GrSetGCForeground(gc1, WHITE);
298                         GrSetGCBackground(gc1, RED);
299                         GrText(tiles, gc1, ((WIDTH_IN_TILES * tile_width)/2) - 40, (HEIGHT_IN_TILES * tile_height)/2, "Well Done!!", -1, 0);
300                 }
301                                 
302         }
303 }
304
305
306 void
307 DrawTile(xpos, ypos)
308         int xpos, ypos;
309 {
310         char text[]="00";
311
312         /* blank out old tile */
313         GrSetGCForeground(gc1, RED);
314         GrFillRect(tiles, gc1, (xpos* tile_width), (ypos*tile_height), tile_width, tile_height);
315
316         if (value[xpos][ypos] != MAX_TILES ) {
317                 /* re-draw tile and number */
318                 GrSetGCForeground(gc1, WHITE);
319                 GrSetGCBackground(gc1, RED);
320                 GrRect(tiles, gc1, (xpos*tile_width), (ypos*tile_height), tile_width, tile_height);
321                 
322 #if USE_IMAGE
323                 if (using_image) {
324                         /* copy from image window */
325                         GrCopyArea(tiles, gc1, 1 + (xpos*tile_width), 1 + (ypos*tile_height), 
326                                 tile_width - 2, tile_height - 2, image,
327                                 1 + (((value[xpos][ypos] - 1) % WIDTH_IN_TILES) * tile_width), 
328                                 1 + (((int)(value[xpos][ypos] - 1) / WIDTH_IN_TILES) * tile_height), 0);
329                 } else {
330 #endif
331                         /* label the tile with a number */
332                         if (value[xpos][ypos] > 9)
333                                 text[0] = 48 + (int)(value[xpos][ypos]/10);
334                         else
335                                 text[0] = 32;
336         
337                         text[1] = 48 + value[xpos][ypos] % 10;
338                         
339                         GrText(tiles, gc1, (xpos*tile_width) + (tile_width /2) - 5, (ypos*tile_height) + (tile_height/2) + 5, &text, -1, 0);
340 #if USE_IMAGE
341                 }
342 #endif
343         }
344 }