最近又在学习LCD,以前也看过一点LCD,但看lcd.c源文件2000多行,说来也惭愧,当时就放弃了,就想先学其他的吧,但是后来发现不学不行呀,LCD太重要了,LCD是输出设配,好多实验都是要显示出来才能看到效果的,哎没办法,后来只好硬着头皮去看啦,咦,我发现好像好多事可以不需要的,厂家为了能兼容更多的LCD,把很多液晶控制芯片都写了进去,由于我用到LCD的控制芯片是ILI9331,我就把其他无用的都删掉了,最后只有六七百行了,哈哈哈,好开心啊,看着心情都好些。熟悉了一些基本函数之后,我想可不可以写一个贪吃蛇的小游戏,说着容易做起来可就没那么简单了,从早到晚做了一整天,才勉强算一个贪吃蛇小游戏,还是有很多的小BUG,希望大家不吝指正。闲话少说,下面直接看游戏。

首先游戏中的点要是随机的,所以要先产生一些随机的数,在C语言中有函数srand和rand()配合使用产生伪随机数序列。rand函数在产生随机数前,需要系统提供的生成伪随机数序列的种子,rand根据这个种子的值产生一系列随机数。如果系统提供的种子没有变化,每次调用rand函数生成的伪随机数序列都是一样的,只要用一直变化的数做种子就能能实现真正的随机,通常可以利用系统时间来改变系统的种子值,我看好多博客是这样写的,srand(time(0)),我试了发现不行,LCD都不显示了,后来我发现可以用STM32 的实时时钟(RTC)来获取系统时间,首先初始化RTC,然后就可以产生真的随机数。

srand(RTC_GetCounter());
food.x=rand()%28+1;
food.y=rand()%33+1; 

接下来是snake.h文件里面定义了一个蛇的结构体,还有一个事物的结构体,方便操作。

#ifndef __SNAKE_H
#define __SNAKE_H
#include "stm32f10x.h"
#define MAX_Longth    100 //定义蛇的最大长度
#define straight  0
#define left   1
#define right  2
#define down   3//定义一个蛇的结构体
typedef struct
{u16 XPos[MAX_Longth]; u16 YPos[MAX_Longth];u8 longth;   u8 score;u8 islive;   //判断蛇是否或者
}Snake;//定义一个食物的结构体
typedef struct
{u16 x;u16 y;u8 flag;  //标志位是否要产生食物标志位
}Food;void Trun_On_Point (u16 x,u16 y);
void Trun_Off_Point (u16 x,u16 y);
void Snake_Run(u8 dir) ;
void Snake_Init(void) ;
void Is_Snake_Dead(void);
void Display_Dead(void);
void Eat_Food(void);
u8 Is_Alive(Snake snake);
#endif

接下来是snake.c文件

