source: soft/giet_vm/applications/raycast/game.c @ 824

Last change on this file since 824 was 711, checked in by alain, 9 years ago

Improve the user interface.

File size: 8.1 KB
RevLine 
[673]1#include "game.h"
2#include "disp.h"
3#include <math.h>
[708]4#include <stdio.h>
[673]5
[708]6//////////////////////////////
7// Game Maps
8//////////////////////////////
[673]9
10static Map map[] =
11{
12    { // map0
13        .tile =
14        {
15            {1, 0, 0, 0, 0, 1, 0, 0, 1, 1},
16            {0, 0, 0, 0, 0, 1, 0, 0, 0, 2},
17            {0, 0, 0, 0, 1, 0, 0, 0, 1, 1},
18            {0, 0, 0, 1, 3, 0, 3, 0, 0, 0},
19            {0, 0, 0, 1, 3, 0, 3, 0, 0, 1},
20            {0, 0, 0, 1, 3, 0, 3, 0, 0, 0},
21            {0, 0, 0, 1, 1, 0, 3, 0, 0, 1},
22            {4, 0, 0, 0, 0, 0, 1, 0, 0, 0},
23            {4, 0, 0, 0, 0, 0, 1, 0, 0, 1},
24            {0, 4, 4, 4, 4, 0, 0, 0, 1, 0}
[711]25
26//          {1,  ,  ,  ,  , 1,  ,  , 1, 1},
27//          { ,  ,  ,  ,  , 1,  ,  ,  , 2},
28//          { ,  ,  ,  , 1,  ,  ,  , 1, 1},
29//          { ,  ,  , 1, 3,  , 3,  ,  ,  },
30//          { ,  ,  , 1, 3,  , 3,  ,  , 1},
31//          { ,  ,  , 1, 3,  , 3,  ,  ,  },
32//          { ,  ,  , 1, 1,  , 3,  ,  , 1},
33//          {4,  ,  ,  ,  ,  , 1,  ,  ,  },
34//          {4,  ,  ,  ,  ,  , 1,  ,  , 1},
35//          { , 4, 4, 4, 4,  ,  ,  , 1,  }
36       },
[673]37        .w = 10,
38        .h = 10,
39        .startX = 2.f,
40        .startY = 3.f,
41        .startDir = 70.f * M_PI / 180.f
42    },
43    { // map1
44        .tile =
45        {
46            {0, 1, 0, 1, 0, 3, 0, 0, 0, 0},
47            {0, 1, 0, 0, 0, 3, 0, 0, 0, 0},
48            {0, 0, 0, 1, 0, 3, 0, 0, 0, 0},
49            {1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
50            {4, 2, 4, 1, 3, 0, 3, 3, 3, 0},
51            {4, 0, 0, 1, 3, 3, 3, 0, 0, 0},
52            {4, 0, 0, 1, 3, 0, 0, 0, 3, 3},
53            {4, 0, 0, 0, 0, 0, 4, 0, 0, 3},
54            {4, 0, 0, 0, 0, 0, 4, 0, 0, 0},
55            {4, 4, 4, 4, 4, 4, 4, 0, 1, 0}
56        },
57        .w = 10,
58        .h = 10,
59        .startX = 0.5f,
60        .startY = 0.5f,
61        .startDir = 90.f * M_PI / 180.f
62    },
63    { // map2
64        .tile =
65        {
66            {4, 4, 4, 4, 4, 4, 4, 0, 0, 0},
67            {0, 0, 0, 0, 0, 0, 0, 0, 3, 0},
68            {3, 0, 0, 0, 4, 4, 4, 0, 0, 0},
69            {3, 0, 0, 4, 0, 0, 0, 1, 1, 0},
70            {3, 0, 4, 2, 0, 0, 0, 0, 0, 0},
71            {3, 0, 4, 2, 0, 0, 0, 0, 0, 0},
72            {3, 0, 0, 4, 0, 0, 0, 1, 1, 0},
73            {3, 0, 0, 0, 4, 4, 4, 0, 0, 0},
74            {0, 0, 0, 0, 0, 0, 0, 0, 3, 0},
75            {4, 4, 4, 4, 4, 4, 4, 0, 0, 0}
76        },
77        .w = 10,
78        .h = 10,
79        .startX = 4.5f,
80        .startY = 5.f,
81        .startDir = 0.f * M_PI / 180.f
82    },
83};
84
[708]85////////////////////////////
86// extern variables
87////////////////////////////
[673]88
[708]89extern Game         game;
[673]90
[708]91//////////////////////
[673]92// Local functions
[708]93//////////////////////
[673]94
[708]95////////////////////////////////////
[673]96static void gameOnBlockHit(int type)
97{
[708]98    giet_tty_printf("\n[RAYCAST] Fatal collision, killed...\n");
99    game.exit = 1;
[673]100}
101
[708]102///////////////////////////////////////////////
[673]103static void gameCollision(float opx, float opy)
104{
[708]105    static unsigned int collided_x = 0;
106    static unsigned int collided_y = 0;
[673]107
[708]108    float               px = game.player.x;
109    float               py = game.player.y;
110    int                 fpx = floor(px);
111    int                 fpy = floor(py);
112    unsigned int        colliding_x = 0;
113    unsigned int        colliding_y = 0;
114    int                 collide_type_x = 0;
115    int                 collide_type_y = 0;
116    int                 type;
[673]117
118    // Check for x axis collisions
[708]119    if      ((type = gameLocate(floor(px + COLLIDE_GAP), fpy))) 
120    {
121        colliding_x = 1, collide_type_x = type;
[673]122        game.player.x = fpx - COLLIDE_GAP + 1;
123    }
[708]124    else if ((type = gameLocate(floor(px - COLLIDE_GAP), fpy))) 
125    {
126        colliding_x = 1, collide_type_x = type;
[673]127        game.player.x = fpx + COLLIDE_GAP;
128    }
129
130    // Check for y axis collisions
[708]131    if      ((type = gameLocate(fpx, floor(py + COLLIDE_GAP)))) 
132    {
133        colliding_y = 1, collide_type_y = type;
[673]134        game.player.y = fpy - COLLIDE_GAP + 1;
135    }
[708]136    else if ((type = gameLocate(fpx, floor(py - COLLIDE_GAP)))) 
137    {
138        colliding_y = 1, collide_type_y = type;
[673]139        game.player.y = fpy + COLLIDE_GAP;
140    }
141
142    // Check if we're inside a wall
[708]143    if ((type = gameLocate(fpx, fpy))) 
144    {
145        colliding_x   = 1   , collide_type_x = type;
146        colliding_y   = 1   , collide_type_y = type;
147        game.player.x = opx , game.player.y = opy;
[673]148    }
149
150    // Take action when the player hits a block
151    if (colliding_x && !collided_x)
152        gameOnBlockHit(collide_type_x);
153    if (colliding_y && !collided_y)
154        gameOnBlockHit(collide_type_y);
155
156    collided_x = colliding_x;
157    collided_y = colliding_y;
158}
159
[708]160/////////////////////////
161// Exported functions
162/////////////////////////
163
164///////////////
165void gameInit()
[673]166{
[708]167    game.mapId      = 0;
168    game.map        = &map[0];
169    game.player.x   = game.map->startX;
170    game.player.y   = game.map->startY;
171    game.player.dir = game.map->startDir;
172    game.timeLeft   = TIME_TOTAL;
173    game.exit       = 0;
[673]174}
175
[708]176//////////////////
177void gameControl()
[673]178{
[708]179    // Only six commands are accepted:
180    // - key Q         : quit game
[711]181    // - key UP        : move forward
182    // - key DOWN      : move backward
183    // - key RIGHT     : move right
184    // - key LEFT      : move left
185    // - key SPACE     : continue
186    // All other keys are ignored
187    // Several<move> can be made before <continue>
[708]188
189    char c;
190    unsigned int state = 0;
191    unsigned int done  = 0;
192
193    // display prompt
194    giet_tty_printf("\n[RAYCAST] > " );
195
196    // get one command
197    while ( done == 0 )
198    {
199        // get one character       
200        giet_tty_getc( &c );
201
202        if (state == 0) // first character
203        {
204            if      (c == 0x1B)         // ESCAPE : possible player move 
205            {
206                state = 1;
207            }
208            else if (c == 0x71)         // quit game
209            {
210                game.exit = 1;
211                done = 1;
212                giet_tty_printf("QUIT\n");
213            }
[711]214            else if (c == 0x20 )        // continue
[708]215            {
216                done = 1;
217                giet_tty_printf("\n");
218            }
219        } 
220        else if (state == 1) // previous character was ESCAPE
221        {
222            if      (c == 0x5B)        // BRAKET : possible player move
223            {
224                state = 2;
225            }
[711]226            else if (c == 0x20 )        // continue
[708]227            {
228                done = 1;
229                giet_tty_printf("\n");
230            }
231        }
232        else  // previous characters were ESCAPE,BRACKET
233        {
234            if      (c == 0x41)        // UP arrow <=> forward move
235            {
236                game.player.x += PLAYER_MOVE * cos(game.player.dir);
237                game.player.y += PLAYER_MOVE * sin(game.player.dir);
238                giet_tty_printf("GO ");
239                state = 0;
240            }
241            else if (c == 0x42)        // DOWN arrow <=> backward move
242            {
243                game.player.x -= PLAYER_MOVE * cos(game.player.dir);
244                game.player.y -= PLAYER_MOVE * sin(game.player.dir);
245                giet_tty_printf("BACK ");
246                state = 0;
247            }
248            else if (c == 0x43)        // RIGHT arrow <=> turn right     
249            {
250                game.player.dir += PLAYER_ROT;
251                giet_tty_printf("RIGHT ");
252                state = 0;
253            }
254            else if (c == 0x44)        // LEFT arrow <=> turn left     
255            {
256                game.player.dir -= PLAYER_ROT;
257                giet_tty_printf("LEFT ");
258                state = 0;
259            }
[711]260            else if (c == 0x20 )        // continue
[708]261            {
262                done = 1;
263                giet_tty_printf("\n");
264            }
265        }
266    }  // end while
267   
268    // check new position
269    int hit = gameLocate( game.player.x , game.player.y );
270    if ( hit )  gameOnBlockHit( hit );
[673]271}
272
[708]273////////////////////////////
[673]274int gameLocate(int x, int y)
275{
276    if ((x < 0 || x >= game.map->w) ||
[708]277        (y < 0 || y >= game.map->h)) 
278    {
[673]279        // Outside the map bounds
280        return 1;
281    }
282
283    return game.map->tile[y][x];
284}
285
[708]286///////////////
[673]287void gameTick()
288{
289    game.timeLeft--;
290
[708]291    if (game.timeLeft == 0) 
292    {
293        game.exit = 1;
[673]294    }
295}
[683]296
Note: See TracBrowser for help on using the repository browser.