diff --git a/2048.c b/2048.c new file mode 100644 index 0000000..52e4ab8 --- /dev/null +++ b/2048.c @@ -0,0 +1,212 @@ + +#include +#include +#include + +#include + + +#define CELLSIZE 128 +#define MAPSIZE 4 + + +typedef struct { + Group group; + int value; +} Cell; + + +Animation grid; +Animation numbers[11]; +Cell map[MAPSIZE][MAPSIZE]; +double speed = 8; + + +void setSprite(Cell *cell, double x, double y) { + if (cell->group) + groupDestroyEach(cell->group); + else + cell->group = createGroup(); + Sprite sprite = createSpriteEx(x, y, 1, 1); + spriteSetAnimation(sprite, numbers[cell->value]); + groupAdd(cell->group, sprite); +} + + +int add(int dr, int dc) { + int count = 0; + for(int r = 0; r < MAPSIZE; ++r) + for(int c = 0; c < MAPSIZE; ++c) + if (map[r][c].value < 0) + ++count; + if (count == 0) return 0; + + int i = randomNumber(0, count-1); + for(int r = 0; r < MAPSIZE; ++r) + for(int c = 0; c < MAPSIZE; ++c) + if (map[r][c].value < 0) + if (i-- == 0) { + map[r][c].value = 0; + int cc = dc > 0 ? -1 : (dc < 0 ? MAPSIZE : c); + int rr = dr > 0 ? -1 : (dr < 0 ? MAPSIZE : r); + setSprite(&map[r][c], cc + 0.5, rr + 0.5); + return 1; + } + + return 0; +} + + +void fallStep(int *moves, Cell **prev, int *skip, Cell *curr, Cell *empty) { + if (curr->value < 0) { + ++(*skip); + } else + if (*prev && (*prev)->value == curr->value && curr->value < 10) { + for(int i = 0; i < groupGetCount(curr->group); ++i) + groupAdd((*prev)->group, groupGet(curr->group, i)); + groupDestroy(curr->group); + curr->group = NULL; + curr->value = -1; + ++((*prev)->value); + ++(*skip); + ++(*moves); + *prev = NULL; + } else { + if (empty != curr) { + empty->group = curr->group; + empty->value = curr->value; + curr->group = NULL; + curr->value = -1; + ++(*moves); + } + *prev = empty; + } +} + + +void fall(int dr, int dc) { + Cell *prev; + int skip; + int moves = 0; + + if (dr == 0) { + for(int r = 0; r < MAPSIZE; ++r) { + prev = NULL; skip = 0; + if (dc < 0) + for(int c = 0; c < MAPSIZE; ++c) + fallStep(&moves, &prev, &skip, &map[r][c], &map[r][c-skip]); + else + if (dc > 0) + for(int c = MAPSIZE-1; c >= 0; --c) + fallStep(&moves, &prev, &skip, &map[r][c], &map[r][c+skip]); + } + } else + if (dc == 0) { + for(int c = 0; c < MAPSIZE; ++c) { + prev = NULL; skip = 0; + if (dr < 0) + for(int r = 0; r < MAPSIZE; ++r) + fallStep(&moves, &prev, &skip, &map[r][c], &map[r-skip][c]); + else + if (dr > 0) + for(int r = MAPSIZE-1; r >= 0; --r) + fallStep(&moves, &prev, &skip, &map[r][c], &map[r+skip][c]); + } + } + + if (moves > 0) add(dr, dc); +} + + +void init() { + for(int r = 0; r < MAPSIZE; ++r) { + for(int c = 0; c < MAPSIZE; ++c) { + map[r][c].group = NULL; + map[r][c].value = -1; + } + } + + grid = createAnimationEx("data/sprite/2048/frame.png", TRUE, TRUE, TRUE); + numbers[ 0] = createAnimation("data/sprite/2048/2.png"); + numbers[ 1] = createAnimation("data/sprite/2048/4.png"); + numbers[ 2] = createAnimation("data/sprite/2048/8.png"); + numbers[ 3] = createAnimation("data/sprite/2048/16.png"); + numbers[ 4] = createAnimation("data/sprite/2048/32.png"); + numbers[ 5] = createAnimation("data/sprite/2048/64.png"); + numbers[ 6] = createAnimation("data/sprite/2048/128.png"); + numbers[ 7] = createAnimation("data/sprite/2048/256.png"); + numbers[ 8] = createAnimation("data/sprite/2048/512.png"); + numbers[ 9] = createAnimation("data/sprite/2048/1024.png"); + numbers[10] = createAnimation("data/sprite/2048/2048.png"); + + add(0, 0); + add(0, 0); +} + + +void draw() { + saveState(); + zoom(CELLSIZE); + + saveState(); + noStroke(); + fillTexture(grid, 0, 0, 1, 1, FALSE); + rect(0, 0, MAPSIZE, MAPSIZE); + restoreState(); + + if (keyWentDown("left")) fall(0, -1); + if (keyWentDown("right")) fall(0, 1); + if (keyWentDown("up")) fall(-1, 0); + if (keyWentDown("down")) fall( 1, 0); + + double dp = speed * worldGetFrameTime(); + int score = 0; + for(int r = 0; r < MAPSIZE; ++r) { + for(int c = 0; c < MAPSIZE; ++c) { + Cell *cell = &map[r][c]; + if (cell->group) { + score += (1 << (cell->value + 1)); + int count = groupGetCount(cell->group); + int ready = count > 1; + double prevX = 0, prevY = 0; + + double cx = c + 0.5; + double cy = r + 0.5; + for(int i = 0; i < count; ++i) { + Sprite sprite = groupGet(cell->group, i); + double x = spriteGetX(sprite); + double y = spriteGetY(sprite); + x = fabs(x - cx) <= dp ? cx : (x < cx ? x + dp : x - dp); + y = fabs(y - cy) <= dp ? cy : (y < cy ? y + dp : y - dp); + spriteSetXY(sprite, x, y); + + if (i > 0 && (fabs(prevX - x) > 0.01 || fabs(prevY - y) > 0.01)) + ready = 0; + prevX = x; + prevY = y; + } + + if (ready) + setSprite(cell, prevX, prevY); + } + } + } + + char buf[20]; + sprintf(buf, "%d", score); + worldSetTitle(buf); + + drawSprites(); + restoreState(); +} + + +int main() { + worldSetInit(&init); + worldSetDraw(&draw); + worldSetSize(MAPSIZE*CELLSIZE, MAPSIZE*CELLSIZE); + worldSetVariableFrameRate(); + worldRun(); + return 0; +} + diff --git a/data-src/sprite/2048.xcf b/data-src/sprite/2048.xcf new file mode 100644 index 0000000..a399e09 Binary files /dev/null and b/data-src/sprite/2048.xcf differ diff --git a/data/sprite/2048/1024.png b/data/sprite/2048/1024.png new file mode 100644 index 0000000..79c81ae Binary files /dev/null and b/data/sprite/2048/1024.png differ diff --git a/data/sprite/2048/128.png b/data/sprite/2048/128.png new file mode 100644 index 0000000..a9fae65 Binary files /dev/null and b/data/sprite/2048/128.png differ diff --git a/data/sprite/2048/16.png b/data/sprite/2048/16.png new file mode 100644 index 0000000..6d4e6e6 Binary files /dev/null and b/data/sprite/2048/16.png differ diff --git a/data/sprite/2048/2.png b/data/sprite/2048/2.png new file mode 100644 index 0000000..1b5f05b Binary files /dev/null and b/data/sprite/2048/2.png differ diff --git a/data/sprite/2048/2048.png b/data/sprite/2048/2048.png new file mode 100644 index 0000000..8ffeee5 Binary files /dev/null and b/data/sprite/2048/2048.png differ diff --git a/data/sprite/2048/256.png b/data/sprite/2048/256.png new file mode 100644 index 0000000..42b4936 Binary files /dev/null and b/data/sprite/2048/256.png differ diff --git a/data/sprite/2048/32.png b/data/sprite/2048/32.png new file mode 100644 index 0000000..5c48c9e Binary files /dev/null and b/data/sprite/2048/32.png differ diff --git a/data/sprite/2048/4.png b/data/sprite/2048/4.png new file mode 100644 index 0000000..e4114a9 Binary files /dev/null and b/data/sprite/2048/4.png differ diff --git a/data/sprite/2048/512.png b/data/sprite/2048/512.png new file mode 100644 index 0000000..b4573cb Binary files /dev/null and b/data/sprite/2048/512.png differ diff --git a/data/sprite/2048/64.png b/data/sprite/2048/64.png new file mode 100644 index 0000000..71f7fcc Binary files /dev/null and b/data/sprite/2048/64.png differ diff --git a/data/sprite/2048/8.png b/data/sprite/2048/8.png new file mode 100644 index 0000000..4f87298 Binary files /dev/null and b/data/sprite/2048/8.png differ diff --git a/data/sprite/2048/frame.png b/data/sprite/2048/frame.png new file mode 100644 index 0000000..e29ce4e Binary files /dev/null and b/data/sprite/2048/frame.png differ diff --git a/fractal.c b/fractal.c index 3cbaca5..be3a8b1 100644 --- a/fractal.c +++ b/fractal.c @@ -84,4 +84,5 @@ int main() { worldSetDraw(&draw); worldSetFrameRateEx(1, 100); worldRun(); + return 0; }