#include "stm32f10x.h"
#include "lcd.h"
#include "snake.h"
#include "stdlib.h"
#include "time.h"Snake  snake;
Food  food;//画一个蛇的最小单位
void Trun_On_Point (u16 x,u16 y)
{LCD_Fill(x*8, y*8, x*8+8, y*8+8, RED);
}//擦去一个蛇的最小单位
void Trun_Off_Point (u16 x,u16 y)
{LCD_Fill(x*8, y*8, x*8+8, y*8+8, WHITE);
}//蛇初始化函数
void Snake_Init(void)
{u8 i;snake.longth = 3;                    //初始化长度为3 snake.islive = 1;                    //蛇是活着的snake.score = 0;                   //当前的分为0food.flag = 1;                      //for(i = 0; i < snake.longth; i++) {snake.XPos[i] = 14 + i;snake.YPos[i] = 17;}for(i = 0; i < snake.longth ; i++){Trun_On_Point(snake.XPos[i], snake.YPos[i]);}
}//显示游戏结束界面
void Display_Dead()
{snake.islive = 0;LCD_Clear(BLACK);LCD_Fill(0,0,8,280,DARKBLUE);LCD_Fill(232,0,240,280,DARKBLUE);LCD_Fill(0,0,240,8,DARKBLUE);LCD_Fill(0,272,240,280,DARKBLUE);LCD_ShowString(60,100,240,24,24,"GAME OVER! "); LCD_ShowString(70,140,240,24,24,"score: ");LCD_ShowNum (145,140,snake.score,3,24);while(1){}
}   //判断蛇是否死亡函数
void Is_Snake_Dead()
{u8 i;if(snake.XPos[snake.longth-1] <= 1 || snake.XPos[snake.longth-1] >= 28 || snake.YPos[snake.longth-1] <= 1 || snake.YPos[snake.longth-1] >= 33  ){snake.islive = 0; //ÉßËÀÍö}if(snake.islive == 0) //Èç¹ûÉßËÀÍöÓÎÏ·½áÊø{Display_Dead();}
}//蛇运动函数
void Snake_Run(u8 dir)
{u8 i;Trun_Off_Point(snake.XPos[0],snake.YPos[0]); //ÏÈϨÃðÉßβif(dir == right){for(i = 0; i < snake.longth - 1 ; i++){snake.XPos[i] = snake.XPos[i+1];snake.YPos[i] = snake.YPos[i+1];}snake.XPos[snake.longth-1] = snake.XPos[snake.longth-2] + 1; //ÉßÍ·Òƶ¯µ½ÏÂһλÖÃsnake.YPos[snake.longth-1] = snake.YPos[snake.longth-2] - 0;}else if(dir == left){for(i = 0; i < snake.longth - 1 ; i++){snake.XPos[i] = snake.XPos[i+1];snake.YPos[i] = snake.YPos[i+1];}snake.XPos[snake.longth-1] = snake.XPos[snake.longth-2] - 1;snake.YPos[snake.longth-1] = snake.YPos[snake.longth-2] + 0;}else if(dir == down){for(i = 0; i < snake.longth - 1 ; i++){snake.XPos[i] = snake.XPos[i+1];snake.YPos[i] = snake.YPos[i+1];}snake.XPos[snake.longth-1] = snake.XPos[snake.longth-2] + 0;snake.YPos[snake.longth-1] = snake.YPos[snake.longth-2] + 1;}else if(dir == straight){for(i = 0; i < snake.longth - 1 ; i++){snake.XPos[i] = snake.XPos[i+1];snake.YPos[i] = snake.YPos[i+1];}snake.XPos[snake.longth-1] = snake.XPos[snake.longth-2] + 0;snake.YPos[snake.longth-1] = snake.YPos[snake.longth-2] - 1;}for(i=0; i<snake.longth; i++)                        //ÈÃÉßÏÔʾ³öÀ´{Trun_On_Point(snake.XPos[i],snake.YPos[i]);}   Is_Snake_Dead();Eat_Food();
}void Eat_Food()
{ u8 length[20]; //用于保存要显示的分数和长度u8 i;/*************************判断蛇是否吃到食物**********************/ if(snake.XPos[snake.longth -1] == food.x && snake.YPos[snake.longth -1] == food.y){snake.longth ++;snake.score += 5;snake.XPos[snake.longth -1] = food.x;snake.YPos[snake.longth -1] = food.y;sprintf((char*)length,"%d  length:%d",snake.score,snake.longth);//将分数长度打印到length数组中LCD_ShowString(75,300,200,12,12,length);//Show Scorefood.flag = 1;}//放食物if(food.flag == 0)  //标志位为0时放置食物{Trun_On_Point (food.x, food.y);}if(food.flag==1)  {srand(RTC_GetCounter());while(1){  food.x=rand()%28+1;                  //产生真随机数food.y=rand()%33+1; for(i=0;i<snake.longth ;i++) //判断产生的食物是否和蛇身重合           {if((food.x==snake.XPos[i]) && (food.y==snake.YPos[i])) break;}if(i==snake.longth)   {food.flag=0;LCD_ShowNum(150,290,food.x,3,12);  LCD_ShowNum(150,300,food.y,3,12);  break;                           }}}
}

控制蛇运动方向,我使用了按键,外部中断的方式来控制,当按下按键,产生外部中断,执行中断服务函数,改变方向。下面是exti.c函数

#include "stm32f10x.h"
#include "exti.h"
#include "lcd.h"
#include "delay.h"
extern u8 dir;
void KEY_GPIO_Config()
{GPIO_InitTypeDef  GPIO_Initstructure;RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA, ENABLE );GPIO_Initstructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;GPIO_Initstructure.GPIO_Mode  = GPIO_Mode_IPU;GPIO_Init(GPIOA, &GPIO_Initstructure);
}static void KEY_NVIC_Config()
{NVIC_InitTypeDef    NVIC_InitStructure;NVIC_PriorityGroupConfig (NVIC_PriorityGroup_1);//配置中断源 按键 1 NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn ;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE ;NVIC_Init(&NVIC_InitStructure);//配置中断源 按键 2NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn ;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =2;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE ;NVIC_Init(&NVIC_InitStructure);//配置中断源 按键 3NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn ;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE ;NVIC_Init(&NVIC_InitStructure);//配置中断源 按键 4NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn ;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE ;NVIC_Init(&NVIC_InitStructure);
}//EXTI中都配置
void EXTI_Key_Config()
{EXTI_InitTypeDef   EXTI_InitStructure;//按键配置KEY_GPIO_Config();//打开AFIO 复用时钟RCC_APB2PeriphClockCmd (RCC_APB2Periph_AFIO, ENABLE );//配置NVIC中断KEY_NVIC_Config();//选择EXTI信号源GPIO_EXTILineConfig (GPIO_PortSourceGPIOA, GPIO_PinSource0|GPIO_PinSource1|GPIO_PinSource2|GPIO_PinSource3);//中断线 0EXTI_InitStructure.EXTI_Line = EXTI_Line0;//中断模式EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//触发类型 下降沿EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//使能中断EXTI_InitStructure.EXTI_LineCmd = ENABLE ;EXTI_Init(&EXTI_InitStructure);//中断线 1EXTI_InitStructure.EXTI_Line = EXTI_Line1;EXTI_Init(&EXTI_InitStructure);//中断线 2EXTI_InitStructure.EXTI_Line = EXTI_Line2;EXTI_Init(&EXTI_InitStructure);//中断线 3EXTI_InitStructure.EXTI_Line = EXTI_Line3;EXTI_Init(&EXTI_InitStructure);
}void EXTI0_IRQHandler(void)
{//È·ÈÏÊÇ·ñ²úÉúEXTI LINE ÖжÏif(EXTI_GetITStatus(EXTI_Line0) != RESET ){dir = 0;//LCD_ShowNum(180,290,dir,3,12); LCD_ShowString(190,290,200,12,12,"straight"); //显示当前蛇的运动方向EXTI_ClearITPendingBit(EXTI_Line0);}
}void EXTI1_IRQHandler(void)
{//È·ÈÏÊÇ·ñ²úÉúEXTI LINE ÖжÏif(EXTI_GetITStatus(EXTI_Line1) != RESET ){dir = 1;LCD_ShowString(190,290,200,12,12,"left    "); //显示当前蛇的运动方向EXTI_ClearITPendingBit(EXTI_Line1);}
}
void EXTI2_IRQHandler(void)
{//È·ÈÏÊÇ·ñ²úÉúEXTI LINE ÖжÏif(EXTI_GetITStatus(EXTI_Line2) != RESET ){dir = 2;LCD_ShowString(190,290,200,12,12,"right      ");  //ÏÔʾµ±Ç°ÉßµÄÇ°½ø·½ÏòEXTI_ClearITPendingBit(EXTI_Line2);}
}void EXTI3_IRQHandler(void)
{//È·ÈÏÊÇ·ñ²úÉúEXTI LINE ÖжÏif(EXTI_GetITStatus(EXTI_Line3) != RESET ){dir = 3;LCD_ShowString(190,290,200,12,12,"    down");  //显示当前蛇的运动方向EXTI_ClearITPendingBit(EXTI_Line3);}
}

