add tetris module
git-svn-id: https://rt-thread.googlecode.com/svn/trunk@904 bbd45198-f89e-11dd-88c7-29a3b14d5316
This commit is contained in:
parent
322b7d21db
commit
e78285e76f
|
@ -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)
|
||||
|
|
@ -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
|
|
@ -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 = ''
|
|
@ -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)
|
||||
|
|
@ -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 <rtthread.h>
|
||||
#include <rtgui/rtgui.h>
|
||||
#include <rtgui/rtgui_server.h>
|
||||
#include <rtgui/rtgui_system.h>
|
||||
#include <rtgui/widgets/workbench.h>
|
||||
|
||||
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;
|
||||
}
|
||||
/*@}*/
|
|
@ -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 <rtthread.h>
|
||||
|
||||
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);
|
||||
|
|
@ -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 <rtthread.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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<<x);
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t rt_tetris_delete_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<<x);
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t rt_tetris_is_reach_top(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++)
|
||||
{
|
||||
if(brick[i] / thiz->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;
|
||||
}
|
||||
}
|
|
@ -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 <rtgui/rtgui.h>
|
||||
#include <rtgui/rtgui_system.h>
|
||||
#include <rtgui/widgets/view.h>
|
||||
#include <rtgui/widgets/label.h>
|
||||
#include <rtgui/widgets/button.h>
|
||||
#include <rtgui/widgets/window.h>
|
||||
#include <rtgui/widgets/workbench.h>
|
||||
#include <rtgui/dc.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
|
@ -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 <rtthread.h>
|
||||
#include <rtgui/rtgui.h>
|
||||
#include <rtgui/rtgui_system.h>
|
||||
#include <rtgui/widgets/view.h>
|
||||
#include <rtgui/dc.h>
|
||||
|
||||
#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<width; j++)
|
||||
{
|
||||
for(k=1; k<height; k++)
|
||||
{
|
||||
rect.x1 = ppb * j;
|
||||
rect.x2 = ppb * (j + 1) - 1;
|
||||
rect.y1 = ppb * (k - 1);
|
||||
rect.y2 = ppb * k - 1;
|
||||
|
||||
if(rt_tetris_check_collision(tetris, k * width + j))
|
||||
{
|
||||
RTGUI_WIDGET_BACKGROUND(widget) = 13;
|
||||
}
|
||||
else
|
||||
{
|
||||
RTGUI_WIDGET_BACKGROUND(widget) = 3;
|
||||
}
|
||||
|
||||
rtgui_dc_fill_rect(dc, &rect);
|
||||
}
|
||||
}
|
||||
|
||||
/* Redraw panel */
|
||||
rtgui_dc_end_drawing(dc);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
Loading…
Reference in New Issue