diff --git a/programs/games/2048/Makefile b/programs/games/2048/Makefile index b302884d34..1b5cef06c1 100755 --- a/programs/games/2048/Makefile +++ b/programs/games/2048/Makefile @@ -1,3 +1,3 @@ OUTFILE = 2048 -OBJS = main.o game.o board.o cell.o rect.o defines.o +OBJS = main.o game.o board.o paint.o cell.o rect.o defines.o include $(MENUETDEV)/makefiles/Makefile_for_program diff --git a/programs/games/2048/Tupfile.lua b/programs/games/2048/Tupfile.lua index 6db8d05782..77a92085f2 100644 --- a/programs/games/2048/Tupfile.lua +++ b/programs/games/2048/Tupfile.lua @@ -1,6 +1,6 @@ if tup.getconfig('NO_GCC') ~= "" then return end -HELPERDIR = (tup.getconfig("HELPERDIR") == "") and "../../.." or tup.getconfig("HELPERDIR") +HELPERDIR = (tup.getconfig("HELPERDIR") == "") and "../.." or tup.getconfig("HELPERDIR") tup.include(HELPERDIR .. "/use_gcc.lua") tup.include(HELPERDIR .. "/use_menuetlibc.lua") -compile_gcc{"main.c" "defines.c" "rect.c" "cell.c" "board.c" "game.c"} +compile_gcc{"main.c", "defines.c", "rect.c", "paint.c", "cell.c", "board.c", "game.c"} link_gcc("2048") diff --git a/programs/games/2048/board.c b/programs/games/2048/board.c index 34391354e8..e931edfb02 100644 --- a/programs/games/2048/board.c +++ b/programs/games/2048/board.c @@ -3,7 +3,6 @@ rect base_cell = {0}; tile null_tile = {0}; - struct { rect draw; // background rect rect cell_map[BOARD_MAP_SIZE]; // background cells array @@ -60,18 +59,21 @@ void board_init(rect* r) // seed for random number generator srand(__menuet__getsystemclock()); - board.score = 0; - board.draw = *r; - __u16 cell_size = (r->width - BOARD_SPACING * (BOARD_COUNT + 1)) / BOARD_COUNT; base_cell.width = cell_size; base_cell.height = cell_size; null_tile.value = 0; null_tile.animate = false; - null_tile.ani_step = ANIM_STEP; + null_tile.ani_step = ANI_APPEAR_STEP; null_tile.merged = false; + board.score = 0; + board.draw = *r; + + canvas_init(r); + canvas_fill(BOARD_BG_COLOR); + __u16 i = 0; for (i = 0; i < BOARD_MAP_SIZE; i++) { @@ -88,6 +90,11 @@ void board_init(rect* r) board_redraw(); } +void board_delete() +{ + canvas_delete(); +} + void board_redraw() { __u16 i = 0; @@ -95,12 +102,11 @@ void board_redraw() __u8 last_animate = false; do { - vsync(); - rect_draw(&board.draw,BOARD_BG_COLOR); + canvas_fill(BOARD_BG_COLOR); for (i = 0; i < BOARD_MAP_SIZE; i++) { - rect_draw(&board.cell_map[i],CELL_COLOR); + canvas_draw_rect(&board.cell_map[i],CELL_COLOR); } animate = false; @@ -115,9 +121,11 @@ void board_redraw() } } + canvas_paint(); + if (animate) { - __menuet__delay100(ANIM_DELAY); + __menuet__delay100(ANI_DELAY); } } while (animate); @@ -333,7 +341,7 @@ __u8 board_add_random_tile() av_tile->value = (random_u32(10) < 9) ? 2 : 4; av_tile->animate = true; - av_tile->ani_step = 5; + av_tile->ani_step = ANI_APPEAR_STEP; av_tile->transition = position2cell(board_position(rnd_av)); av_tile->cell.x = av_tile->transition.x + base_cell.width / 2; av_tile->cell.y = av_tile->transition.y + base_cell.height / 2; @@ -460,6 +468,7 @@ void tempboard_move_tile(tile* temp[], __u16 from, __u16 to) { temp[to] = temp[from]; temp[to]->animate = true; + temp[to]->ani_step = ANI_MOVE_STEP; temp[from] = 0; } diff --git a/programs/games/2048/board.h b/programs/games/2048/board.h index a6e89f8fe7..24f23b9258 100644 --- a/programs/games/2048/board.h +++ b/programs/games/2048/board.h @@ -7,6 +7,9 @@ // Draw a new board void board_init(rect* r); +// Free board resources +void board_delete(); + // Redraw board and all content (animation will started if needed) void board_redraw(); diff --git a/programs/games/2048/cell.c b/programs/games/2048/cell.c index 4b5f3ee88c..fbc47bb278 100644 --- a/programs/games/2048/cell.c +++ b/programs/games/2048/cell.c @@ -29,8 +29,8 @@ __u8 tile_draw(tile* t) if (rect_transform(begin,end,t->ani_step)) t->animate = false; - rect_draw(begin,bg_color); - rect_draw_value(begin,t->value,txt_color); + canvas_draw_rect(begin,bg_color); + canvas_draw_value(begin,t->value,txt_color); if (t->merged) { @@ -42,8 +42,8 @@ __u8 tile_draw(tile* t) t->value *= 2; } - rect_draw(&t->merged_rect,bg_color); - rect_draw_value(&t->merged_rect,t->value,txt_color); + canvas_draw_rect(&t->merged_rect,bg_color); + canvas_draw_value(&t->merged_rect,t->value,txt_color); } } diff --git a/programs/games/2048/cell.h b/programs/games/2048/cell.h index a543229a78..3e6c8939c2 100644 --- a/programs/games/2048/cell.h +++ b/programs/games/2048/cell.h @@ -2,7 +2,7 @@ #define CELL_H #include "defines.h" -#include "rect.h" +#include "paint.h" typedef struct { rect cell; // current rect diff --git a/programs/games/2048/defines.c b/programs/games/2048/defines.c index 0def9a32af..ac8baf742b 100644 --- a/programs/games/2048/defines.c +++ b/programs/games/2048/defines.c @@ -1,15 +1,18 @@ #include "defines.h" +// Enable scancodes for event loop inline void enable_scancode() { __asm__ __volatile__("int $0x40"::"a"(66),"b"(1),"c"(1)); } +// Clear key buffer inline void clear_key_buffer() { int i = 0; for (i = 0; i < 120; i++) __menuet__getkey(); } +// Wait for screen draw (vertical sync) inline void vsync() { __asm__ __volatile__("int $0x40"::"a"(18),"b"(14)); } diff --git a/programs/games/2048/defines.h b/programs/games/2048/defines.h index af0e66e680..c6cf661d8b 100644 --- a/programs/games/2048/defines.h +++ b/programs/games/2048/defines.h @@ -16,8 +16,9 @@ inline void vsync(); #define FONT_WIDTH (5) #define FONT_HEIGHT (9) -#define ANIM_DELAY (5) // time between animation redraw -#define ANIM_STEP (25) // default step for animation +#define ANI_DELAY (2) // time between animation redraw +#define ANI_APPEAR_STEP (15) // default step for appear animation +#define ANI_MOVE_STEP (25) // default step for move animation #define START_COUNT (2) // tiles count for new game diff --git a/programs/games/2048/game.c b/programs/games/2048/game.c index c50e2f783b..700b3a0901 100644 --- a/programs/games/2048/game.c +++ b/programs/games/2048/game.c @@ -79,6 +79,11 @@ void game_init() __menuet__window_redraw(2); } +void game_exit() +{ + board_delete(); +} + void game_redraw() { __menuet__get_process_table(&proc_info,PID_WHOAMI); @@ -86,7 +91,6 @@ void game_redraw() // start redraw __menuet__window_redraw(1); - vsync(); __menuet__define_window(0, // __u16 x1 : ignored 0, // __u16 y1 : ignored 0, // __u16 xsize : ignored diff --git a/programs/games/2048/game.h b/programs/games/2048/game.h index 31a82d4b58..eb60954e79 100644 --- a/programs/games/2048/game.h +++ b/programs/games/2048/game.h @@ -12,6 +12,9 @@ static struct process_table_entry proc_info = {0}; // Start a new game void game_init(); +// Exit game +void game_exit(); + // Redraw game content void game_redraw(); diff --git a/programs/games/2048/main.c b/programs/games/2048/main.c index 3cbda4461d..edf42df46e 100644 --- a/programs/games/2048/main.c +++ b/programs/games/2048/main.c @@ -47,6 +47,7 @@ void main() game_init(); break; default : // close + game_exit(); return; } } diff --git a/programs/games/2048/paint.c b/programs/games/2048/paint.c new file mode 100644 index 0000000000..e27ebdb7ea --- /dev/null +++ b/programs/games/2048/paint.c @@ -0,0 +1,133 @@ +#include "paint.h" + +typedef struct { + char b; + char g; + char r; +} rgb; + +struct { + rect area; + rgb* image; +} canvas = {0}; + +__u32 canvas_index(__u16 row, __u16 column) { + return column + row * canvas.area.width; +} + +point canvas_position(__u32 index) { + point p = { + .x = index % canvas.area.width, + .y = index / canvas.area.width + }; + return p; +} + +void canvas_init(rect *r) +{ + canvas.area = *r; + + canvas_delete(); + canvas.image = malloc(r->width * r->height * sizeof(rgb)); +} + +void canvas_delete() +{ + if (canvas.image) + free(canvas.image); +} + +void canvas_fill(__u32 color) +{ + if (canvas.image) + { + __u32 i = 0; + __u32 len = canvas.area.width * canvas.area.height; + for (i = 0; i < len; i++) + { + canvas.image[i] = *((rgb*)(&color)); + } + } +} + +void canvas_draw_rect(rect *r, __u32 color) +{ + if (canvas.image) + { + __u32 row = 0; + __u32 column = 0; + rgb* c = (rgb*)(&color); + + for (row = 0; row < r->height; row++) + { + for (column = 0; column < (r->width); column++) + { + canvas.image[canvas_index(row + r->y - canvas.area.y, + column + r->x - canvas.area.x)] = *c; + } + } + } +} + +void canvas_draw_text(rect* r, char* txt, __u32 len, __u32 color) +{ + __u16 x = r->x + (r->width - len * FONT_WIDTH - len) / 2 - canvas.area.x; + __u16 y = r->y + (r->height - FONT_HEIGHT) / 2 - canvas.area.y; + + __u32 w; + __u32 h; + char* mem; + + h = FONT_HEIGHT; + w = len * FONT_WIDTH + len; + mem = malloc(sizeof(__u32) * 2 + h * w * sizeof(__u32)); + + memset(mem,0,sizeof(__u32) * 2 + h * w * sizeof(__u32)); + ((__u32*)mem)[0] = w; + ((__u32*)mem)[1] = h; + + __asm__ __volatile__("int $0x40":: + "a"(4), + "b"(0), + "c"(color | (8 << 24)), + "d"((__u32)txt), + "S"(len), + "D"((__u32)(mem))); + + int row = 0; + int column = 0; + __u32* __mem = (__u32*)(mem + 8); + for (row = 0; row < h; row++) + { + for (column = 0; column < w; column++) + { + __u32 c = __mem[column + row * w]; + if (c & 0xFF000000) + { + canvas.image[canvas_index(row + y,column + x)] = *((rgb*)&c); + } + } + } + + memset(mem,0,sizeof(__u32) * 2 + h * w * sizeof(__u32)); + free(mem); +} + +void canvas_draw_value(rect* r, __u32 v, __u32 color) +{ + char buffer[16] = {0}; + __u32 length = strlen(itoa(v,buffer,10)); + canvas_draw_text(r,buffer,length,color); +} + +void canvas_paint() +{ + if (canvas.image) + { + __menuet__putimage(canvas.area.x, + canvas.area.y, + canvas.area.width, + canvas.area.height, + (char*)canvas.image); + } +} diff --git a/programs/games/2048/paint.h b/programs/games/2048/paint.h new file mode 100644 index 0000000000..7c77ac0a80 --- /dev/null +++ b/programs/games/2048/paint.h @@ -0,0 +1,17 @@ +#ifndef PAINT_H +#define PAINT_H + +#include "defines.h" +#include "rect.h" + +void canvas_init(rect* r); +void canvas_delete(); +void canvas_fill(__u32 color); + +void canvas_draw_rect(rect* r, __u32 color); +void canvas_draw_text(rect* r, char* txt, __u32 len, __u32 color); +void canvas_draw_value(rect *r, __u32 v, __u32 color); + +void canvas_paint(); + +#endif // PAINT_H diff --git a/programs/games/2048/rect.c b/programs/games/2048/rect.c index 122dff5615..dedde6bded 100644 --- a/programs/games/2048/rect.c +++ b/programs/games/2048/rect.c @@ -9,45 +9,45 @@ __u8 rect_transform(rect* from, rect* to, __u16 step) { if (from->width < to->width) { - from->width += (ANIM_STEP << 1); + from->width += (step << 1); if (from->width > to->width) from->width = to->width; } else if (from->width > to->width) { - from->width -= (ANIM_STEP << 1); + from->width -= (step << 1); if (from->width < to->width) from->width = to->width; } if (from->height < to->height) { - from->height += (ANIM_STEP << 1); + from->height += (step << 1); if (from->height > to->height) from->height = to->height; } else if (from->height > to->height) { - from->height -= (ANIM_STEP << 1); + from->height -= (step << 1); if (from->height < to->height) from->height = to->height; } if (from->x < to->x) { - from->x += ANIM_STEP; + from->x += step; if (from->x > to->x) from->x = to->x; } else if (from->x > to->x) { - from->x -= ANIM_STEP; + from->x -= step; if (from->x < to->x) from->x = to->x; } if (from->y < to->y) { - from->y += ANIM_STEP; + from->y += step; if (from->y > to->y) from->y = to->y; } else if (from->y > to->y) { - from->y -= ANIM_STEP; + from->y -= step; if (from->y < to->y) from->y = to->y; } @@ -90,7 +90,7 @@ void rect_draw_text(rect *r, char *txt, __u32 len, __u32 color) 0,txt,len); } -void rect_draw_value(rect *r, __u32 v, __u32 color) +void rect_draw_value(rect* r, __u32 v, __u32 color) { char buffer[16] = {0}; __u32 length = strlen(itoa(v,buffer,10));