米多0036 发表于 2023-2-23 16:11

开始函数
通过begin()函数和first()函数实现。方块的实际绘制是begin()函数完成的,此外该函数定义了方块的初始刷新位置并且对方块是否触顶进行判断以提示游戏结束。first()函数以负责清空上一次数组保存的状态和基本UI的绘制,由于我们设置的边界,UI部分在游戏过程中不会受到刷新影响,故只需要绘制一次。
void begin()//绘制方块,开始游戏
{
        Del_tuxing1(150,25,suijishu);
        Del_tuxing1(150,50,suijishu);
        Del_tuxing1(150,75,suijishu);
       
        what=suijishu;//
        suijishu=suijishu;
        suijishu=suijishu;
        suijishu=suijishu;
        suijishu=suijishu;
        suijishu=rand()%19+1;
       
        Draw_tuxing1(150,25,suijishu);
        Draw_tuxing1(150,50,suijishu);
        Draw_tuxing1(150,75,suijishu);
       
        x=60,y=0;
       
        Draw(60,0,what);
        if(panduan(x,y,what,2))
        {
                game_over();
        }
}

米多0036 发表于 2023-2-23 16:11

void first()
{
        uint8 i,n;
        fengshu=0;
        leave=1;
        speed=80;
        lcd_clear(WHITE);//WHITE清除欢迎界面
   Gui_DrawLine(150 ,0,150,160,BLACK);//BLACK
        //清空状态
        for(i=0;i<A;i++)
        {
                for(n=1;n<B;n++)
                {
                        zhuangtai=0;
                }
        }
}

米多0036 发表于 2023-2-23 16:11

主程序
int main(void)
{
        lcd_init();
        Key_Init();
        NVIC_Init(NVIC_PriorityGroup_2);
        TIM3_Init(20,36000-1);
        lcd_clear(WHITE);
        welcome();
        systick_delay_ms(10);
        suijishu=rand()%19+1;
        suijishu=rand()%19+1;
        suijishu=rand()%19+1;
        suijishu=rand()%19+1;
        suijishu=rand()%19+1;
                /*
                #define KEY_UP 1
                #define KEY_DOWN 2
                #define KEY_LEFT 3
                #define KEY_RIGHT 4
                #define KEY_MID 5*/
        while(1)
        {
                switch(Key_Scan())
                {
                        case 0:
                                break;
                        //功能区
                        case 1:
                                if(game==1){
                                        game=2;
                                        first();
                                        begin();
                                }
                                else if(game==2){
                                        game=4;
                                        stop();
                                }
                                else if(game==4){
                                        game=2;
                                        star();
                                        }
                                else if(game==3){
                                        game=1;
                                }
                                break;
                       
                        case 2:
                                if(game!=2)
                                        break;
                                if(!panduan(x,y,what,2)){//方向判断
                                        Down(x,y,what);
                                        y=y+10;
                                        }else{       
                                                xiaochu();
                                                begin();
                                                } break;
                        case 3:
                                if(game!=2)
                                        break;
                                if(!panduan(x,y,what,1)){
                                        Left(x,y,what);x=x-10;
                                        }break;
                        case 4:
                                if(game!=2)
                                        break;
                                if(!panduan(x,y,what,3)){
                                        Right(x,y,what);x=x+10;
                                        }break;
                        case 5:
                                if(game!=2)
                                        break;
                                if(!panduan(x,y,what,4))
                                        change();
                                        break;
                 
                }
//方块下落               
                if(game==2)
                {
                if(i>speed)
                {
                        i=0;
               
                if(panduan(x,y,what,2))//若判断碰撞且满足消除条件,返回值并调用消除函数
                        {
                                xiaochu();
                                begin();                                                       
                  }
                        else
                        {
                                Down(x,y,what);                //否则匀速下移       
                                y=y+10;               
                        }
                }
                       
}
        }
}               

米多0036 发表于 2023-2-23 16:12

定时器及中断服务函数
这个地方搞了很久,因为之前只接触过51的定时器,stm32的定时器只在教学视频中看见过,从来都没有进行过实操。这里选取TIM3定时器就可以完成。定时器真的曲折,光是里面定时器的调用函数和结构体就找了半天。

定时器3的初始化函数
void TIM3_Init(u16 per,u16 psc)
{
        exNVIC_Init_TypeDef NVIC_InitStructure;
        TIM_TimeBaseInitTypeDef TimeBaseInitStrue;
        //TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
        //TIM_DeInit(TIM3);
        TimeBaseInitStrue.TIM_Period=per;
        TimeBaseInitStrue.TIM_Prescaler=psc;
        TimeBaseInitStrue.TIM_CounterMode=TIM_CounterMode_Up;
        TimeBaseInitStrue.TIM_ClockDivision=TIM_CKD_DIV1;
       
        TIM_TimeBaseInit(TIM3, &TimeBaseInitStrue);
        TIM_ITConfig(TIM3,TIM_EventSource_Update, ENABLE);
        NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;               
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;       
        NVIC_Init(&NVIC_InitStructure);       
       
        TIM_Cmd(TIM3, ENABLE);
}

米多0036 发表于 2023-2-23 16:12

中断服务函数,这里也有些奇怪,MM32和stm32的例程不太一样。
void TIM3_IRQHandler (void) //中断服务函数
{
        uint32 state = TIM3->SR;                                                                                                        // 读取中断状态
        i++;   
        TIM3->SR &= ~state;                                                                                                                                // 清空中断状态
}

米多0036 发表于 2023-2-23 16:12

上面的代码俄罗斯方块累满了一行之后消去会神奇的产生问题,我调了一晚上和一下午都解决不了,可能游戏逻辑理解的不是特别深刻,在很多遍历数组的时候i的界限被我修改乱了,导致数组的一行不能完全遍历,而且有时候还会出现同时消掉两行,和方块掉到越界区域的问题。

七毛钱 发表于 2023-3-3 11:14

俄罗斯方块游戏开发应该已经很成熟了吧

tpgf 发表于 2023-3-3 11:42

做这种俄罗斯方块的游戏 需要随机数的应用吗

qcliu 发表于 2023-3-3 11:55

做出来的效果如何 会不会屏幕闪烁啊

drer 发表于 2023-3-3 12:08

画画的函数 可以做成活的吗 就是自适应的那种

coshi 发表于 2023-3-3 12:16

楼主按键扫描功能是如何做防抖的呢?

kxsi 发表于 2023-3-3 13:11

楼主使用的是触摸屏还是普通屏幕呀

wiba 发表于 2023-3-3 13:22

楼主的这个代码好像很灵活 应该是自动计算的吧
页: 1 [2]
查看完整版本: MM32SPIN27PS实现俄罗斯方块游戏