stm32贪吃蛇tftlcd显示实验
最近又在学习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显示实验相关推荐
- 基于正点原子stm32的mini板的TFTLCD显示实验
本章将讲述TFTLCD显示实验,小白总结,如有错误,请大神指教. 一.TFTLCD 简介 1.TFT-LCD 即薄膜晶体管液晶显示器.TFT-LCD具有:亮度好.对比度高.层次感强.颜色鲜艳等特点.是 ...
- STM32贪吃蛇实现
一. 前言 最近在弄一个桌面小摆件的DIY,在里面弄了一个贪吃蛇的小游戏,在stm32f103平台上实现,通过tft模块进行显示.不加显示部分的话,贪吃蛇游戏与平台无关,可以轻松添加到自己其他平台项目 ...
- 软件实习项目2——贪吃喵(猫吃鱼版贪吃蛇)(实验准备与设计)
软件实习项目2--贪吃喵(猫吃鱼版贪吃蛇)(实验准备与设计) 实验内容 编程语言以及开发环境的选择 实验思路(游戏设计) 一.游戏的逻辑设计 1.猫头的生成 2.鱼的生成 3.猫头和鱼骨的移动 4.按 ...
- c语言设计贪吃蛇实验报告,贪吃蛇游戏程序设计实验报告
<贪吃蛇游戏程序设计实验报告>由会员分享,可在线阅读,更多相关<贪吃蛇游戏程序设计实验报告(11页珍藏版)>请在人人文库网上搜索. 1.Windows编程大作业贪吃蛇设计与实现 ...
- STM32F103 TFTLCD显示实验(一)
文章内容 本文将介绍有关TFTLCD的有关知识,包括几个部分,分别如下: TFTLCD简介 相关指令 配置步骤 FSMC简介 由于篇幅过长,因此,代码讲解放到下一章中,链接如下: STM32F103 ...
- STM32贪吃蛇(流畅,高移植性)
目录 一.一些前言: 二.完整代码 2.2.snake.c 2.3.中断处理 2.4.startup 三.后言 一.一些前言: 自己用2.4寸TFTSPI的屏写了个贪吃蛇,蛇行走画面流畅,不会有一顿一 ...
- 贪吃蛇——汇编综合性实验(含实验报告+源码)
贪吃蛇--汇编综合性实验 完整的实验报告和源码见贪吃蛇--汇编综合性实验(含实验报告+源码) 实现效果 实验原理分析 (1)程序总体设计 贪吃蛇游戏我们并不陌生,简单来说就是一条小蛇通过吃在地图上随机 ...
- STM32单片机TFTLCD显示实验:TFTLCD简介
STM32单片机TFTLCD显示实验学习笔记 1.TFTLCD模块接口图 以2.8寸的TFTLCD为例,采用16位的并方式与外界进行连接,模块接口图如下所示: 具有如下一些信号线: CS:TFTLCD ...
- stm32贪吃蛇代码c语言,STM32实现贪吃蛇
本帖最后由 akwkevin2011 于 2012-7-14 14:47 编辑 STM32学习笔记二 竹天笑 呵呵,界面非常简单 要点:1.触摸屏校准信息保存在SD卡,不必每次开机都校准.(读写S ...
最新文章
- 为什么多 TCP 连接比单 TCP 连接传输快
- kthread_work和kthread_worker机制
- [译]怎样用HTML5 Canvas制作一个简单的游戏
- 计算机应用基础二00018,2019年10月自学考试00018《计算机应用基础》试题(二)
- uniapptabbar的高度是多少_【报Bug】uniapp页面底部空出了tabBar的高度
- JavaScript 之call , apply 和prototype 介绍
- centos php 5.2,CentOS服务器单独升级 php5.1 到 5.2版本
- AI 假冒老板骗取 173 万!
- JVM面试重点总结(一)——java内存区域与内存溢出异常
- 我的 WinClock 项目系列之一 (概述)
- HTML5 css3 阴影效果
- ctfmon是什么启动项_win7系统启动项中没有ctfmon进程的解决方法
- HTML做成信纸格式,css实现一个写信的格式_html/css_WEB-ITnose
- 使用Blynk打造一款物联网产品
- IO流---Reader和Writer
- 根据旋转矩阵计算角度差
- 服务器隐藏文件夹怎样打开,局域网文件如何设置隐藏?服务器隐藏文件夹的方法...
- 查找最小的k 个元素
- 《浪潮之颠》学习笔记
- word添加水印后多出一条线的删除方法