STM32学习笔记二十一:WS2812制作像素游戏屏-飞行射击游戏(11)探索游戏脚本

 还记得上次在第十七章中为BOSS创建的路径动画吧。我们写了一大坨的代码来描述BOSS的运动路径,但凡是写过几年代码的人都不会干出这样的事情。-_-!

没办法,谁叫那时候还没有脚本呢。这章就来补齐这块短板。

脚本属于配置化的一种,你可以把脚本当成配置文件来看待。要做脚本,优先要确定脚本的格式。常用的格式有:

1、二进制格式。优势是最节约空间,非常适合单片机这种嵌入式设备。劣势是无法直接阅读,不需要另外写个编解码工具来生成配置文件。

2、文本行格式。优势是可阅读,空间也可接受。劣势是修改容易出错,尽量不要有对齐要求,否则用起来可能要崩溃。

3、JSON或XML。优势是方便阅读方便编辑,不需要专用工具。劣势是需要空间较大。

本项目中,采用2+3方式,即按行保存压缩的JSON串。

脚本主要起两个作用,一是描述物体运动的轨迹,如前面BOSS的运动动画。另一个是制作关卡剧本。

先来搞第一个:

1、现有弄个JSON解析工具。以前做MQTT时用过一个:《【嵌入式项目应用】__cJSON在单片机的使用》

下载cJSON.h 和cJSON.c,并放到项目中。

 2、统一所有敌机的TICK,先尝试有没有故事板可以运行。如果故事板运行结束,则按原有固定向下运行。

uint8_t EnemyT1::tick(uint32_t t) {if (animationStoryBoard->isValid) {animationStoryBoard->tick(t);} else {if (explodeState == 0)baseInfo.y += t * baseInfo.speedY;if (baseInfo.y > 64 * PlaneXYScale)baseInfo.visiable = 0;}if (fireTimer.tick(t))createBulletObject();for (ListNode *node = animationList->next; node != animationList; node =node->next) {if (((Animation*) node->data)->isValid) {((Animation*) node->data)->tick(t);}}return 0;
}

3、把原来BOSS的运行路径转为JSON串:

[{"r": 1,"i": [{				"c": 0,						"x": 200000,				"y": 0			},{				"c": 2000,				"x": 200000,				"y": 100000			}]},{"r": 2,"i": [{				"c": 0,						"x": 200000,				"y": 100000		},{				"c": 3772,				"x": 120000,				"y": 150000		},{				"c": 5772,				"x":  70000,				"y": 150000		},{				"c": 6904,				"x":  50000,				"y": 160000		},{				"c": 7304,				"x":  50000,				"y": 140000		},{				"c": 8436,				"x":  70000,				"y": 100000		},{				"c": 10436,				"x": 120000,				"y": 100000		},{				"c": 14208,				"x": 200000,				"y": 150000		},{				"c": 16208,				"x": 250000,				"y": 150000		},{				"c": 17340,				"x": 270000,				"y": 160000		},{				"c": 17740,				"x": 270000,				"y": 140000		},{				"c": 18872,				"x": 250000,				"y": 100000		},{				"c": 20872,				"x": 200000,				"y": 100000		}]}
]

r 为 group的重复次数

c为时间点

x,y为坐标值。应提前 * PlaneXYScale

4、对JSON进行压缩转义,然后用字符串来保存。

/** PlaneScript.h**  Created on: Dec 28, 2023*      Author: YoungMay*/#ifndef SRC_PLANE_PLANESCRIPT_H_
#define SRC_PLANE_PLANESCRIPT_H_const char *PlaneLevelScript[] ={"[{\"r\":1,\"i\":[{\"c\":0,\"x\":200000,\"y\":0},{\"c\":2000,\"x\":200000,\"y\":100000}]},{\"r\":2,\"i\":[{\"c\":0,\"x\":200000,\"y\":100000},{\"c\":3772,\"x\":120000,\"y\":150000},{\"c\":5772,\"x\":70000,\"y\":150000},{\"c\":6904,\"x\":50000,\"y\":160000},{\"c\":7304,\"x\":50000,\"y\":140000},{\"c\":8436,\"x\":70000,\"y\":100000},{\"c\":10436,\"x\":120000,\"y\":100000},{\"c\":14208,\"x\":200000,\"y\":150000},{\"c\":16208,\"x\":250000,\"y\":150000},{\"c\":17340,\"x\":270000,\"y\":160000},{\"c\":17740,\"x\":270000,\"y\":140000},{\"c\":18872,\"x\":250000,\"y\":100000},{\"c\":20872,\"x\":200000,\"y\":100000}]}]"};#endif /* SRC_PLANE_PLANESCRIPT_H_ */

