Subversion Repositories freemyipod

Rev

Rev 652 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
652 theseven 1
//
2
//
3
//    Copyright 2011 TheSeven
4
//
5
//
6
//    This file is part of emCORE.
7
//
8
//    emCORE is free software: you can redistribute it and/or
9
//    modify it under the terms of the GNU General Public License as
10
//    published by the Free Software Foundation, either version 2 of the
11
//    License, or (at your option) any later version.
12
//
13
//    emCORE is distributed in the hope that it will be useful,
14
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
//    See the GNU General Public License for more details.
17
//
18
//    You should have received a copy of the GNU General Public License along
19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
20
//
21
//
22
 
23
 
640 theseven 24
#include "emcoreapp.h"
25
#include "libui.h"
26
 
27
 
28
#define TILE_W 5
29
#define TILE_H 5
30
 
31
 
32
enum state
33
{
34
    STATE_FREE,
35
    STATE_SNAKE,
36
    STATE_FOOD,
37
    STATE_OUTOFBOUNDS,
38
    NUM_STATES
39
};
40
 
41
struct pos
42
{
43
    uint8_t x;
44
    uint8_t y;
45
};
46
 
47
 
48
uint32_t colors[NUM_STATES] =
49
{
50
    [STATE_FREE] = 0,
51
    [STATE_SNAKE] = 0xff000000,
52
    [STATE_FOOD] = 0xffff0000
53
};
54
 
55
 
56
struct libui_api* ui;
57
int dirx;
58
int diry;
59
int offsetx;
60
int offsety;
61
int tilesx;
62
int tilesy;
63
int tilecount;
64
void* framebuf;
65
int framebufx;
66
int framebufy;
67
int framebufsize;
68
uint8_t* field;
69
struct pos* snake;
70
int snakehead;
71
int snaketail;
72
int snakelength;
73
int xrandshift;
74
int yrandshift;
75
 
76
 
77
void buttonhandler(void* user, enum button_event eventtype, int which, int value)
78
{
79
    if (eventtype == BUTTON_PRESS)
80
        switch (which)
81
        {
82
        case 1:
83
            dirx = 1;
84
            diry = 0;
85
            break;
86
        case 2:
87
            dirx = -1;
88
            diry = 0;
89
            break;
90
        case 3:
91
            dirx = 0;
92
            diry = 1;
93
            break;
94
        case 4:
95
            dirx = 0;
96
            diry = -1;
97
            break;
98
        }
99
}
100
 
101
void setstate(int x, int y, enum state s)
102
{
103
    if (x < 0 || x >= tilesx || y < 0 || y >= tilesy) return;
104
    field[y * tilesx + x] = (uint8_t)s;
105
}
106
 
107
enum state getstate(int x, int y)
108
{
109
    if (x < 0 || x >= tilesx || y < 0 || y >= tilesy) return STATE_OUTOFBOUNDS;
110
    return (enum state)field[y * tilesx + x];
111
}
112
 
113
enum state extendsnake()
114
{
115
    int newx = snake[snakehead].x + dirx;
116
    int newy = snake[snakehead].y + diry;
117
    enum state s = getstate(newx, newy);
118
    if (s != STATE_FREE && s != STATE_FOOD) return s;
119
    snakehead++;
120
    setstate(newx, newy, STATE_SNAKE);
121
    if (snakehead >= tilecount) snakehead = 0;
122
    snake[snakehead].x = newx;
123
    snake[snakehead].y = newy;
124
    snakelength++;
125
    return s;
126
}
127
 
128
void shrinksnake()
129
{
130
    setstate(snake[snaketail].x, snake[snaketail].y, STATE_FREE);
131
    snaketail++;
132
    if (snaketail >= tilecount) snaketail = 0;
133
    snakelength--;
134
}
135
 
