Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 5228 → Rev 5229

/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
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/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")
/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;
}
/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
/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));
}
/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
/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));
}
/programs/games/2048/defines.h
0,0 → 1,39
#ifndef DEFINES_H
#define DEFINES_H
 
#include <string.h>
#include <stdlib.h>
#include <keys.h>
#include <menuet/gui.h>
 
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
/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();
}
}
/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
/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;
}
}
}
}
/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);
}
/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