5、在故事板中添加脚本解析方法。

void AnimationStoryBoard::loadScript(const char *value, int *bindAddX,int *bindAddY) {cJSON *root = cJSON_Parse(value);int gcount = cJSON_GetArraySize(root);for (int i = 0; i < gcount; i++) {cJSON *jGroup = cJSON_GetArrayItem(root, i);AnimationGroup *group = new AnimationGroup();ContinuousAnimation *aniX = new ContinuousAnimation();ContinuousAnimation *aniY = new ContinuousAnimation();aniX->bindAddress = bindAddX;aniY->bindAddress = bindAddY;group->addItem(aniX);group->addItem(aniY);group->repeat = cJSON_GetObjectItem(jGroup, "r")->valueint;cJSON *iGroup = cJSON_GetObjectItem(jGroup, "i");int icount = cJSON_GetArraySize(iGroup);for (int j = 0; j < icount; j++) {cJSON *items = cJSON_GetArrayItem(iGroup, j);int time = cJSON_GetObjectItem(items, "c")->valueint;int x = cJSON_GetObjectItem(items, "x")->valueint;int y = cJSON_GetObjectItem(items, "y")->valueint;aniX->addItem(time, x);aniY->addItem(time, y);}ListPushBack(animationGroupList, (LTDataType) group);}
}

这就ok了。

脚本的另一个作用是制作关卡。

我们通过脚本定义不同时间或者不同位置(滚轴游戏),出现不同的敌人,也可以定义出现一些地形物体,加上碰撞,可以做到类似地图的效果。

我们来试着做个排队行进的小飞机。方式是几个飞机绑定相同的线路,错开相同间隔出现。

1、先定义飞机的飞行线路

对应的JSON:

[{"r": 1,"i": [{				"c": 0,						"x": 200000,				"y": 0			},{				"c": 4000,				"x": 200000,				"y": 400000	},{				"c": 5000,				"x": 100000,				"y": 400000	},{				"c": 7000,				"x": 100000,				"y": 200000	},{				"c": 7500,				"x": 150000,				"y": 200000	},]}
]

再加一个与之对称的。

2、加入数组

/** PlaneScript.h**  Created on: Dec 28, 2023*      Author: YoungMay*/#ifndef SRC_PLANE_PLANESCRIPT_H_
#define SRC_PLANE_PLANESCRIPT_H_static const char *PlaneLevelScript[] ={"[{\"r\":1,\"i\":[{\"c\":0,\"x\":200000,\"y\":0},{\"c\":2000,\"x\":200000,\"y\":100000}]},{\"r\":2,\"i\":[{\"c\":0,\"x\":200000,\"y\":100000},{\"c\":3772,\"x\":120000,\"y\":150000},{\"c\":5772,\"x\":70000,\"y\":150000},{\"c\":6904,\"x\":50000,\"y\":160000},{\"c\":7304,\"x\":50000,\"y\":140000},{\"c\":8436,\"x\":70000,\"y\":100000},{\"c\":10436,\"x\":120000,\"y\":100000},{\"c\":14208,\"x\":200000,\"y\":150000},{\"c\":16208,\"x\":250000,\"y\":150000},{\"c\":17340,\"x\":270000,\"y\":160000},{\"c\":17740,\"x\":270000,\"y\":140000},{\"c\":18872,\"x\":250000,\"y\":100000},{\"c\":20872,\"x\":200000,\"y\":100000}]}]","[{\"r\":1,\"i\":[{\"c\":0,\"x\":210000,\"y\":0},{\"c\":4000,\"x\":210000,\"y\":400000},{\"c\":5000,\"x\":100000,\"y\":400000},{\"c\":7000,\"x\":100000,\"y\":200000},{\"c\":7500,\"x\":160000,\"y\":200000}]}]","[{\"r\":1,\"i\":[{\"c\":0,\"x\":100000,\"y\":0},{\"c\":4000,\"x\":100000,\"y\":400000},{\"c\":5000,\"x\":210000,\"y\":400000},{\"c\":7000,\"x\":210000,\"y\":200000},{\"c\":7500,\"x\":160000,\"y\":200000}]}]",
};#endif /* SRC_PLANE_PLANESCRIPT_H_ */