136
void placefood()
137
{
138
    int x;
139
    int y;
140
    enum state s = STATE_OUTOFBOUNDS;
141
    while (s != STATE_FREE)
142
    {
143
        x = rand() >> xrandshift;
144
        y = rand() >> yrandshift;
145
        s = getstate(x, y);
146
    }
147
    setstate(x, y, STATE_FOOD);
148
}
149
 
150
void draw()
151
{
152
    int x, y;
153
    memset(framebuf, 0xff, framebufsize);
154
    for (y = 0; y < tilesy; y++)
155
        for (x = 0; x < tilesx; x++)
156
        {
157
            uint32_t color = colors[getstate(x, y)];
158
            if (color) ui->fill(TILE_W, TILE_H, color, framebuf, x * TILE_W, y * TILE_H, framebufx);
159
        }
160
    displaylcd(offsetx, offsety, framebufx, framebufy, framebuf, 0, 0, framebufx);
161
}
162
 
163
 
835 theseven 164
static void main(int argc, const char** argv)
640 theseven 165
{
166
    int i;
167
 
651 theseven 168
    struct emcorelib_header* libui = get_library(LIBUI_IDENTIFIER, LIBUI_API_VERSION, LIBSOURCE_BOOTFLASH, "libui   ");
640 theseven 169
    if (!libui) panicf(PANIC_KILLTHREAD, "Could not load user interface library!");
170
    ui = (struct libui_api*)libui->api;
171
 
172
    int width = lcd_get_width();
173
    int height = lcd_get_height();
174
    tilesx = width / TILE_W;
175
    tilesy = height / TILE_H;
176
    tilecount = tilesx * tilesy;
177
    framebufx = tilesx * TILE_W;
178
    framebufy = tilesy * TILE_H;
179
    framebufsize = framebufx * framebufy * 3;
180
    offsetx = (width - framebufx) / 2;
181
    offsety = (height - framebufy) / 2;
182
    xrandshift = __emcore_syscall->__clzsi2(tilesx - 1) - 1;
183
    yrandshift = __emcore_syscall->__clzsi2(tilesy - 1) - 1;
184
    framebuf = malloc(framebufsize);
651 theseven 185
    field = malloc(tilecount * sizeof(typeof(*field)));
186
    snake = malloc(tilecount * sizeof(typeof(*snake)));
640 theseven 187
    if (!framebuf || !field || !snake) panicf(PANIC_KILLTHREAD, "Out of memory!");
188
    struct button_hook_entry* hook = button_register_handler(buttonhandler, NULL);
189
    if (!hook) panicf(PANIC_KILLTHREAD, "Could not register button hook!");
190
 
191
    memset(field, STATE_FREE, tilesx * tilesy);
192
    bool finished = false;
193
    dirx = 1;
194
    diry = 0;
195
    snakehead = 0;
196
    snaketail = 0;
197
    snakelength = 0;
198
    snake[0].x = 10;
199
    snake[0].y = 10;
200
    for (i = 0; i < 10; i++) placefood();
201
    long steptime = 500000;
202
    long lasttime = USEC_TIMER - steptime;
203
 
204
    while (!finished)
205
    {
206
        long time = USEC_TIMER;
207
        lasttime += steptime;
208
        if (time >= lasttime) lasttime = time;
209
        else sleep(lasttime - time);
210
        bool food = false;
211
        switch (extendsnake())
212
        {
213
        case STATE_SNAKE:
214
        case STATE_OUTOFBOUNDS:
215
            finished = true;
216
            break;
217
        case STATE_FOOD:
218
            food = true;
219
        }
220
        if (food) placefood();
221
        else if (snakelength > 5) shrinksnake();
222
        if (steptime > 50000) steptime -= 100;
223
        draw();
224
    }
225
 
226
    cprintf(1, "Score: %d\n", snakelength);
227
 
228
    button_unregister_handler(hook);
229
    free(snake);
230
    free(field);
231
    free(framebuf);
232
 
233
    release_library(libui);
234
    library_unload(libui);
235
}
236
 
237
 
238
EMCORE_APP_HEADER("Snake", main, 127)