接下来是主函数

int main(void){  POINT_COLOR=BLUE;  //画笔颜色RTC_Init();Snake_Init();EXTI_Key_Config();LCD_Init();LCD_Fill(0,0,8,280,YELLOW);//Rectangle(8,8-1,85,120,0xaa);//绘制界面LCD_Fill(232,0,240,280,YELLOW);//LCD_Fill(0,0,240,8,YELLOW);//LCD_Fill(0,272,240,280,YELLOW);//LCD_ShowString(0,290,200,24,24,"Score:");//Show ScoreLCD_ShowString(75,300,200,12,12,"0  length:3");//Show Scorewhile(1)  {  Snake_Run(dir);delay_ms(200);}
}

下面是程序运行的图片。

源码文件源码文件

stm32贪吃蛇tftlcd显示实验相关推荐

  1. 基于正点原子stm32的mini板的TFTLCD显示实验

    本章将讲述TFTLCD显示实验,小白总结,如有错误,请大神指教. 一.TFTLCD 简介 1.TFT-LCD 即薄膜晶体管液晶显示器.TFT-LCD具有:亮度好.对比度高.层次感强.颜色鲜艳等特点.是 ...

  2. STM32贪吃蛇实现

    一. 前言 最近在弄一个桌面小摆件的DIY,在里面弄了一个贪吃蛇的小游戏,在stm32f103平台上实现,通过tft模块进行显示.不加显示部分的话,贪吃蛇游戏与平台无关,可以轻松添加到自己其他平台项目 ...

  3. 软件实习项目2——贪吃喵(猫吃鱼版贪吃蛇)(实验准备与设计)

    软件实习项目2--贪吃喵(猫吃鱼版贪吃蛇)(实验准备与设计) 实验内容 编程语言以及开发环境的选择 实验思路(游戏设计) 一.游戏的逻辑设计 1.猫头的生成 2.鱼的生成 3.猫头和鱼骨的移动 4.按 ...

  4. c语言设计贪吃蛇实验报告,贪吃蛇游戏程序设计实验报告

    <贪吃蛇游戏程序设计实验报告>由会员分享,可在线阅读,更多相关<贪吃蛇游戏程序设计实验报告(11页珍藏版)>请在人人文库网上搜索. 1.Windows编程大作业贪吃蛇设计与实现 ...

  5. STM32F103 TFTLCD显示实验(一)

    文章内容 本文将介绍有关TFTLCD的有关知识,包括几个部分,分别如下: TFTLCD简介 相关指令 配置步骤 FSMC简介 由于篇幅过长,因此,代码讲解放到下一章中,链接如下: STM32F103 ...

  6. STM32贪吃蛇(流畅,高移植性)

    目录 一.一些前言: 二.完整代码 2.2.snake.c 2.3.中断处理 2.4.startup 三.后言 一.一些前言: 自己用2.4寸TFTSPI的屏写了个贪吃蛇,蛇行走画面流畅,不会有一顿一 ...

  7. 贪吃蛇——汇编综合性实验(含实验报告+源码)

    贪吃蛇--汇编综合性实验 完整的实验报告和源码见贪吃蛇--汇编综合性实验(含实验报告+源码) 实现效果 实验原理分析 (1)程序总体设计 贪吃蛇游戏我们并不陌生,简单来说就是一条小蛇通过吃在地图上随机 ...

  8. STM32单片机TFTLCD显示实验:TFTLCD简介

    STM32单片机TFTLCD显示实验学习笔记 1.TFTLCD模块接口图 以2.8寸的TFTLCD为例,采用16位的并方式与外界进行连接,模块接口图如下所示: 具有如下一些信号线: CS:TFTLCD ...

  9. stm32贪吃蛇代码c语言,STM32实现贪吃蛇

    本帖最后由 akwkevin2011 于 2012-7-14 14:47 编辑 STM32学习笔记二   竹天笑 呵呵,界面非常简单 要点:1.触摸屏校准信息保存在SD卡,不必每次开机都校准.(读写S ...

最新文章

  1. 为什么多 TCP 连接比单 TCP 连接传输快
  2. kthread_work和kthread_worker机制
  3. [译]怎样用HTML5 Canvas制作一个简单的游戏
  4. 计算机应用基础二00018,2019年10月自学考试00018《计算机应用基础》试题(二)
  5. uniapptabbar的高度是多少_【报Bug】uniapp页面底部空出了tabBar的高度
  6. JavaScript 之call , apply 和prototype 介绍
  7. centos php 5.2,CentOS服务器单独升级 php5.1 到 5.2版本
  8. AI 假冒老板骗取 173 万!
  9. JVM面试重点总结(一)——java内存区域与内存溢出异常
  10. 我的 WinClock 项目系列之一 (概述)
  11. HTML5 css3 阴影效果
  12. ctfmon是什么启动项_win7系统启动项中没有ctfmon进程的解决方法
  13. HTML做成信纸格式,css实现一个写信的格式_html/css_WEB-ITnose
  14. 使用Blynk打造一款物联网产品
  15. IO流---Reader和Writer
  16. 根据旋转矩阵计算角度差
  17. 服务器隐藏文件夹怎样打开,局域网文件如何设置隐藏?服务器隐藏文件夹的方法...
  18. 查找最小的k 个元素
  19. 《浪潮之颠》学习笔记
  20. word添加水印后多出一条线的删除方法

热门文章

  1. DCG, NDCG 公式及其实现
  2. stacking 的代码实现
  3. html5中preload是什么意思,html的video标签的preload属性详解
  4. Android Studio的ADV无法启动解决办法
  5. 大二数据结构实验(迪杰斯特拉最短路径)
  6. 记一次微信小程序从原生到Taro的迁移
  7. Android 源码编译
  8. JavaWeb(三)jQuery
  9. wireshark 解密加密报文
  10. 用C语言设计一个订房程序,酒店预定程序的设计.doc