3、设置关卡剧本,关卡剧本我们换一种方法,不是因为这样更好,仅仅是为了多测试几种方式。如果将来要做更复杂,则应该用文件方式保存在flash里面。

/** PlaneScript.h**  Created on: Dec 28, 2023*      Author: YoungMay*/#ifndef SRC_PLANE_PLANESCRIPT_H_
#define SRC_PLANE_PLANESCRIPT_H_static const char *PlaneLevelScript[] ={"[{\"r\":1,\"i\":[{\"c\":0,\"x\":200000,\"y\":0},{\"c\":2000,\"x\":200000,\"y\":100000}]},{\"r\":2,\"i\":[{\"c\":0,\"x\":200000,\"y\":100000},{\"c\":3772,\"x\":120000,\"y\":150000},{\"c\":5772,\"x\":70000,\"y\":150000},{\"c\":6904,\"x\":50000,\"y\":160000},{\"c\":7304,\"x\":50000,\"y\":140000},{\"c\":8436,\"x\":70000,\"y\":100000},{\"c\":10436,\"x\":120000,\"y\":100000},{\"c\":14208,\"x\":200000,\"y\":150000},{\"c\":16208,\"x\":250000,\"y\":150000},{\"c\":17340,\"x\":270000,\"y\":160000},{\"c\":17740,\"x\":270000,\"y\":140000},{\"c\":18872,\"x\":250000,\"y\":100000},{\"c\":20872,\"x\":200000,\"y\":100000}]}]","[{\"r\":1,\"i\":[{\"c\":0,\"x\":210000,\"y\":0},{\"c\":4000,\"x\":210000,\"y\":400000},{\"c\":5000,\"x\":100000,\"y\":400000},{\"c\":7000,\"x\":100000,\"y\":200000},{\"c\":7500,\"x\":160000,\"y\":200000}]}]","[{\"r\":1,\"i\":[{\"c\":0,\"x\":100000,\"y\":0},{\"c\":4000,\"x\":100000,\"y\":400000},{\"c\":5000,\"x\":210000,\"y\":400000},{\"c\":7000,\"x\":210000,\"y\":200000},{\"c\":7500,\"x\":160000,\"y\":200000}]}]", };typedef struct {uint32_t createTime;uint8_t objType;uint8_t bindScript;
} StageScript_t;#define StageScriptsCount 13
const StageScript_t StageScripts[] = {{1000,		0,		1},{1600,		0,		1},{2200,		0,		1},{2800,		0,		1},{3400,		0,		1},{4000,		0,		1},{11000,		0,		2},{11600,		0,		2},{12200,		0,		2},{12800,		0,		2},{13400,		0,		2},{14000,		0,		2},{20000,		0,		1},};#endif /* SRC_PLANE_PLANESCRIPT_H_ */

4、修改EnemyManager管理类敌机创造的逻辑,加上脚本。

uint8_t EnemyManager::tick(uint32_t t) {if (stageScriptPoint < StageScriptsCount) {stageTime += t;while (stageScriptPoint < StageScriptsCount&& StageScripts[stageScriptPoint].createTime < stageTime) {EnemyBase *enemy = createEnemyObject(StageScripts[stageScriptPoint].objType);enemy->init();enemy->animationStoryBoard->loadScript(PlaneLevelScript[StageScripts[stageScriptPoint].bindScript],&enemy->baseInfo.x, &enemy->baseInfo.y);enemy->animationStoryBoard->start();ListPushBack(enemyList, (LTDataType) enemy);stageScriptPoint++;}} else {if (createTimer.tick(t)) {EnemyBase *enemy = createEnemyObject(ran_seq(2, enemyTypeProportion));enemy->init();ListPushBack(enemyList, (LTDataType) enemy);}if (createBossTimer.tick(t)) {createTimer.defaultSpan -= 100;EnemyBase *enemy = new EnemyT3();enemy->init();enemy->animationStoryBoard->loadScript(PlaneLevelScript[0],&enemy->baseInfo.x, &enemy->baseInfo.y);enemy->animationStoryBoard->start();ListPushBack(enemyList, (LTDataType) enemy);}}for (ListNode *cur = enemyList->next; cur != enemyList; cur = cur->next) {EnemyBase *enemy = ((EnemyBase*) (cur->data));enemy->tick(t);}return 0;
}

