diff --git a/components/module/SConstruct b/components/module/SConstruct new file mode 100644 index 0000000000..ccb812ca73 --- /dev/null +++ b/components/module/SConstruct @@ -0,0 +1,36 @@ +import os +import sys +import rtconfig + +RTT_ROOT = os.path.normpath(os.getcwd() + '/../..') +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +import mdk + +target = RTT_ROOT + '/bsp/mini2440/rtthread-mini2440' +projects = [] + +AddOption('--target', + dest='target', + type='string', + help='set target project: mdk') + +if GetOption('target'): + SetOption('no_exec', 1) + +TARGET = target + '.' + rtconfig.TARGET_EXT + +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +Export('env') +Export('RTT_ROOT') +Export('rtconfig') +Export('projects') +Export('TARGET') + +objs = SConscript(RTT_ROOT + '/components/module/tetris/SConscript', variant_dir='build/tetris', duplicate=0) + diff --git a/components/module/rtconfig.h b/components/module/rtconfig.h new file mode 100644 index 0000000000..58416d8e96 --- /dev/null +++ b/components/module/rtconfig.h @@ -0,0 +1,213 @@ +/* RT-Thread config file */ +#ifndef __RTTHREAD_CFG_H__ +#define __RTTHREAD_CFG_H__ + +/* RT_NAME_MAX*/ +#define RT_NAME_MAX 8 + +/* RT_ALIGN_SIZE*/ +#define RT_ALIGN_SIZE 4 + +/* PRIORITY_MAX */ +#define RT_THREAD_PRIORITY_MAX 256 + +/* Tick per Second */ +#define RT_TICK_PER_SECOND 100 + +/* SECTION: RT_DEBUG */ +/* Thread Debug */ +#define RT_DEBUG +/* #define RT_THREAD_DEBUG */ + +#define RT_USING_OVERFLOW_CHECK + +/* Using Hook */ +#define RT_USING_HOOK + +/* Using Software Timer */ +#define RT_USING_TIMER_SOFT +#define RT_TIMER_THREAD_PRIO 8 +#define RT_TIMER_THREAD_STACK_SIZE 512 +#define RT_TIMER_TICK_PER_SECOND 10 + +/* SECTION: IPC */ +/* Using Semaphore */ +#define RT_USING_SEMAPHORE + +/* Using Mutex */ +#define RT_USING_MUTEX + +/* Using Event */ +#define RT_USING_EVENT + +/* Using MailBox */ +#define RT_USING_MAILBOX + +/* Using Message Queue */ +#define RT_USING_MESSAGEQUEUE + +/* SECTION: Memory Management */ +/* Using Memory Pool Management*/ +#define RT_USING_MEMPOOL + +/* Using Dynamic Heap Management */ +#define RT_USING_HEAP + +/* Using Small MM */ +#define RT_USING_SMALL_MEM + +/* Using SLAB Allocator */ +/* #define RT_USING_SLAB */ + +/* SECTION: Device System */ +/* Using Device System */ +#define RT_USING_DEVICE + +/* Using Module System */ +#define RT_USING_MODULE + +/* SECTION: Console options */ +/* the buffer size of console */ +#define RT_CONSOLEBUF_SIZE 128 + +/* SECTION: finsh, a C-Express shell */ +/* Using FinSH as Shell*/ +#define RT_USING_FINSH +/* Using symbol table */ +#define FINSH_USING_SYMTAB +#define FINSH_USING_DESCRIPTION +#define FINSH_THREAD_STACK_SIZE 4096 + +/* SECTION: a runtime libc library */ +/* a runtime libc library */ +/* #define RT_USING_NEWLIB */ + +/* SECTION: C++ support */ +/* Using C++ support */ +/* #define RT_USING_CPLUSPLUS */ + +/* SECTION: Device filesystem support */ +/* using DFS support */ +#define RT_USING_DFS +#define RT_USING_DFS_ELMFAT +/* use long file name feature */ +#define RT_DFS_ELM_USE_LFN 1 +/* the max number of file length */ +#define RT_DFS_ELM_MAX_LFN 32 +/* #define RT_USING_DFS_YAFFS2 */ + +#define RT_USING_DFS_NFS +#define RT_NFS_HOST_EXPORT "192.168.1.5:/" + +/* #define DFS_USING_WORKDIR */ + +/* the max number of mounted filesystem */ +#define DFS_FILESYSTEMS_MAX 2 +/* the max number of opened files */ +#define DFS_FD_MAX 16 +/* the max number of cached sector */ +#define DFS_CACHE_MAX_NUM 4 + +/* Enable freemodbus protocal stack*/ +/* #define RT_USING_MODBUS */ + +/* SECTION: lwip, a lighwight TCP/IP protocol stack */ +/* Using lighweight TCP/IP protocol stack */ +#define RT_USING_LWIP +#define RT_LWIP_DNS + +/* Trace LwIP protocol */ +/* #define RT_LWIP_DEBUG */ + +/* Enable ICMP protocol */ +#define RT_LWIP_ICMP + +/* Enable IGMP protocol */ +#define RT_LWIP_IGMP + +/* Enable UDP protocol */ +#define RT_LWIP_UDP + +/* Enable TCP protocol */ +#define RT_LWIP_TCP + +/* the number of simulatenously active TCP connections*/ +#define RT_LWIP_TCP_PCB_NUM 5 + +/* TCP sender buffer space */ +#define RT_LWIP_TCP_SND_BUF 1024*10 + +/* TCP receive window. */ +#define RT_LWIP_TCP_WND 1024 + +/* Enable SNMP protocol */ +/* #define RT_LWIP_SNMP */ + +/* Using DHCP */ +/* #define RT_LWIP_DHCP */ + +#define RT_LWIP_DNS + +/* ip address of target */ +#define RT_LWIP_IPADDR0 192 +#define RT_LWIP_IPADDR1 168 +#define RT_LWIP_IPADDR2 1 +#define RT_LWIP_IPADDR3 30 + +/* gateway address of target */ +#define RT_LWIP_GWADDR0 192 +#define RT_LWIP_GWADDR1 168 +#define RT_LWIP_GWADDR2 1 +#define RT_LWIP_GWADDR3 1 + +/* mask address of target */ +#define RT_LWIP_MSKADDR0 255 +#define RT_LWIP_MSKADDR1 255 +#define RT_LWIP_MSKADDR2 255 +#define RT_LWIP_MSKADDR3 0 + +/* the number of blocks for pbuf */ +#define RT_LWIP_PBUF_NUM 16 + +/* thread priority of tcpip thread */ +#define RT_LWIP_TCPTHREAD_PRIORITY 128 + +/* mail box size of tcpip thread to wait for */ +#define RT_LWIP_TCPTHREAD_MBOX_SIZE 32 + +/* thread stack size of tcpip thread */ +#define RT_LWIP_TCPTHREAD_STACKSIZE 4096 + +/* thread priority of ethnetif thread */ +#define RT_LWIP_ETHTHREAD_PRIORITY 144 + +/* mail box size of ethnetif thread to wait for */ +#define RT_LWIP_ETHTHREAD_MBOX_SIZE 32 + +/* thread stack size of ethnetif thread */ +#define RT_LWIP_ETHTHREAD_STACKSIZE 1024 + +/* SECTION: RTGUI support */ +/* using RTGUI support */ +#define RT_USING_RTGUI + +/* name length of RTGUI object */ +#define RTGUI_NAME_MAX 16 +/* support 16 weight font */ +#define RTGUI_USING_FONT16 +/* support 16 weight font */ +#define RTGUI_USING_FONT12 +/* support Chinese font */ +#define RTGUI_USING_FONTHZ +/* use DFS as file interface */ +#define RTGUI_USING_DFS_FILERW +/* use font file as Chinese font */ +/* #define RTGUI_USING_HZ_FILE */ +/* use Chinese bitmap font */ +#define RTGUI_USING_HZ_BMP +/* use small size in RTGUI */ +/* #define RTGUI_USING_SMALL_SIZE */ +/* use mouse cursor */ +/* #define RTGUI_USING_MOUSE_CURSOR */ + +#endif diff --git a/components/module/rtconfig.py b/components/module/rtconfig.py new file mode 100644 index 0000000000..2340038cfb --- /dev/null +++ b/components/module/rtconfig.py @@ -0,0 +1,83 @@ +import SCons.cpp + +# component options + +# toolchains options +ARCH = 'arm' +CPU = 's3c24x0' +TextBase = '0x30000000' + +CROSS_TOOL = 'gcc' + +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = 'E:/Program Files/CodeSourcery/Sourcery G++ Lite/bin' +elif CROSS_TOOL == 'keil': + PLATFORM = 'armcc' + EXEC_PATH = 'E:/Keil' +BUILD = 'debug' + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'axf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -mcpu=arm920t' + CFLAGS = DEVICE + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp' + ' -DTEXT_BASE=' + TextBase + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread_mini2440.map,-cref,-u,_start -T mini2440_ram.ld' + ' -Ttext ' + TextBase + + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O2' + + POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' + +elif PLATFORM == 'armcc': + # toolchains + CC = 'armcc' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --device DARMSS9' + CFLAGS = DEVICE + ' --apcs=interwork --diag_suppress=870' + AFLAGS = DEVICE + LFLAGS = DEVICE + ' --strict --info sizes --info totals --info unused --info veneers --list rtthread-mini2440.map --ro-base 0x30000000 --entry Entry_Point --first Entry_Point' + + CFLAGS += ' -I"' + EXEC_PATH + '/ARM/RV31/INC"' + LFLAGS += ' --libpath "' + EXEC_PATH + '/ARM/RV31/LIB"' + ' --keep __RTMsym_*' + + EXEC_PATH += '/arm/bin40/' + + if BUILD == 'debug': + CFLAGS += ' -g -O0' + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + +elif PLATFORM == 'iar': + # toolchains + CC = 'armcc' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + + CFLAGS = '' + AFLAGS = '' + LFLAGS = '' diff --git a/components/module/tetris/SConscript b/components/module/tetris/SConscript new file mode 100644 index 0000000000..8f7844e7db --- /dev/null +++ b/components/module/tetris/SConscript @@ -0,0 +1,42 @@ +Import('env') +Import('projects') +Import('RTT_ROOT') +Import('rtconfig') +Import('TARGET') + +RTMLINKER = RTT_ROOT + '/tools/rtmlinker.exe ' + +# group definitions +group = {} +group['CCFLAGS'] = '' +group['CPPPATH'] = [RTT_ROOT + '/include', + RTT_ROOT + '/components/module', + RTT_ROOT + '/components/rtgui/include', + RTT_ROOT + '/components/rgtui/common', + RTT_ROOT + '/components/rtgui/server', + RTT_ROOT + '/components/rtgui/widgets'] +group['CPPDEFINES'] = '' + +target = 'tetris.so' +POST_ACTION = RTMLINKER + ' -D 1 -l ' + TARGET + ' -o tetris.mo ' + '$TARGET' + +# add group to project list +projects.append(group) + +src_local = Split(""" +application.c +tetris_ui.c +tetris_modal.c +tetris_view.c +""") + +env.Append(CCFLAGS = group['CCFLAGS']) +env.Append(CPPPATH = group['CPPPATH']) +env.Append(CPPDEFINES = group['CPPDEFINES']) +module_env = env.Clone(CPPDEFINE = 'RT_MODULE') +module_env = env.Clone(CCFLAGS = ' -mcpu=arm920t -O0 -fPIC') +module_env.Replace(LINK = 'arm-none-eabi-ld') +module_env.Replace(LINKFLAGS = '-z max-page-size=0x4 -shared -fPIC -e rt_application_init -nostdlib -s') +module_env.Program(target, src_local) +module_env.AddPostAction(target, POST_ACTION) + diff --git a/components/module/tetris/application.c b/components/module/tetris/application.c new file mode 100644 index 0000000000..9239e3d19b --- /dev/null +++ b/components/module/tetris/application.c @@ -0,0 +1,45 @@ +/* + * 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 + */ + +/** + * @addtogroup LM3S + */ +/*@{*/ + +#include +#include +#include +#include +#include + +extern void tetris_ui_entry(void* parameter); + +int rt_application_init() +{ + rt_thread_t tid; + rtgui_rect_t rect; + + /* ×¢²لأو°ه */ + rect.x1 = 0; + rect.y1 = 0; + rect.x2 = 128; + rect.y2 = 96; + rtgui_panel_register("main", &rect); + rtgui_panel_set_default_focused("main"); + + tid = rt_thread_create("wb", tetris_ui_entry, RT_NULL, 2048, 20, 5); + if (tid != RT_NULL) rt_thread_startup(tid); + return 0; +} +/*@}*/ diff --git a/components/module/tetris/tetris.h b/components/module/tetris/tetris.h new file mode 100644 index 0000000000..4085c8c0c5 --- /dev/null +++ b/components/module/tetris/tetris.h @@ -0,0 +1,59 @@ +/* + * 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); + diff --git a/components/module/tetris/tetris_modal.c b/components/module/tetris/tetris_modal.c new file mode 100644 index 0000000000..2ba462b8d5 --- /dev/null +++ b/components/module/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/components/module/tetris/tetris_ui.c b/components/module/tetris/tetris_ui.c new file mode 100644 index 0000000000..06eada7a43 --- /dev/null +++ b/components/module/tetris/tetris_ui.c @@ -0,0 +1,178 @@ +/* + * 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_view* info_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 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) + { + rt_kprintf("GAME OVER\n"); + rtgui_timer_stop(g_app_info._timer); + rt_tetris_pause(g_app_info.tetris); + } + } + } + } + + 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) + { + rt_kprintf("GAME OVER\n"); + rtgui_timer_stop(g_app_info._timer); + rt_tetris_destory(g_app_info.tetris); + rt_tetris_view_destroy(g_app_info.tetris_view); + } +} + +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; + + rt_kprintf("tetris_ui_entry\n"); + + 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) 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)) = 10; + + 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_thread_deregister(rt_thread_self()); + rt_mq_delete(mq); +} + diff --git a/components/module/tetris/tetris_view.c b/components/module/tetris/tetris_view.c new file mode 100644 index 0000000000..9b409ce5bc --- /dev/null +++ b/components/module/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_WIDGET_BACKGROUND(widget) = 10; + 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_WIDGET_BACKGROUND(widget) = 3; + 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_WIDGET_BACKGROUND(widget) = 10; + rtgui_dc_fill_rect(dc, &rect); + rt_sprintf(text, "%d", rt_tetris_level(tetris)); + RTGUI_WIDGET_BACKGROUND(widget) = 3; + 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_WIDGET_BACKGROUND(widget) = 10; + rtgui_dc_fill_rect(dc, &rect); + rt_sprintf(text, "%d", rt_tetris_lines(tetris)); + RTGUI_WIDGET_BACKGROUND(widget) = 3; + rtgui_dc_draw_text(dc, text, &rect); + + rect.y1 += 22; + rect.y2 = rect.y1 + 10; + RTGUI_WIDGET_BACKGROUND(widget) = 10; + rtgui_dc_fill_rect(dc, &rect); + rt_sprintf(text, "%d", rt_tetris_score(tetris)); + RTGUI_WIDGET_BACKGROUND(widget) = 3; + 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