Subversion Repositories freemyipod

Rev

Rev 640 | Rev 652 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
640 theseven 1
#include "emcoreapp.h"
2
#include "libui.h"
3
 
4
 
5
#define TILE_W 5
6
#define TILE_H 5
7
 
8
 
9
enum state
10
{
11
    STATE_FREE,
12
    STATE_SNAKE,
13
    STATE_FOOD,
14
    STATE_OUTOFBOUNDS,
15
    NUM_STATES
16
};
17
 
18
struct pos
19
{
20
    uint8_t x;
21
    uint8_t y;
22
};
23
 
24
 
25
uint32_t colors[NUM_STATES] =
26
{
27
    [STATE_FREE] = 0,
28
    [STATE_SNAKE] = 0xff000000,
29
    [STATE_FOOD] = 0xffff0000
30
};
31
 
32
 
33
struct libui_api* ui;
34
int dirx;
35
int diry;
36
int offsetx;
37
int offsety;
38
int tilesx;
39
int tilesy;
40
int tilecount;
41
void* framebuf;
42
int framebufx;
43
int framebufy;
44
int framebufsize;
45
uint8_t* field;
46
struct pos* snake;
47
int snakehead;
48
int snaketail;
49
int snakelength;
50
int xrandshift;
51
int yrandshift;
52
 
53
 
54
void buttonhandler(void* user, enum button_event eventtype, int which, int value)
55
{
56
    if (eventtype == BUTTON_PRESS)
57
        switch (which)
58
        {
59
        case 1:
60
            dirx = 1;
61
            diry = 0;
62
            break;
63
        case 2:
64
            dirx = -1;
65
            diry = 0;
66
            break;
67
        case 3:
68
            dirx = 0;
69
            diry = 1;
70
            break;
71
        case 4:
72
            dirx = 0;
73
            diry = -1;
74
            break;
75
        }
76
}
77
 
78
void setstate(int x, int y, enum state s)
79
{
80
    if (x < 0 || x >= tilesx || y < 0 || y >= tilesy) return;
81
    field[y * tilesx + x] = (uint8_t)s;
82
}
83
 
84
enum state getstate(int x, int y)
85
{
86
    if (x < 0 || x >= tilesx || y < 0 || y >= tilesy) return STATE_OUTOFBOUNDS;
87
    return (enum state)field[y * tilesx + x];
88
}
89
 
90
enum state extendsnake()
91
{
92
    int newx = snake[snakehead].x + dirx;
93
    int newy = snake[snakehead].y + diry;
94
    enum state s = getstate(newx, newy);
95
    if (s != STATE_FREE && s != STATE_FOOD) return s;
96
    snakehead++;
97
    setstate(newx, newy, STATE_SNAKE);
98
    if (snakehead >= tilecount) snakehead = 0;
99
    snake[snakehead].x = newx;
100
    snake[snakehead].y = newy;
101
    snakelength++;
102
    return s;
103
}
104
 
105
void shrinksnake()
106
{
107
    setstate(snake[snaketail].x, snake[snaketail].y, STATE_FREE);
108
    snaketail++;
109
    if (snaketail >= tilecount) snaketail = 0;
110
    snakelength--;
111
}
112
 
113
void placefood()
114
{
115
    int x;
116
    int y;
117
    enum state s = STATE_OUTOFBOUNDS;
118
    while (s != STATE_FREE)
119
    {
120
        x = rand() >> xrandshift;
121
        y = rand() >> yrandshift;
122
        s = getstate(x, y);
123
    }
124
    setstate(x, y, STATE_FOOD);
125
}
126
 
127
void draw()
128
{
129
    int x, y;
130
    memset(framebuf, 0xff, framebufsize);
131
    for (y = 0; y < tilesy; y++)
132
        for (x = 0; x < tilesx; x++)
133
        {
134
            uint32_t color = colors[getstate(x, y)];
135
            if (color) ui->fill(TILE_W, TILE_H, color, framebuf, x * TILE_W, y * TILE_H, framebufx);
136
        }
137
    displaylcd(offsetx, offsety, framebufx, framebufy, framebuf, 0, 0, framebufx);
138
}
139
 
140
 
141
static void main()
142
{
143
    int i;
144
 
651 theseven 145
    struct emcorelib_header* libui = get_library(LIBUI_IDENTIFIER, LIBUI_API_VERSION, LIBSOURCE_BOOTFLASH, "libui   ");
640 theseven 146
    if (!libui) panicf(PANIC_KILLTHREAD, "Could not load user interface library!");
147
    ui = (struct libui_api*)libui->api;
148
 
149
    int width = lcd_get_width();
150
    int height = lcd_get_height();
151
    tilesx = width / TILE_W;
152
    tilesy = height / TILE_H;
153
    tilecount = tilesx * tilesy;
154
    framebufx = tilesx * TILE_W;
155
    framebufy = tilesy * TILE_H;
156
    framebufsize = framebufx * framebufy * 3;
157
    offsetx = (width - framebufx) / 2;
158
    offsety = (height - framebufy) / 2;
159
    xrandshift = __emcore_syscall->__clzsi2(tilesx - 1) - 1;
160
    yrandshift = __emcore_syscall->__clzsi2(tilesy - 1) - 1;
161
    framebuf = malloc(framebufsize);
651 theseven 162
    field = malloc(tilecount * sizeof(typeof(*field)));
163
    snake = malloc(tilecount * sizeof(typeof(*snake)));
640 theseven 164
    if (!framebuf || !field || !snake) panicf(PANIC_KILLTHREAD, "Out of memory!");
165
    struct button_hook_entry* hook = button_register_handler(buttonhandler, NULL);
166
    if (!hook) panicf(PANIC_KILLTHREAD, "Could not register button hook!");
167
 
168
    memset(field, STATE_FREE, tilesx * tilesy);
169
    bool finished = false;
170
    dirx = 1;
171
    diry = 0;
172
    snakehead = 0;
173
    snaketail = 0;
174
    snakelength = 0;
175
    snake[0].x = 10;
176
    snake[0].y = 10;
177
    for (i = 0; i < 10; i++) placefood();
178
    long steptime = 500000;
179
    long lasttime = USEC_TIMER - steptime;
180
 
181
    while (!finished)
182
    {
183
        long time = USEC_TIMER;
184
        lasttime += steptime;
185
        if (time >= lasttime) lasttime = time;
186
        else sleep(lasttime - time);
187
        bool food = false;
188
        switch (extendsnake())
189
        {
190
        case STATE_SNAKE:
191
        case STATE_OUTOFBOUNDS:
192
            finished = true;
193
            break;
194
        case STATE_FOOD:
195
            food = true;
196
        }
197
        if (food) placefood();
198
        else if (snakelength > 5) shrinksnake();
199
        if (steptime > 50000) steptime -= 100;
200
        draw();
201
    }
202
 
203
    cprintf(1, "Score: %d\n", snakelength);
204
 
205
    button_unregister_handler(hook);
206
    free(snake);
207
    free(field);
208
    free(framebuf);
209
 
210
    release_library(libui);
211
    library_unload(libui);
212
}
213
 
214
 
215
EMCORE_APP_HEADER("Snake", main, 127)