TIPS:花点时间设计脚本,就可以做出沙罗曼蛇那样的闯关游戏了。

 看看效果吧

STM32学习笔记二十一:WS2812制作像素游戏屏-飞行射

STM32学习笔记二十二:WS2812制作像素游戏屏-飞行射击游戏(12)总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/616570.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大模型学习与实践笔记(四)

一、大模型开发范式 RAG&#xff08;Retrieval Augmented Generation&#xff09;检索增强生成&#xff0c;即大模型LLM在回答问题或生成文本时&#xff0c;会先从大量的文档中检索出相关信息&#xff0c;然后基于这些检索出的信息进行回答或生成文本&#xff0c;从而可以提高回…

【实用技巧】Steam Wallpaper Engine 壁纸引擎向手机导入壁纸方法

一、内容简介 本文介绍如何使用电脑上的 Wallpaper Engine &#xff08;Steam 平台中的壁纸引擎&#xff09;向安卓手机导入并使用壁纸。 二、所需原材料 安卓手机&#xff08;以笔者使用的华为荣耀50为例&#xff09;、安装有Steam以及Wallpaper Engine的电脑 三、导入方法…

c++最值查找

目录 min和max函数 min_element和max_element 例 nth_element函数 例 例题 题目描述 输入描述 输出描述 解 min和max函数 只能传入两个值或一个列表 时间复杂度为O(1),数组O(n)&#xff0c;n为元素个数 min_element和max_element min_element(st,ed)返回地址[st,…

Rust 最新版1.75.0升级记

升级方法 稳定版 C:\>rustup update stable info: syncing channel updates for stable-x86_64-pc-windows-msvc info: latest update on 2023-12-28, rust version 1.75.0 (82e1608df 2023-12-21) info: downloading component cargo 5.9 MiB / 5.9 MiB (100 %) 3.…

宏集案例丨宏集PC Runtime软件助推食品行业生产线数字化革新

来源&#xff1a;宏集科技 工业物联网 宏集案例丨宏集PC Runtime软件助推食品行业生产线数字化革新 原文链接&#xff1a;https://mp.weixin.qq.com/s/DwzVzifUiidNr-FT3Zfzpg 欢迎关注虹科&#xff0c;为您提供最新资讯&#xff01; 01 前言 近年来&#xff0c;中国食品行业…

html+css实现子元素完全居中常见方案

详细过程 查看公众号文章 htmlcss实现子元素完全居中常见方案 获取更多内容&#xff0c;请关注微信公众号。搜索“码圈小橙子”&#xff0c;或扫描下方二维码获取关注

FFmpeg编程录制音频(Mac OS)

之前我们使用FFmpeg命令行工具进行了简单的音视频操作&#xff0c;这次在Mac OS环境下编写代码实现简单的音频录制功能。 FFmpeg命令行音频录制 首先回顾一下Mac OS环境下简单的音频录制命令行实现&#xff1a; ffmpeg -f avfoundation -i ":0" -t 20 -acodec pcm…

opencv拉流出现missing picture in access unit with size 4错误解决

0、应用场景问题 我们使用opencv作为拉流客户端&#xff0c;获取画面后进行图像处理并推流&#xff08;使用ffmpeg库&#xff09;。 opencv解码同样使用ffmpeg库。 我们要求opencv能根据业务不断进行拉流操作&#xff0c;等效的逻辑代码如下&#xff1a; while(1) {printf(&…

gazebo模型库目录(国内源)

