From efb7aefdec3ab1174a3b1928f8b0285084a97c08 Mon Sep 17 00:00:00 2001 From: "qiuyiuestc@gmail.com" Date: Mon, 23 May 2011 13:36:26 +0000 Subject: reconstruct module examples git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1427 bbd45198-f89e-11dd-88c7-29a3b14d5316 --- examples/module/rtgui_app/tetris/SConstruct | 31 + examples/module/rtgui_app/tetris/application.c | 30 + examples/module/rtgui_app/tetris/tetris.h | 61 ++ examples/module/rtgui_app/tetris/tetris_modal.c | 730 ++++++++++++++++++++++++ examples/module/rtgui_app/tetris/tetris_ui.c | 184 ++++++ examples/module/rtgui_app/tetris/tetris_view.c | 218 +++++++ 6 files changed, 1254 insertions(+) create mode 100644 examples/module/rtgui_app/tetris/SConstruct create mode 100644 examples/module/rtgui_app/tetris/application.c create mode 100644 examples/module/rtgui_app/tetris/tetris.h create mode 100644 examples/module/rtgui_app/tetris/tetris_modal.c create mode 100644 examples/module/rtgui_app/tetris/tetris_ui.c create mode 100644 examples/module/rtgui_app/tetris/tetris_view.c (limited to 'examples/module/rtgui_app') diff --git a/examples/module/rtgui_app/tetris/SConstruct b/examples/module/rtgui_app/tetris/SConstruct new file mode 100644 index 0000000000..28b4ebd0a3 --- /dev/null +++ b/examples/module/rtgui_app/tetris/SConstruct @@ -0,0 +1,31 @@ +import os +import sys + +EXEC_PATH = '/home/shaolin/CodeSourcery/Sourcery_G++_Lite/bin' +RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..') +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +PREFIX = 'arm-none-eabi-' +env = Environment(tools = ['mingw'], + AS = PREFIX + 'gcc', + ASFLAGS = '', + CC = PREFIX + 'gcc', + CCFLAGS = '-mcpu=arm920t -O0 -fPIC' , + AR = PREFIX + 'ar', + ARFLAGS = '-rc', + LINK = PREFIX + 'ld', + LINKFLAGS = '-z max-page-size=0x4 -shared -fPIC -e rt_application_init -nostdlib -s', + CPPPATH = [ + RTT_ROOT + '/include', + RTT_ROOT + '/bsp/mini2440', + RTT_ROOT + '/components/rtgui/include', + RTT_ROOT + '/components/rgtui/common', + RTT_ROOT + '/components/rtgui/server', + RTT_ROOT + '/components/rtgui/widgets' + ]) +env.PrependENVPath('PATH', EXEC_PATH) + +target = 'tetris.so' +src = Glob('*.c') + +env.Program(target, src) + diff --git a/examples/module/rtgui_app/tetris/application.c b/examples/module/rtgui_app/tetris/application.c new file mode 100644 index 0000000000..d845346eb3 --- /dev/null +++ b/examples/module/rtgui_app/tetris/application.c @@ -0,0 +1,30 @@ +/* + * File : app.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://openlab.rt-thread.com/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2010-08-28 Yi.Qiu the first version + */ + +#include +#include +#include +#include +#include +#include "tetris.h" + +int rt_application_init(void) +{ + rt_thread_t tid; + + tid = rt_thread_create("tetris", tetris_ui_entry, RT_NULL, 2048, 20, 5); + if (tid != RT_NULL) rt_thread_startup(tid); + return 0; +} + diff --git a/examples/module/rtgui_app/tetris/tetris.h b/examples/module/rtgui_app/tetris/tetris.h new file mode 100644 index 0000000000..b5ef13785f --- /dev/null +++ b/examples/module/rtgui_app/tetris/tetris.h @@ -0,0 +1,61 @@ +/* + * File : tetris_modal.c + * This file is part of RTGUI in RT-Thread RTOS + * COPYRIGHT (C) 2010, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2010-08-14 Yi.Qiu first version + */ + + #include + + struct rt_tetris; + typedef struct rt_tetris rt_tetris_t; + + struct rt_tetris_view; + typedef struct rt_tetris_view rt_tetris_view_t; + + typedef rt_err_t (*on_update)(rt_tetris_view_t* thiz, rt_tetris_t* tetris); + + struct rt_tetris_view + { + rt_uint32_t width; + rt_uint32_t height; + + on_update update; + on_update update_next_brick; + on_update update_level; + on_update update_score_and_lines; + void *private; + }; + + rt_tetris_t* rt_tetris_create(rt_uint32_t width, rt_uint32_t height); + rt_err_t rt_tetris_destory(rt_tetris_t* thiz); + rt_err_t rt_tetris_start(rt_tetris_t* thiz); + rt_err_t rt_tetris_pause(rt_tetris_t* thiz); + rt_uint32_t rt_tetris_width(rt_tetris_t* thiz); + rt_uint32_t* rt_tetris_next_brick(rt_tetris_t* thiz); + rt_uint32_t rt_tetris_level(rt_tetris_t* thiz); + rt_uint32_t rt_tetris_lines(rt_tetris_t* thiz); + rt_uint32_t rt_tetris_score(rt_tetris_t* thiz); + rt_uint32_t rt_tetris_height(rt_tetris_t* thiz); + rt_bool_t rt_tetris_status(rt_tetris_t* thiz); + rt_err_t rt_tetris_down(rt_tetris_t* thiz); + rt_err_t rt_tetris_left(rt_tetris_t* thiz); + rt_err_t rt_tetris_right(rt_tetris_t* thiz); + rt_err_t rt_tetris_drop(rt_tetris_t* thiz); + rt_err_t rt_tetris_rotate(rt_tetris_t* thiz, rt_bool_t direction); + rt_err_t rt_tetris_add_view(rt_tetris_t* thiz, rt_tetris_view_t* view); + rt_err_t rt_tetris_delete_view(rt_tetris_t* thiz, rt_tetris_view_t* view); + rt_err_t rt_tetris_check_collision(rt_tetris_t* thiz, rt_uint32_t block); + + rt_tetris_view_t* rt_tetris_view_create(void* private); + rt_err_t rt_tetris_view_destroy(rt_tetris_view_t* thiz); + +void tetris_ui_entry(void* parameter); + diff --git a/examples/module/rtgui_app/tetris/tetris_modal.c b/examples/module/rtgui_app/tetris/tetris_modal.c new file mode 100644 index 0000000000..01b5850e96 --- /dev/null +++ b/examples/module/rtgui_app/tetris/tetris_modal.c @@ -0,0 +1,730 @@ +/* + * File : tetris_modal.c + * This file is part of RTGUI in RT-Thread RTOS + * COPYRIGHT (C) 2010, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2010-08-14 Yi.Qiu first version + */ + +#include +#include +#include "tetris.h" + +struct rt_tetris +{ + rt_uint32_t width; /* the width of the tetris */ + rt_uint32_t height; /* the height of the tetris */ + rt_uint16_t* panel; /* the panel of the tetris */ + rt_uint32_t* brick; /* the current brick of the tetris */ + rt_uint32_t* next_brick; /* the next brick of the tetris */ + rt_tetris_view_t* view; /* the view on which the tetris show */ + rt_uint32_t level; /* game level */ + rt_uint32_t lines; /* released lines count */ + rt_uint32_t score; /* total scores statistic */ + rt_bool_t status; /* game status, pause or runing */ +}; + +static const rt_uint32_t g_brick[][4] = +{ + {23,7,8,22}, + {23,7,8,24}, + {24,7,8,25}, + {8,7,9,23}, + {8,7,9,24}, + {8,7,9,25}, + {7,6,8,9}, +}; + +static rt_err_t rt_tetris_append_brick(rt_tetris_t* thiz, rt_uint32_t brick[]); +static rt_err_t rt_tetris_delete_brick(rt_tetris_t* thiz, rt_uint32_t brick[]); +static rt_err_t rt_tetris_release_lines(rt_tetris_t* thiz, rt_uint32_t brick[]); +static rt_err_t rt_tetris_is_reach_top(rt_tetris_t* thiz, rt_uint32_t brick[]); +static rt_err_t rt_tetris_update_brick(rt_tetris_t* thiz); + +/** + * this function create a tetris instance + * + * @param width the width of tetris. + * @param height the height of tetris. + * + * @return the tetris instance + */ +rt_tetris_t* rt_tetris_create(rt_uint32_t width, rt_uint32_t height) +{ + int index; + + rt_tetris_t* thiz = (rt_tetris_t*)rt_malloc(sizeof(rt_tetris_t)); + RT_ASSERT(thiz != RT_NULL); + + thiz->height = height; + thiz->width = width; + thiz->panel = rt_malloc(thiz->height * sizeof(rt_uint32_t)); + rt_memset(thiz->panel, 0, thiz->height * sizeof(rt_uint32_t)); + + thiz->brick = (rt_uint32_t*)rt_malloc(4 * sizeof(rt_uint32_t)); + index = (int)(7.0 * rand()/(RAND_MAX + 1.0)); + rt_memcpy(thiz->brick, g_brick[index], 4 * sizeof(rt_uint32_t)); + + thiz->next_brick= (rt_uint32_t*)rt_malloc(4 * sizeof(rt_uint32_t)); + index = (int)(7.0 * rand()/(RAND_MAX + 1.0)); + rt_memcpy(thiz->next_brick, g_brick[index], 4 * sizeof(rt_uint32_t)); + + thiz->view = RT_NULL; + thiz->level = 0; + thiz->lines = 0; + thiz->score = 0; + thiz->status = RT_FALSE; + + return thiz; +} + +/** + * this function destory a tetris instance + * + * @param thiz the tetris instance. + * + * @return RT_EOK + */ +rt_err_t rt_tetris_destory(rt_tetris_t* thiz) +{ + RT_ASSERT(thiz->panel && thiz->brick && thiz->next_brick); + + rt_free(thiz->panel); + rt_free(thiz->brick); + rt_free(thiz->next_brick); + rt_free(thiz); + + return RT_EOK; +} + +/** + * this function start tetris game + * + * @param thiz the tetris instance. + * + * @return RT_EOK + */ +rt_err_t rt_tetris_start(rt_tetris_t* thiz) +{ + RT_ASSERT(thiz != RT_NULL); + + /* update next brick on view */ + thiz->view->update_next_brick(thiz->view, thiz); + + /* update level */ + thiz->view->update_level(thiz->view, thiz); + + /* update lines and score */ + thiz->view->update_score_and_lines(thiz->view, thiz); + + thiz->status = RT_TRUE; + + return RT_EOK; +} + +/** + * this function pause tetris game + * + * @param thiz the tetris instance. + * + * @return RT_EOK + */ +rt_err_t rt_tetris_pause(rt_tetris_t* thiz) +{ + RT_ASSERT(thiz != RT_NULL); + + thiz->status = RT_FALSE; + + return RT_EOK; +} + +/** + * this function get width of a tetris instance + * + * @param thiz the tetris instance. + * + * @return the width of the tetris instance + */ +rt_uint32_t rt_tetris_width(rt_tetris_t* thiz) +{ + RT_ASSERT(thiz != RT_NULL); + + return thiz->width; +} + +/** + * this function get next brick of a tetris instance + * + * @param thiz the tetris instance. + * + * @return the next brick of the tetris instance + */ +rt_uint32_t* rt_tetris_next_brick(rt_tetris_t* thiz) +{ + RT_ASSERT(thiz != RT_NULL); + + return thiz->next_brick; +} + +/** + * this function get level of the tetris instance + * + * @param thiz the tetris instance. + * + * @return the level of the tetris instance + */ +rt_uint32_t rt_tetris_level(rt_tetris_t* thiz) +{ + RT_ASSERT(thiz != RT_NULL); + + return thiz->level; +} + +/** + * this function get released lines of the tetris instance + * + * @param thiz the tetris instance. + * + * @return the released lines of the tetris instance + */ +rt_uint32_t rt_tetris_lines(rt_tetris_t* thiz) +{ + RT_ASSERT(thiz != RT_NULL); + + return thiz->lines; +} + +/** + * this function get score of the tetris instance + * + * @param thiz the tetris instance. + * + * @return the score of the tetris instance + */ +rt_uint32_t rt_tetris_score(rt_tetris_t* thiz) +{ + RT_ASSERT(thiz != RT_NULL); + + return thiz->score; +} + +/** + * this function get height of a tetris instance + * + * @param thiz the tetris instance. + * + * @return the height of the tetris instance + */ +rt_uint32_t rt_tetris_height(rt_tetris_t* thiz) +{ + RT_ASSERT(thiz != RT_NULL); + + return thiz->height; +} + +/** + * this function get status of a tetris instance + * + * @param thiz the tetris instance. + * + * @return the status of the tetris instance + */ +rt_bool_t rt_tetris_status(rt_tetris_t* thiz) +{ + RT_ASSERT(thiz != RT_NULL); + + return thiz->status; +} + +/** + * this function makes current brick move down + * + * @param thiz the tetris instance. + * + * @return RT_EOK on success, -RT_ERROR on fail + */ +rt_err_t rt_tetris_down(rt_tetris_t* thiz) +{ + int i; + + RT_ASSERT(thiz != RT_NULL); + + if(thiz->status == RT_FALSE) return -RT_ERROR; + + /* delete the brick from tetris panel */ + rt_tetris_delete_brick(thiz, thiz->brick); + + for(i=0; i<4; i++) + { + /* check collision and bottom*/ + if((thiz->brick[i] >= thiz->width * (thiz->height - 1)) + || rt_tetris_check_collision(thiz, thiz->brick[i] + thiz->width) == RT_EOK) + { + /* restore the deleted brick */ + rt_tetris_append_brick(thiz, thiz->brick); + + if(rt_tetris_is_reach_top(thiz, thiz->brick) == RT_EOK) + { + rt_memset(thiz->panel, 0xff, thiz->height * sizeof(rt_uint32_t)); + + /* update view */ + thiz->view->update(thiz->view, thiz); + + /* game over */ + return -RT_ETIMEOUT; + } + + if(rt_tetris_release_lines(thiz, thiz->brick) == RT_EOK) + { + /* update view */ + thiz->view->update(thiz->view, thiz); + } + + rt_tetris_update_brick(thiz); + return -RT_ERROR; + } + } + + for(i=0; i<4; i++) + { + /* increase one line */ + thiz->brick[i] += thiz->width; + } + + /* append the brick to tetris panel */ + rt_tetris_append_brick(thiz, thiz->brick); + + /* update view */ + thiz->view->update(thiz->view, thiz); + + return RT_EOK; +} + +/** + * this function makes current brick move left + * + * @param thiz the tetris instance. + * + * @return RT_EOK on success, -RT_ERROR on fail + */ +rt_err_t rt_tetris_left(rt_tetris_t* thiz) +{ + int i; + RT_ASSERT(thiz != RT_NULL); + + if(thiz->status == RT_FALSE) return -RT_ERROR; + + /* delete the brick from tetris panel */ + rt_tetris_delete_brick(thiz, thiz->brick); + + for(i=0; i<4; i++) + { + /* check left board */ + if((thiz->brick[i] % thiz->width) == 0) + { + /* restore the deleted brick */ + rt_tetris_append_brick(thiz, thiz->brick); + return -RT_ERROR; + } + + if(rt_tetris_check_collision(thiz, thiz->brick[i] - 1) == RT_EOK) + { + /* restore the deleted brick */ + rt_tetris_append_brick(thiz, thiz->brick); + return -RT_ERROR; + } + } + + for(i=0; i<4; i++) + { + /* move one step to left */ + thiz->brick[i] --;; + } + + /* append the brick to tetris panel */ + rt_tetris_append_brick(thiz, thiz->brick); + + /* update view */ + thiz->view->update(thiz->view, thiz); + + return RT_EOK; +} + +/** + * this function makes current brick move right + * + * @param thiz the tetris instance. + * + * @return RT_EOK on success, -RT_ERROR on fail + */ +rt_err_t rt_tetris_right(rt_tetris_t* thiz) +{ + int i; + RT_ASSERT(thiz != RT_NULL); + + if(thiz->status == RT_FALSE) return -RT_ERROR; + + /* delete the brick from tetris panel */ + rt_tetris_delete_brick(thiz, thiz->brick); + + for(i=0; i<4; i++) + { + /* check left board */ + if(((thiz->brick[i] + 1) % thiz->width) == 0) + { + /* restore the deleted brick */ + rt_tetris_append_brick(thiz, thiz->brick); + return -RT_ERROR; + } + + /* check collision */ + if(rt_tetris_check_collision(thiz, thiz->brick[i] + 1) == RT_EOK) + { + /* restore the deleted brick */ + rt_tetris_append_brick(thiz, thiz->brick); + return -RT_ERROR; + } + } + + for(i=0; i<4; i++) + { + /* move one step to right */ + thiz->brick[i] ++;; + } + + /* append the brick to tetris panel */ + rt_tetris_append_brick(thiz, thiz->brick); + + /* update view */ + thiz->view->update(thiz->view, thiz); + + return RT_EOK; +} + +/** + * this function makes current brick drop quickly + * + * @param thiz the tetris instance. + * + * @return RT_EOK on success, -RT_ERROR on fail + */ +rt_err_t rt_tetris_drop(rt_tetris_t* thiz) +{ + rt_err_t ret; + RT_ASSERT(thiz != RT_NULL); + + if(thiz->status == RT_FALSE) return -RT_ETIMEOUT; + + /* move down until blocked */ + while((ret = rt_tetris_down(thiz)) == RT_EOK); + + return ret; +} + +/** + * this function makes current brick do rotation + * + * @param thiz the tetris instance. + * + * @return RT_EOK on success, -RT_ERROR on fail + */ +rt_err_t rt_tetris_rotate(rt_tetris_t* thiz, rt_bool_t direction) +{ + int i; + rt_uint32_t tmp[4]; + RT_ASSERT(thiz != RT_NULL); + + if(thiz->status == RT_FALSE) return -RT_ERROR; + + rt_tetris_delete_brick(thiz, thiz->brick); + + tmp[0] = thiz->brick[0]; + for(i=1; i<4; i++) + { + int diff = thiz->brick[0] - thiz->brick[i]; + if(diff == 1) + { + tmp[i] = thiz->brick[0] - thiz->width; + } + else if(diff == -1) + { + tmp[i] = thiz->brick[0] + thiz->width; + } + else if(diff == 2) + { + tmp[i] = thiz->brick[0] - 2 * thiz->width; + } + else if(diff == -2) + { + tmp[i] = thiz->brick[0] + 2 * thiz->width; + } + else if(diff == thiz->width - 1) + { + tmp[i] = thiz->brick[0] + thiz->width + 1; + } + else if(diff == 1 - thiz->width) + { + tmp[i] = thiz->brick[0] - thiz->width - 1; + } + else if(diff == thiz->width) + { + if((thiz->brick[0] + 1) % thiz->width == 0) + { + /* restore the deleted brick */ + rt_tetris_append_brick(thiz, thiz->brick); + return -RT_ERROR; + } + else tmp[i] = thiz->brick[0] + 1; + } + else if(diff == -1 * (thiz->width)) + { + if(thiz->brick[0] % thiz->width == 0) + { + /* restore the deleted brick */ + rt_tetris_append_brick(thiz, thiz->brick); + return -RT_ERROR; + } + else tmp[i] = thiz->brick[0] - 1; + } + else if(diff == thiz->width + 1) + { + tmp[i] = thiz->brick[0] - thiz->width + 1; + } + else if(diff == -1 - thiz->width) + { + tmp[i] = thiz->brick[0] + thiz->width - 1; + } + else if(diff == 2 * thiz->width) + { + if((thiz->brick[0] % thiz->width) >= (thiz->width - 2)) + { + /* restore the deleted brick */ + rt_tetris_append_brick(thiz, thiz->brick); + return -RT_ERROR; + } + else tmp[i] = thiz->brick[0] + 2; + } + else if(diff == -2 * thiz->width) + { + if((thiz->brick[0] % thiz->width) < 2) + { + /* restore the deleted brick */ + rt_tetris_append_brick(thiz, thiz->brick); + return -RT_ERROR; + } + else tmp[i] = thiz->brick[0] - 2; + } + + if(tmp[i] > (thiz->height) * thiz->width) + { + /* restore the deleted brick */ + rt_tetris_append_brick(thiz, thiz->brick); + return -RT_ERROR; + } + + if(rt_tetris_check_collision(thiz, tmp[i]) == RT_EOK) + { + /* restore the deleted brick */ + rt_tetris_append_brick(thiz, thiz->brick); + return -RT_ERROR; + } + } + + /* do roration */ + for(i=0; i<4; i++) + { + thiz->brick[i] = tmp[i]; + } + + /* append the brick to tetris panel */ + rt_tetris_append_brick(thiz, thiz->brick); + + /* update view */ + thiz->view->update(thiz->view, thiz); + + return RT_EOK; +} + +/** + * this function add a view to the tetris + * + * @param thiz the tetris instance. + * @param view the view instance. + * + * @return RT_EOK on success, -RT_ERROR on fail + */ +rt_err_t rt_tetris_add_view(rt_tetris_t* thiz, rt_tetris_view_t* view) +{ + RT_ASSERT(thiz != RT_NULL); + + /* Only suppurt single view now */ + thiz->view = view; + + return RT_EOK; +} + +/** + * this function delete a view from the tetris + * + * @param thiz the tetris instance. + * @param view the view instance. + * + * @return RT_EOK on success, -RT_ERROR on fail + */ + +rt_err_t rt_tetris_delete_view(rt_tetris_t* thiz, rt_tetris_view_t* view) +{ + RT_ASSERT(thiz != RT_NULL); + + thiz->view = RT_NULL; + + return RT_EOK; +} + +/** + * this function used to check collision + * + * @param thiz the tetris instance. + * @param block the block to be checked. + * + * @return RT_EOK on collision, -RT_ERROR on not collision + */ +rt_err_t rt_tetris_check_collision(rt_tetris_t* thiz, rt_uint32_t block) +{ + RT_ASSERT(thiz != RT_NULL); + RT_ASSERT(block < thiz->height * thiz->width); + + if((thiz->panel[block/thiz->width] & (1 << (block % thiz->width))) + == (1 << (block % thiz->width))) + { + return RT_EOK; + } + else + { + return -RT_ERROR; + } +} + +static rt_err_t rt_tetris_update_brick(rt_tetris_t* thiz) +{ + int index; + + RT_ASSERT(thiz != RT_NULL); + + index = (int)(7.0 * rand()/(RAND_MAX + 1.0)); + + rt_memcpy(thiz->brick, thiz->next_brick, 4 * sizeof(rt_uint32_t)); + rt_memcpy(thiz->next_brick, g_brick[index], 4 * sizeof(rt_uint32_t)); + + /* update next brick on view */ + thiz->view->update_next_brick(thiz->view, thiz); + + return RT_EOK; +} + +static rt_err_t rt_tetris_append_brick(rt_tetris_t* thiz, rt_uint32_t brick[]) +{ + int i; + + RT_ASSERT(thiz != RT_NULL); + RT_ASSERT(brick != RT_NULL); + + for(i=0; i<4; i++) + { + int y = brick[i]/thiz->width; + int x = brick[i]%thiz->width; + + thiz->panel[y] |= (1<width; + int x = brick[i]%thiz->width; + + thiz->panel[y] &= ~(1<width == 0) + return RT_EOK; + } + + return -RT_ERROR; +} + +static rt_err_t rt_tetris_release_lines(rt_tetris_t* thiz, rt_uint32_t brick[]) +{ + int i, j, check_line = 0; + rt_bool_t line_released = -RT_ERROR; + + RT_ASSERT(thiz != RT_NULL); + RT_ASSERT(brick != RT_NULL); + + for(i=0; i<4; i++) + { + /* choose a line */ + check_line = brick[i]/thiz->width; + if((thiz->panel[check_line]) == ((1 << thiz->width) - 1)) + { + for(j=check_line; j>0; j--) + { + thiz->panel[j] = thiz->panel[j-1]; + } + + /* clear the first line */ + thiz->panel[0] = 0; + + for(j=i+1; j<4; j++) + { + if(brick[j] < brick[i]) + { + brick[j] += thiz->width; + } + } + + thiz->lines++; + thiz->score += 100; + line_released = RT_EOK; + } + } + + if(line_released == RT_EOK) + { + /* update view */ + thiz->view->update_score_and_lines(thiz->view, thiz); + return RT_EOK; + } + else + { + return -RT_ERROR; + } +} + diff --git a/examples/module/rtgui_app/tetris/tetris_ui.c b/examples/module/rtgui_app/tetris/tetris_ui.c new file mode 100644 index 0000000000..808a713602 --- /dev/null +++ b/examples/module/rtgui_app/tetris/tetris_ui.c @@ -0,0 +1,184 @@ +/* + * File : tetris_ui.c + * This file is part of RTGUI in RT-Thread RTOS + * COPYRIGHT (C) 2010, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2010-08-14 Yi.Qiu first version + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "tetris.h" + +struct app_info +{ + struct rtgui_view* home_view; + struct rtgui_workbench* workbench; + rt_tetris_t * tetris; + rt_tetris_view_t* tetris_view; + rtgui_timer_t* _timer; +}; +typedef struct app_info app_info; +static app_info g_app_info; + +static void _game_over(void) +{ + rtgui_timer_stop(g_app_info._timer); + rt_tetris_pause(g_app_info.tetris); + rt_tetris_destory(g_app_info.tetris); + rt_tetris_view_destroy(g_app_info.tetris_view); + rtgui_view_destroy(g_app_info.home_view); + rtgui_workbench_close(g_app_info.workbench); + rt_kprintf("GAME OVER\n"); +} + +static rt_bool_t home_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event) +{ + if (event->type == RTGUI_EVENT_PAINT) + { + struct rtgui_dc* dc; + rtgui_rect_t rect; + + /* draw child */ + rtgui_view_event_handler(widget, event); + + dc = rtgui_dc_begin_drawing(widget); + if (dc == RT_NULL) return -RT_ERROR; + rect.x1 = 96; + rect.y1 = 0; + rect.x2 = 128; + rect.y2 = 16; + rtgui_dc_draw_text(dc, "next", &rect); + rect.y1 += 30; + rect.y2 = rect.y1 + 16; + rtgui_dc_draw_text(dc, "level", &rect); + rect.y1 += 22; + rect.y2 = rect.y1 + 16; + rtgui_dc_draw_text(dc, "lines", &rect); + rect.y1 += 22; + rect.y2 = rect.y1 + 16; + rtgui_dc_draw_text(dc, "score", &rect); + rtgui_dc_end_drawing(dc); + + /* start tetris game, removed later */ + rt_tetris_start(g_app_info.tetris); + return RT_FALSE; + } + else if ((event->type == RTGUI_EVENT_KBD)) + { + struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event; + + if (ekbd->type == RTGUI_KEYDOWN) + { + if (ekbd->key == RTGUIK_RIGHT) + { + rt_tetris_right(g_app_info.tetris); + } + else if (ekbd->key == RTGUIK_LEFT) + { + rt_tetris_left(g_app_info.tetris); + } + else if (ekbd->key == RTGUIK_UP) + { + rt_tetris_rotate(g_app_info.tetris, RT_EOK); + } + else if (ekbd->key == RTGUIK_DOWN) + { + if( rt_tetris_drop(g_app_info.tetris) == -RT_ETIMEOUT + && rt_tetris_status(g_app_info.tetris) != RT_FALSE) + { + _game_over(); + } + } + } + } + + return rtgui_view_event_handler(widget, event); +} + +static void _timer_timeout(rtgui_timer_t* timer, void* parameter) +{ + if( rt_tetris_down(g_app_info.tetris) == -RT_ETIMEOUT) + { + _game_over(); + } +} + +static rt_bool_t workbench_event_handler(rtgui_widget_t *widget, rtgui_event_t *event) +{ + if (event->type == RTGUI_EVENT_KBD) + { + struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event; + if (((ekbd->type == RTGUI_KEYUP) && ekbd->key == RTGUIK_HOME) + && !RTGUI_WORKBENCH_IS_MODAL_MODE(g_app_info.workbench)) + { + /* active home view */ + if (g_app_info.workbench->current_view != g_app_info.home_view) + { + rtgui_view_show(g_app_info.home_view, RT_FALSE); + return RT_TRUE; + } + } + } + + return rtgui_workbench_event_handler(widget, event); +} + +void tetris_ui_entry(void* parameter) +{ + rt_mq_t mq; + + mq = rt_mq_create("tetris_ui", 256, 4, RT_IPC_FLAG_FIFO); + rtgui_thread_register(rt_thread_self(), mq); + + g_app_info.workbench = rtgui_workbench_create("main", "workbench"); + if (g_app_info.workbench == RT_NULL) + { + rt_kprintf("can't find panel 'main'\n"); + return; + } + rtgui_widget_set_event_handler(RTGUI_WIDGET(g_app_info.workbench), workbench_event_handler); + + /* add home view */ + g_app_info.home_view = rtgui_view_create("Home"); + rtgui_widget_set_event_handler(RTGUI_WIDGET(g_app_info.home_view), home_view_event_handler); + + rtgui_workbench_add_view(g_app_info.workbench, g_app_info.home_view); + /* this view can be focused */ + RTGUI_WIDGET(g_app_info.home_view)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE; + /* set widget focus */ + rtgui_widget_focus(RTGUI_WIDGET(g_app_info.home_view)); + RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(g_app_info.home_view)) = RTGUI_RGB(0xff, 0xff, 0xff); + rtgui_view_show(g_app_info.home_view, RT_FALSE); + + /* create tetris modal instance */ + g_app_info.tetris = rt_tetris_create(16, 17); + + /* create tetris view instance */ + g_app_info.tetris_view = rt_tetris_view_create(RTGUI_WIDGET(g_app_info.home_view)); + + /* register tetris view to tetris modal */ + rt_tetris_add_view(g_app_info.tetris, g_app_info.tetris_view); + + g_app_info._timer = rtgui_timer_create(40, RT_TIMER_FLAG_PERIODIC, _timer_timeout, RT_NULL); + rtgui_timer_start(g_app_info._timer); + + rtgui_workbench_event_loop(g_app_info.workbench); + rtgui_workbench_destroy(g_app_info.workbench); + + rtgui_thread_deregister(rt_thread_self()); + rt_mq_delete(mq); +} + diff --git a/examples/module/rtgui_app/tetris/tetris_view.c b/examples/module/rtgui_app/tetris/tetris_view.c new file mode 100644 index 0000000000..dcb0cb312a --- /dev/null +++ b/examples/module/rtgui_app/tetris/tetris_view.c @@ -0,0 +1,218 @@ +/* + * File : tetris_view.c + * This file is part of RTGUI in RT-Thread RTOS + * COPYRIGHT (C) 2010, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2010-08-14 Yi.Qiu first version + */ + +#include +#include +#include +#include +#include +#include "tetris.h" + +static rt_err_t _rt_tetris_view_update(rt_tetris_view_t* thiz, rt_tetris_t* tetris); +static rt_err_t _rt_tetris_view_update_next_brick(rt_tetris_view_t* thiz, rt_tetris_t* tetris); +static rt_err_t _rt_tetris_view_update_level(rt_tetris_view_t* thiz, rt_tetris_t* tetris); +static rt_err_t _rt_tetris_view_update_score_and_lines(rt_tetris_view_t* thiz, rt_tetris_t* tetris); + +rt_tetris_view_t* rt_tetris_view_create(void* private) +{ + rt_tetris_view_t* thiz; + + RT_ASSERT(private != RT_NULL) + + thiz = (rt_tetris_view_t*)rt_malloc(sizeof(rt_tetris_view_t)); + thiz->width = 96; + thiz->height = 96; + + thiz->update = _rt_tetris_view_update; + thiz->update_next_brick = _rt_tetris_view_update_next_brick; + thiz->update_level = _rt_tetris_view_update_level; + thiz->update_score_and_lines = _rt_tetris_view_update_score_and_lines; + thiz->private = private; + + return thiz; +} + +rt_err_t rt_tetris_view_destroy(rt_tetris_view_t* thiz) +{ + RT_ASSERT(thiz != RT_NULL); + + rt_free(thiz); + + return RT_EOK; +} + +static rt_err_t _rt_tetris_view_update_next_brick(rt_tetris_view_t* thiz, rt_tetris_t* tetris) +{ + struct rtgui_dc* dc; + struct rtgui_rect rect; + rt_uint32_t width; + rt_uint32_t ppb, i; + rtgui_widget_t* widget; + rt_uint32_t* next_brick; + + RT_ASSERT(thiz != RT_NULL); + RT_ASSERT(tetris != RT_NULL); + + next_brick = rt_tetris_next_brick(tetris); + widget = (rtgui_widget_t*)thiz->private; + width = rt_tetris_width(tetris); + /* pixel per block */ + ppb = thiz->width / width; + + dc = rtgui_dc_begin_drawing(widget); + if (dc == RT_NULL) return -RT_ERROR; + + rect.x1 = 100; + rect.x2 = rect.x1 + 4 * ppb; + rect.y1 = 16; + rect.y2 = rect.y1 + 2 * ppb; + + RTGUI_DC_BC(dc) = RTGUI_RGB(0xff, 0xff, 0xff); + rtgui_dc_fill_rect(dc, &rect); + + for(i=0; i<4; i++) + { + rt_uint32_t y = next_brick[i] / width; + rt_uint32_t x = next_brick[i] % width; + + rect.x1 = 100 + ppb * (x - 6); + rect.x2 = rect.x1 + ppb - 1; + rect.y1 = 16 + ppb * y ; + rect.y2 = rect.y1 + ppb - 1; + + RTGUI_DC_BC(dc) = RTGUI_RGB(0xff, 0x00, 0x00); + rtgui_dc_fill_rect(dc, &rect); + } + + rtgui_dc_end_drawing(dc); + + return RT_EOK; +} + +static rt_err_t _rt_tetris_view_update_level(rt_tetris_view_t* thiz, rt_tetris_t* tetris) +{ + struct rtgui_dc* dc; + struct rtgui_rect rect; + rtgui_widget_t* widget; + char text[4]; + + RT_ASSERT(thiz != RT_NULL); + RT_ASSERT(tetris != RT_NULL); + + widget = (rtgui_widget_t*)thiz->private; + dc = rtgui_dc_begin_drawing(widget); + if (dc == RT_NULL) return -RT_ERROR; + + rect.x1 = 96; + rect.y1 = 42; + rect.x2 = 128; + rect.y2 = rect.y1 + 10; + RTGUI_DC_BC(dc) = RTGUI_RGB(0xff, 0xff, 0xff); + rtgui_dc_fill_rect(dc, &rect); + rt_sprintf(text, "%d", rt_tetris_level(tetris)); + RTGUI_DC_BC(dc) = RTGUI_RGB(0xff, 0x00, 0x00); + rtgui_dc_draw_text(dc, text, &rect); + + /* Redraw panel */ + rtgui_dc_end_drawing(dc); + + return RT_EOK; +} + +static rt_err_t _rt_tetris_view_update_score_and_lines(rt_tetris_view_t* thiz, rt_tetris_t* tetris) +{ + struct rtgui_dc* dc; + struct rtgui_rect rect; + rtgui_widget_t* widget; + char text[4]; + + RT_ASSERT(thiz != RT_NULL); + RT_ASSERT(tetris != RT_NULL); + + widget = (rtgui_widget_t*)thiz->private; + dc = rtgui_dc_begin_drawing(widget); + if (dc == RT_NULL) return -RT_ERROR; + + rect.x1 = 96; + rect.y1 = 64; + rect.x2 = 128; + rect.y2 = rect.y1 + 10; + RTGUI_DC_BC(dc) = RTGUI_RGB(0xff, 0xff, 0xff); + rtgui_dc_fill_rect(dc, &rect); + rt_sprintf(text, "%d", rt_tetris_lines(tetris)); + RTGUI_DC_BC(dc) = RTGUI_RGB(0xff, 0x00, 0x00); + rtgui_dc_draw_text(dc, text, &rect); + + rect.y1 += 22; + rect.y2 = rect.y1 + 10; + RTGUI_DC_BC(dc) = RTGUI_RGB(0xff, 0xff, 0xff); + rtgui_dc_fill_rect(dc, &rect); + rt_sprintf(text, "%d", rt_tetris_score(tetris)); + RTGUI_DC_BC(dc) = RTGUI_RGB(0xff, 0x00, 0x00); + rtgui_dc_draw_text(dc, text, &rect); + + /* Redraw panel */ + rtgui_dc_end_drawing(dc); + + return RT_EOK; +} + +static rt_err_t _rt_tetris_view_update(rt_tetris_view_t* thiz, rt_tetris_t* tetris) +{ + struct rtgui_dc* dc; + struct rtgui_rect rect; + rt_uint32_t width, height; + rt_uint32_t j,k, ppb; + rtgui_widget_t* widget; + + RT_ASSERT(thiz != RT_NULL); + RT_ASSERT(tetris != RT_NULL); + + widget = (rtgui_widget_t*)thiz->private; + width = rt_tetris_width(tetris); + height = rt_tetris_height(tetris); + ppb = thiz->width / width; + + dc = rtgui_dc_begin_drawing(widget); + if (dc == RT_NULL) return -RT_ERROR; + + /* Redraw panel */ + for(j=0; j