From 9f16c89604d9c25b6f538e2bc626716ac50d63fa Mon Sep 17 00:00:00 2001 From: raandoom Date: Thu, 11 Dec 2014 20:14:23 +0000 Subject: [PATCH] 2048: source files added git-svn-id: svn://kolibrios.org@5229 a494cfbc-eb01-0410-851d-a64ba20cac60 --- programs/games/2048/Makefile | 3 + programs/games/2048/Tupfile.lua | 6 + programs/games/2048/board.c | 476 ++++++++++++++++++++++++++++++++ programs/games/2048/board.h | 40 +++ programs/games/2048/cell.c | 58 ++++ programs/games/2048/cell.h | 23 ++ programs/games/2048/defines.c | 15 + programs/games/2048/defines.h | 39 +++ programs/games/2048/game.c | 155 +++++++++++ programs/games/2048/game.h | 30 ++ programs/games/2048/main.c | 54 ++++ programs/games/2048/rect.c | 98 +++++++ programs/games/2048/rect.h | 32 +++ 13 files changed, 1029 insertions(+) create mode 100755 programs/games/2048/Makefile create mode 100644 programs/games/2048/Tupfile.lua create mode 100644 programs/games/2048/board.c create mode 100644 programs/games/2048/board.h create mode 100644 programs/games/2048/cell.c create mode 100644 programs/games/2048/cell.h create mode 100644 programs/games/2048/defines.c create mode 100644 programs/games/2048/defines.h create mode 100644 programs/games/2048/game.c create mode 100644 programs/games/2048/game.h create mode 100644 programs/games/2048/main.c create mode 100644 programs/games/2048/rect.c create mode 100644 programs/games/2048/rect.h diff --git a/programs/games/2048/Makefile b/programs/games/2048/Makefile new file mode 100755 index 0000000000..b302884d34 --- /dev/null +++ b/programs/games/2048/Makefile @@ -0,0 +1,3 @@ +OUTFILE = 2048 +OBJS = main.o game.o board.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 new file mode 100644 index 0000000000..6db8d05782 --- /dev/null +++ b/programs/games/2048/Tupfile.lua @@ -0,0 +1,6 @@ +if tup.getconfig('NO_GCC') ~= "" then return end +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"} +link_gcc("2048") diff --git a/programs/games/2048/board.c b/programs/games/2048/board.c new file mode 100644 index 0000000000..34391354e8 --- /dev/null +++ b/programs/games/2048/board.c @@ -0,0 +1,476 @@ +#include "board.h" + +rect base_cell = {0}; +tile null_tile = {0}; + + +struct { + rect draw; // background rect + rect cell_map[BOARD_MAP_SIZE]; // background cells array + tile tile_map[BOARD_MAP_SIZE]; // tiles array + __u16 empty_index[BOARD_MAP_SIZE];// empty cells indexes + __u16 empty_count; // empty cells count + __u32 score; +} board = {0}; + +// Get tile index for row and column +__u16 board_index(__u16 row, __u16 column) { + return column + row * BOARD_COUNT; +} + +// Get tile position (as point with eow and column) for index +point board_position(__u16 index) { + point p = { + .x = index % BOARD_COUNT, + .y = index / BOARD_COUNT + }; + return p; +} + +// Calculate cell rect for row and column +rect position2cell(point p) { + rect c = {0}; + c.width = base_cell.width; + c.height = base_cell.height; + c.x = board.draw.x + BOARD_SPACING + p.x * (c.width + BOARD_SPACING); + c.y = board.draw.y + BOARD_SPACING + p.y * (c.height + BOARD_SPACING); + return c; +} + +// Update information about empty cells +void board_update_empty_info(); + +// Represent tile array as pointers array +void board_to_tempboard(tile* temp[]); + +// Fill tile array with tiles from pointers array +void board_from_tempboard(tile* temp[], __u8 forward); + +// Move tile inside a pointer array +void tempboard_move_tile(tile* temp[], __u16 from, __u16 to); + +// Merge tiles inside a pointer array +void tempboard_merge_tile(tile* temp[], __u16 from, __u16 to); + +// Random number generator +__u32 random_u32(__u32 max); + +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.merged = false; + + __u16 i = 0; + for (i = 0; i < BOARD_MAP_SIZE; i++) + { + board.cell_map[i] = position2cell(board_position(i)); + board.tile_map[i] = null_tile; + } + + i = 0; + for (i = 0; i < START_COUNT; i++) + { + board_add_random_tile(); + } + + board_redraw(); +} + +void board_redraw() +{ + __u16 i = 0; + __u8 animate = false; + __u8 last_animate = false; + do + { + vsync(); + rect_draw(&board.draw,BOARD_BG_COLOR); + + for (i = 0; i < BOARD_MAP_SIZE; i++) + { + rect_draw(&board.cell_map[i],CELL_COLOR); + } + + animate = false; + last_animate = false; + for (i = 0; i < BOARD_MAP_SIZE; i++) + { + tile* t = &board.tile_map[i]; + last_animate = tile_draw(t); + if (last_animate) + { + animate = last_animate; + } + } + + if (animate) + { + __menuet__delay100(ANIM_DELAY); + } + } + while (animate); +} + +__u8 board_up() +{ + __u8 moved = false; + + __u16 row = 0; + __u16 column = 0; + __u16 ind = 0; + __u16 preind = 0; + tile* indtile = 0; + tile* pretile = 0; + + tile* temp_board[BOARD_MAP_SIZE] = {0}; + board_to_tempboard(temp_board); + + for (column = 0; column < BOARD_COUNT; column++) + { + for (row = 0; row < BOARD_COUNT; row++) + { + if (row > 0) + { + ind = board_index(row,column); + indtile = temp_board[ind]; + if (indtile) + { + preind = board_index(row - 1,column); + pretile = temp_board[preind]; + if (!pretile) + { + moved = true; + tempboard_move_tile(temp_board,ind,preind); + row = 0; + } + else if (tile_mergeable(indtile,pretile)) + { + moved = true; + board.score += indtile->value * 2; + tempboard_merge_tile(temp_board,ind,preind); + row = 0; + } + } + } + } + } + + board_from_tempboard(temp_board,true); + + return moved; +} + +__u8 board_down() +{ + __u8 moved = false; + + __u16 row = 0; + __u16 column = 0; + __u16 ind = 0; + __u16 preind = 0; + tile* indtile = 0; + tile* pretile = 0; + + tile* temp_board[BOARD_MAP_SIZE] = {0}; + board_to_tempboard(temp_board); + + for (column = 0; column < BOARD_COUNT; column++) + { + row = BOARD_COUNT; + while (row--) + { + if ((BOARD_COUNT - row) > 1) + { + ind = board_index(row,column); + indtile = temp_board[ind]; + if (indtile) + { + preind = board_index(row + 1,column); + pretile = temp_board[preind]; + if (!pretile) + { + moved = true; + tempboard_move_tile(temp_board,ind,preind); + row = BOARD_COUNT; + } + else if (tile_mergeable(indtile,pretile)) + { + moved = true; + board.score += indtile->value * 2; + tempboard_merge_tile(temp_board,ind,preind); + row = BOARD_COUNT; + } + } + } + } + } + + board_from_tempboard(temp_board,false); + + return moved; +} + +__u8 board_left() +{ + __u8 moved = false; + + __u16 row = 0; + __u16 column = 0; + __u16 ind = 0; + __u16 preind = 0; + tile* indtile = 0; + tile* pretile = 0; + + tile* temp_board[BOARD_MAP_SIZE] = {0}; + board_to_tempboard(temp_board); + + for (row = 0; row < BOARD_COUNT; row++) + { + for (column = 0; column < BOARD_COUNT; column++) + { + if (column > 0) + { + ind = board_index(row,column); + indtile = temp_board[ind]; + if (indtile) + { + preind = board_index(row,column - 1); + pretile = temp_board[preind]; + if (!pretile) + { + moved = true; + tempboard_move_tile(temp_board,ind,preind); + column = 0; + } + else if (tile_mergeable(indtile,pretile)) + { + moved = true; + board.score += indtile->value * 2; + tempboard_merge_tile(temp_board,ind,preind); + column = 0; + } + } + } + } + } + + board_from_tempboard(temp_board,true); + + return moved; +} + +__u8 board_right() +{ + __u8 moved = false; + + __u16 row = 0; + __u16 column = 0; + __u16 ind = 0; + __u16 preind = 0; + tile* indtile = 0; + tile* pretile = 0; + + tile* temp_board[BOARD_MAP_SIZE] = {0}; + board_to_tempboard(temp_board); + + for (row = 0; row < BOARD_COUNT; row++) + { + column = BOARD_COUNT; + while (column--) + { + if ((BOARD_COUNT - column) > 1) + { + ind = board_index(row,column); + indtile = temp_board[ind]; + if (indtile) + { + preind = board_index(row,column + 1); + pretile = temp_board[preind]; + if (!pretile) + { + moved = true; + tempboard_move_tile(temp_board,ind,preind); + column = BOARD_COUNT; + } + else if (tile_mergeable(indtile,pretile)) + { + moved = true; + board.score += indtile->value * 2; + tempboard_merge_tile(temp_board,ind,preind); + column = BOARD_COUNT; + } + } + } + } + } + + board_from_tempboard(temp_board,false); + + return moved; +} + +__u8 board_add_random_tile() +{ + board_update_empty_info(); + if (board.empty_count) + { + __u16 rnd_av = random_u32(board.empty_count); + rnd_av = board.empty_index[rnd_av]; + + tile* av_tile = &board.tile_map[rnd_av]; + av_tile->value = (random_u32(10) < 9) ? 2 : 4; + + av_tile->animate = true; + av_tile->ani_step = 5; + 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; + av_tile->cell.width = 0; + av_tile->cell.height = 0; + } + return board.empty_count; +} + +__u8 board_has_moves() +{ + __u16 ind = 0; + __u16 next = 0; + __u16 step = 0; + __u16 pos = 0; + for (step = 0; step < BOARD_COUNT; step++) + { + for (pos = 0; pos < BOARD_COUNT; pos++) + { + // check horizontal + ind = board_index(step,pos); + next = board_index(step,pos + 1); + + if (!board.tile_map[ind].value || + (((pos + 1) < BOARD_COUNT) && + (!board.tile_map[next].value || + (board.tile_map[ind].value == board.tile_map[next].value) + ) + ) + ) + return true; + + // check vertical + ind = board_index(pos,step); + next = board_index(pos + 1,step); + + if (!board.tile_map[ind].value || + (((pos + 1) < BOARD_COUNT) && + (!board.tile_map[next].value || + (board.tile_map[ind].value == board.tile_map[next].value) + ) + ) + ) + return true; + } + } + return false; +} + +__u32 board_score() +{ + return board.score; +} + +void board_update_empty_info() +{ + board.empty_count = 0; + + __u16 i = 0; + for (i = 0; i < BOARD_MAP_SIZE; i++) + { + if (!board.tile_map[i].value) + { + board.empty_index[board.empty_count] = i; + board.empty_count++; + } + } +} + +void board_to_tempboard(tile* temp[]) +{ + __u16 ind = 0; + for (ind = 0; ind < BOARD_MAP_SIZE; ind++) + { + tile* bt = &board.tile_map[ind]; + if (bt->value) + { + temp[ind] = bt; + } + } +} + +void board_from_tempboard(tile *temp[], __u8 forward) +{ + __u16 ind = 0; + if (forward) + { + for (ind = 0; ind < BOARD_MAP_SIZE; ind++) + { + tile* bt = &board.tile_map[ind]; + tile* tt = temp[ind]; + if (tt) + { + *bt = *tt; + bt->transition = position2cell(board_position(ind)); + } + else + { + *bt = null_tile; + } + } + } + else + { + ind = BOARD_MAP_SIZE; + while (ind--) + { + tile* bt = &board.tile_map[ind]; + tile* tt = temp[ind]; + if (tt) + { + *bt = *tt; + bt->transition = position2cell(board_position(ind)); + } + else + { + *bt = null_tile; + } + } + } +} + +void tempboard_move_tile(tile* temp[], __u16 from, __u16 to) +{ + temp[to] = temp[from]; + temp[to]->animate = true; + temp[from] = 0; +} + +void tempboard_merge_tile(tile* temp[], __u16 from, __u16 to) +{ + temp[from]->merged = true; + temp[from]->merged_rect = temp[to]->cell; + tempboard_move_tile(temp,from,to); +} + +__u32 random_u32(__u32 max) +{ + return ((rand() * 1.0) / RAND_MAX) * max; +} diff --git a/programs/games/2048/board.h b/programs/games/2048/board.h new file mode 100644 index 0000000000..a6e89f8fe7 --- /dev/null +++ b/programs/games/2048/board.h @@ -0,0 +1,40 @@ +#ifndef BOARD_H +#define BOARD_H + +#include "defines.h" +#include "cell.h" + +// Draw a new board +void board_init(rect* r); + +// Redraw board and all content (animation will started if needed) +void board_redraw(); + +// Add one tile with 2 or 4 value in a random cell place +// Return true if tile added, false - if no more place for tile +__u8 board_add_random_tile(); + +// Check for available moves +// Return true if board has moves, false - if not +__u8 board_has_moves(); + +// Get score +__u32 board_score(); + +// Try to move all tiles up +// Will return true if something moved or false - if not +__u8 board_up(); + +// Try to move all tiles down +// Will return true if something moved or false - if not +__u8 board_down(); + +// Try to move all tiles left +// Will return true if something moved or false - if not +__u8 board_left(); + +// Try to move all tiles right +// Will return true if something moved or false - if not +__u8 board_right(); + +#endif // BOARD_H diff --git a/programs/games/2048/cell.c b/programs/games/2048/cell.c new file mode 100644 index 0000000000..4b5f3ee88c --- /dev/null +++ b/programs/games/2048/cell.c @@ -0,0 +1,58 @@ +#include "cell.h" + +__u8 tile_draw(tile* t) +{ + if (t->value) + { + __u32 bg_color = 0; + __u32 txt_color = 0; + switch (t->value) + { + case 0 : bg_color = CELL_COLOR; break; + case 2 : bg_color = 0xEEE4DA; txt_color = 0x776E65; break; + case 4 : bg_color = 0xEDE0C8; txt_color = 0x776E65; break; + case 8 : bg_color = 0xF2B179; txt_color = 0xF9F6F2; break; + case 16 : bg_color = 0xF59563; txt_color = 0xF9F6F2; break; + case 32 : bg_color = 0xF67C5F; txt_color = 0xF9F6F2; break; + case 64 : bg_color = 0xF65E3B; txt_color = 0xF9F6F2; break; + case 128 : bg_color = 0xEDCF72; txt_color = 0xF9F6F2; break; + case 256 : bg_color = 0xEDCC61; txt_color = 0xF9F6F2; break; + case 512 : bg_color = 0xEDC850; txt_color = 0xF9F6F2; break; + case 1024 : bg_color = 0xEDC53F; txt_color = 0xF9F6F2; break; + case 2048 : bg_color = 0xEDC22E; txt_color = 0xF9F6F2; break; + default : bg_color = 0x3C3A32; txt_color = 0xF9F6F2; break; + } + + rect* begin = &t->cell; + rect* end = &t->transition; + + if (rect_transform(begin,end,t->ani_step)) + t->animate = false; + + rect_draw(begin,bg_color); + rect_draw_value(begin,t->value,txt_color); + + if (t->merged) + { + if (rect_transform(&t->merged_rect,end,t->ani_step) && + (t->animate == false)) + { + t->animate = true; + t->merged = false; + t->value *= 2; + } + + rect_draw(&t->merged_rect,bg_color); + rect_draw_value(&t->merged_rect,t->value,txt_color); + } + } + + return t->animate; +} + +__u8 tile_mergeable(tile* from, tile* to) +{ + return (from && !from->merged && + to && !to->merged && + (from->value == to->value)); +} diff --git a/programs/games/2048/cell.h b/programs/games/2048/cell.h new file mode 100644 index 0000000000..a543229a78 --- /dev/null +++ b/programs/games/2048/cell.h @@ -0,0 +1,23 @@ +#ifndef CELL_H +#define CELL_H + +#include "defines.h" +#include "rect.h" + +typedef struct { + rect cell; // current rect + __u32 value; // value, 0 - do not draw a tile + __u8 animate; // animation needed: true or false + __u16 ani_step; // step for animation + rect transition; // destination rect for animation + __u8 merged; // merge flag + rect merged_rect;// rect for drawing merged tile +} tile; + +// Draw a tile (animation will started if needed) +__u8 tile_draw(tile* t); + +// Check two tiles for merging +__u8 tile_mergeable(tile* from, tile* to); + +#endif // CELL_H diff --git a/programs/games/2048/defines.c b/programs/games/2048/defines.c new file mode 100644 index 0000000000..0def9a32af --- /dev/null +++ b/programs/games/2048/defines.c @@ -0,0 +1,15 @@ +#include "defines.h" + +inline void enable_scancode() { + __asm__ __volatile__("int $0x40"::"a"(66),"b"(1),"c"(1)); +} + +inline void clear_key_buffer() { + int i = 0; + for (i = 0; i < 120; i++) + __menuet__getkey(); +} + +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 new file mode 100644 index 0000000000..af0e66e680 --- /dev/null +++ b/programs/games/2048/defines.h @@ -0,0 +1,39 @@ +#ifndef DEFINES_H +#define DEFINES_H + +#include +#include +#include +#include + +inline void enable_scancode(); +inline void clear_key_buffer(); +inline void vsync(); + +#define false (0) +#define true (1) + +#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 START_COUNT (2) // tiles count for new game + +#define WND_WIDTH (400) // main window width +#define WND_HEIGHT (400) // main window height + +#define GAME_BORDER (30) // minimum border size around board +#define GAME_BG_COLOR (0x34FAF8EF) // main window background color + +#define SCORE_HEIGHT (21) // minimum height for score text + +#define BOARD_SPACING (10) // spacing between cells +#define BOARD_COUNT (4) // row and column count +#define BOARD_MAP_SIZE (16) // cells total count (row * column) +#define BOARD_BG_COLOR (0xBBADA0) // board color + +#define CELL_COLOR (0xCDC0B4) // cell color + +#endif // DEFINES_H diff --git a/programs/games/2048/game.c b/programs/games/2048/game.c new file mode 100644 index 0000000000..c50e2f783b --- /dev/null +++ b/programs/games/2048/game.c @@ -0,0 +1,155 @@ +#include "game.h" + +struct { + rect new_game_button;// new game button place + rect score_rect; // score place + __u8 over; // flag for game over +} game; + +void game_draw_top() +{ + if (game.over) + { + __menuet__make_button(game.new_game_button.x, + game.new_game_button.y, + game.new_game_button.width, + game.new_game_button.height, + NEW_GAME_BUTTON, + BOARD_BG_COLOR); + rect_draw_text(&game.new_game_button,"NEW GAME",8,GAME_BG_COLOR); + } + + rect_draw(&game.score_rect,BOARD_BG_COLOR); + rect_draw_value(&game.score_rect,board_score(),GAME_BG_COLOR); +} + +void game_init() +{ + game.over = false; + // place window at the center of screen + __u16 screen_w = 0; + __u16 screen_h = 0; + __menuet__get_screen_max(&screen_w,&screen_h); + + __menuet__window_redraw(1); + + __menuet__define_window((screen_w - WND_WIDTH) / 2, + (screen_h - WND_HEIGHT) / 2, + WND_WIDTH, + WND_HEIGHT, + GAME_BG_COLOR, + 0, + (__u32)header); + + // find info about window client area + __menuet__get_process_table(&proc_info,PID_WHOAMI); + + // calc board + rect av_area = {0}; + av_area.x = GAME_BORDER; + av_area.y = (SCORE_HEIGHT > GAME_BORDER) ? SCORE_HEIGHT : GAME_BORDER; + av_area.width = proc_info.client_width - av_area.x * 2; + av_area.height = proc_info.client_height - av_area.y - GAME_BORDER; + // minimal square + if (av_area.width < av_area.height) + { + av_area.y += (av_area.height - av_area.width) / 2; + av_area.height = av_area.width; + } + else // if (av_area.height < av_area.width) + { + av_area.x += (av_area.width - av_area.height) / 2; + av_area.width = av_area.height; + } + + board_init(&av_area); + + game.new_game_button.x = av_area.x; + game.new_game_button.y = (av_area.y - SCORE_HEIGHT) / 2; + game.new_game_button.width = (av_area.width - BOARD_SPACING) / 2; + game.new_game_button.height = SCORE_HEIGHT; + + game.score_rect.x = av_area.x + (av_area.width + BOARD_SPACING) / 2; + game.score_rect.y = (av_area.y - SCORE_HEIGHT) / 2; + game.score_rect.width = (av_area.width - BOARD_SPACING) / 2; + game.score_rect.height = SCORE_HEIGHT; + + game_draw_top(); + + __menuet__window_redraw(2); +} + +void game_redraw() +{ + __menuet__get_process_table(&proc_info,PID_WHOAMI); + + // start redraw + __menuet__window_redraw(1); + + vsync(); + __menuet__define_window(0, // __u16 x1 : ignored + 0, // __u16 y1 : ignored + 0, // __u16 xsize : ignored + 0, // __u16 ysize : ignored + GAME_BG_COLOR, // __u32 body_color + 0, // __u32 grab_color + (__u32)header); // __u32 frame_color or header + + game_draw_top(); + board_redraw(); + + // end redraw + __menuet__window_redraw(2); +} + +void game_move_up() +{ + if (board_up()) + { + board_redraw(); + __u8 added = board_add_random_tile(); + board_redraw(); + + game.over = !added || !board_has_moves(); + game_draw_top(); + } +} + +void game_move_down() +{ + if (board_down()) + { + board_redraw(); + __u8 added = board_add_random_tile(); + board_redraw(); + + game.over = !added || !board_has_moves(); + game_draw_top(); + } +} + +void game_move_left() +{ + if (board_left()) + { + board_redraw(); + __u8 added = board_add_random_tile(); + board_redraw(); + + game.over = !added || !board_has_moves(); + game_draw_top(); + } +} + +void game_move_right() +{ + if (board_right()) + { + board_redraw(); + __u8 added = board_add_random_tile(); + board_redraw(); + + game.over = !added || !board_has_moves(); + game_draw_top(); + } +} diff --git a/programs/games/2048/game.h b/programs/games/2048/game.h new file mode 100644 index 0000000000..31a82d4b58 --- /dev/null +++ b/programs/games/2048/game.h @@ -0,0 +1,30 @@ +#ifndef GAME_H +#define GAME_H + +#include "defines.h" +#include "board.h" + +static const char header[] = "2048"; +static struct process_table_entry proc_info = {0}; + +#define NEW_GAME_BUTTON (0xFF) + +// Start a new game +void game_init(); + +// Redraw game content +void game_redraw(); + +// Move Up +void game_move_up(); + +// Move Down +void game_move_down(); + +// Move Left +void game_move_left(); + +// Move Right +void game_move_right(); + +#endif // GAME_H diff --git a/programs/games/2048/main.c b/programs/games/2048/main.c new file mode 100644 index 0000000000..3cbda4461d --- /dev/null +++ b/programs/games/2048/main.c @@ -0,0 +1,54 @@ +#include "game.h" + +#define KEY_RELEASED 0x80 + +void main() +{ + enable_scancode(); + game_init(); + for(;;) + { + int ev = __menuet__wait_for_event(); + switch (ev) + { + case 1 : // EVENT_REDRAW: + game_redraw(); + break; + case 2 : // EVENT_KEY: + { + ev = __menuet__getkey() & 0xFF; + switch (ev) + { + case ((K_Up & 0xFF) | KEY_RELEASED) : // key Up released + game_move_up(); + clear_key_buffer(); + break; + case ((K_Down & 0xFF) | KEY_RELEASED) : // key Down released + game_move_down(); + clear_key_buffer(); + break; + case ((K_Left & 0xFF) | KEY_RELEASED) : // key Left released + game_move_left(); + clear_key_buffer(); + break; + case ((K_Right & 0xFF) | KEY_RELEASED) : // key Right released + game_move_right(); + clear_key_buffer(); + break; + } + + break; + } + case 3 : // EVENT_BUTTON + ev = __menuet__get_button_id(); + switch (ev) + { + case NEW_GAME_BUTTON : + game_init(); + break; + default : // close + return; + } + } + } +} diff --git a/programs/games/2048/rect.c b/programs/games/2048/rect.c new file mode 100644 index 0000000000..122dff5615 --- /dev/null +++ b/programs/games/2048/rect.c @@ -0,0 +1,98 @@ +#include "rect.h" + +void rect_draw(rect* r, __u32 color) +{ + __menuet__bar(r->x,r->y,r->width,r->height,color); +} + +__u8 rect_transform(rect* from, rect* to, __u16 step) +{ + if (from->width < to->width) + { + from->width += (ANIM_STEP << 1); + if (from->width > to->width) from->width = to->width; + } + else if (from->width > to->width) + { + from->width -= (ANIM_STEP << 1); + if (from->width < to->width) from->width = to->width; + } + + if (from->height < to->height) + { + from->height += (ANIM_STEP << 1); + if (from->height > to->height) from->height = to->height; + } + else if (from->height > to->height) + { + from->height -= (ANIM_STEP << 1); + if (from->height < to->height) from->height = to->height; + } + + if (from->x < to->x) + { + from->x += ANIM_STEP; + if (from->x > to->x) from->x = to->x; + } + else if (from->x > to->x) + { + from->x -= ANIM_STEP; + if (from->x < to->x) from->x = to->x; + } + + if (from->y < to->y) + { + from->y += ANIM_STEP; + if (from->y > to->y) from->y = to->y; + } + else if (from->y > to->y) + { + from->y -= ANIM_STEP; + if (from->y < to->y) from->y = to->y; + } + + return (from->x == to->x) && + (from->y == to->y) && + (from->width == to->width) && + (from->height == to->height); +} + +void rect_draw_text(rect *r, char *txt, __u32 len, __u32 color) +{ + __menuet__write_text(r->x + 1 + (r->width - len * FONT_WIDTH - len) / 2, + r->y + 1 + (r->height - FONT_HEIGHT) / 2, + 0xFFFFFF,txt,len); + __menuet__write_text(r->x - 1 + (r->width - len * FONT_WIDTH - len) / 2, + r->y - 1 + (r->height - FONT_HEIGHT) / 2, + 0xFFFFFF,txt,len); + __menuet__write_text(r->x - 1 + (r->width - len * FONT_WIDTH - len) / 2, + r->y + 1 + (r->height - FONT_HEIGHT) / 2, + 0xFFFFFF,txt,len); + __menuet__write_text(r->x + 1 + (r->width - len * FONT_WIDTH - len) / 2, + r->y - 1 + (r->height - FONT_HEIGHT) / 2, + 0xFFFFFF,txt,len); + + __menuet__write_text(r->x + 1 + (r->width - len * FONT_WIDTH - len) / 2, + r->y + (r->height - FONT_HEIGHT) / 2, + 0xFFFFFF,txt,len); + __menuet__write_text(r->x - 1 + (r->width - len * FONT_WIDTH - len) / 2, + r->y + (r->height - FONT_HEIGHT) / 2, + 0xFFFFFF,txt,len); + __menuet__write_text(r->x + (r->width - len * FONT_WIDTH - len) / 2, + r->y + 1 + (r->height - FONT_HEIGHT) / 2, + 0xFFFFFF,txt,len); + __menuet__write_text(r->x + (r->width - len * FONT_WIDTH - len) / 2, + r->y - 1 + (r->height - FONT_HEIGHT) / 2, + 0xFFFFFF,txt,len); + + __menuet__write_text(r->x + (r->width - len * FONT_WIDTH - len) / 2, + r->y + (r->height - FONT_HEIGHT) / 2, + 0,txt,len); +} + +void rect_draw_value(rect *r, __u32 v, __u32 color) +{ + char buffer[16] = {0}; + __u32 length = strlen(itoa(v,buffer,10)); + rect_draw_text(r,buffer,length,color); +} diff --git a/programs/games/2048/rect.h b/programs/games/2048/rect.h new file mode 100644 index 0000000000..d03b16877f --- /dev/null +++ b/programs/games/2048/rect.h @@ -0,0 +1,32 @@ +#ifndef RECT_H +#define RECT_H + +#include "defines.h" + +typedef struct { + short x; + short y; + short width; + short height; +} rect; + +typedef struct { + short x; + short y; +} point; + +// Draw rect filled with color +void rect_draw(rect* r, __u32 color); + +// Make transformation step +// Rect 'from' will be changed +// Return 'true' if transformation ends ('from' == 'to') +__u8 rect_transform(rect* from, rect* to, __u16 step); + +// Draw text at the rect center +void rect_draw_text(rect* r, char* txt, __u32 len, __u32 color); + +// Draw value as text at the rect center +void rect_draw_value(rect* r, __u32 v, __u32 color); + +#endif // RECT_H