这个是比较普遍的&#xff0c;一般用途&#xff1a; GitCode - 开发者的代码家园https://gitcode.com/geniusChinaHN/osrf.gazebo_models/tree/master/ambulance这个主要是车辆&#xff1a; car_demo: osrf汽车模型库https://gitee.com/geniuschinahn/car_demo还有这个是以前…

YOLOv6s,map值打印成两位小数(原本是显示0.538,变成显示为53.79)

显示结果 更改前&#xff1a; 更改后&#xff1a; 方法 将tools/eval.py中的--do_pr_metric后面改为defaultTrue即可打印出map值原本是显示0.538&#xff0c;变成显示为53.79&#xff0c;方法为&#x1f447; 在YOLOv6-main/yolov6/core/evaler.py中做如下更改&#xff1a…

对回调函数的各种讲解说明

有没有跟我师弟一样的童靴~&#xff0c;学习和使用ROS节点时&#xff0c;对其中的callback函数一直摸不着头脑的&#xff0c;以下这么多回调函数的讲解&#xff0c;挨个看&#xff0c;你总会懂的O.o 回调函数怎么调用,如何定义回调函数&#xff1a; 回调函数怎么调用,如何定义…

最大公共子串

解题思路&#xff1a; 解题代码&#xff1a; UP主运用的方法很巧妙。厉害。

IPv6路由协议----BGP4+

BGP基本概念 边界网关协议BGP(Border Gateway Protocol)是一种实现自治系统AS(Autonomous System)之间的路由可达,并选择最佳路由的距离矢量路由协议。 MP-BGP是对BGP4进行了扩展达到在不同网络中应用的目的,BGP4原有的消息机制和路由机制并没有改变。MP-BGP在IPv6单播网…

day1·算法-双指针

今天是第一天&#xff0c;GUNDOM带你学算法&#xff0c;跟上我的节奏吗&#xff0c;一起闪击蓝桥杯&#xff01; 正文展开&#xff0c;今天先上点小菜供大家想用&#xff0c;如有错误或者建议直接放评论区&#xff0c;我会一个一个仔细查看的哦。 双方指针问题一般是在数组中…

QT 小组件 列表框以及微调框

.cpp文件 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);QListWidgetItem *pPhone new QListWidgetItem;pPhone->setText("西瓜");pPhone->…

SSM整合(实现简单查询功能)

在名为ssm的数据库内创建表 CREATE TABLE account (id int(11) NOT NULL AUTO_INCREMENT,name varchar(20) DEFAULT NULL,money double DEFAULT NULL,PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8; 创建工程 pom.xml <?xml version"1.0" encoding&quo…

Find My游戏手柄|苹果Find My技术与手柄结合,智能防丢,全球定位

游戏手柄是一种常见电子游戏机的部件&#xff0c;通过操纵其按钮等&#xff0c;实现对游戏虚拟角色的控制。随着游戏设备硬件的升级换代&#xff0c;现代游戏手柄又增加了&#xff1a;类比摇杆&#xff08;方向及视角&#xff09;&#xff0c;扳机键以及HOME菜单键等。现在的游…

2024年实时获取地图边界数据方法,省市区县街道多级联动【附实时geoJson数据下载】

首先&#xff0c;来看下效果图 在线体验地址&#xff1a;https://geojson.hxkj.vip&#xff0c;并提供实时geoJson数据文件下载 可下载的数据包含省级geojson行政边界数据、市级geojson行政边界数据、区/县级geojson行政边界数据、省市区县街道行政编码四级联动数据&#xff0…

Postman接口测试神器从安装到精通

Postman 的优点&#xff1a; 支持各种的请求类型: get、post、put、patch、delete 等支持在线存储数据&#xff0c;通过账号就可以进行迁移数据很方便的支持请求 header 和请求参数的设置支持不同的认证机制&#xff0c;包括 Basic Auth&#xff0c;Digest Auth&#xff0c;OAu…

使用 Docker 部署 Halo 博客系统

:::info 项目地址&#xff1a;https://github.com/halo-dev/halo ::: 一、Halo 介绍 1&#xff09;Halo 简介 Halo 是一款强大易用的开源建站工具&#xff0c;它让你无需太多的技术知识就可以快速搭建一个博客、网站或者内容管理系统。具备可插拔架构、主题套用、富文本编辑器…