forked from KolibriOS/kolibrios
2048:
- 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:
parent
0587a82809
commit
3fdad8ab94
@ -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
|
||||
|
@ -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")
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define CELL_H
|
||||
|
||||
#include "defines.h"
|
||||
#include "rect.h"
|
||||
#include "paint.h"
|
||||
|
||||
typedef struct {
|
||||
rect cell; // current rect
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
||||
|
@ -47,6 +47,7 @@ void main()
|
||||
game_init();
|
||||
break;
|
||||
default : // close
|
||||
game_exit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
133
programs/games/2048/paint.c
Normal file
133
programs/games/2048/paint.c
Normal 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);
|
||||
}
|
||||
}
|
17
programs/games/2048/paint.h
Normal file
17
programs/games/2048/paint.h
Normal 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
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user