- fix flickering (canvas drawing added)
TODO:
 - optimize tile drawing: maybe separate canvas for every tile
 - game over screen
 - last game save / load
 - record save / load

git-svn-id: svn://kolibrios.org@5231 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
raandoom 2014-12-14 17:05:58 +00:00
parent 0587a82809
commit 3fdad8ab94
14 changed files with 204 additions and 30 deletions

View File

@ -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

View File

@ -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")

View File

@ -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;
}

View File

@ -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();

View File

@ -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);
}
}

View File

@ -2,7 +2,7 @@
#define CELL_H
#include "defines.h"
#include "rect.h"
#include "paint.h"
typedef struct {
rect cell; // current rect

View File

@ -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));
}

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -47,6 +47,7 @@ void main()
game_init();
break;
default : // close
game_exit();
return;
}
}

133
programs/games/2048/paint.c Normal file
View File

@ -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);
}
}

View File

@ -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

View File

@ -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;
}