发帖
12 2 0

扇巴掌demo-Ai-M61-32S

lclight
金牌会员

6

主题

18

回帖

1781

积分

金牌会员

积分
1781
电子DIY 2311 12 2023-12-12 00:04:17
g1.png 640e681b7cc8b6aa2f8384bc313b0537.jpg

https://www.bilibili.com/video/BV1p94y1P7he/?spm_id_from=333.999.0.0

上传的附件: Project_game.zip (31.68 KB, 下载次数: 5)


以后有其它外设可以做成联机,谁输谁洗碗,解决家务纠纷


如果有相同的外设,需要配置以下内容,分别是屏幕和输入方式

#define INPUT_DEF_PIN GPIO_PIN_18 // 暂时用的输入方式
#define INPUT_ATK_PIN GPIO_PIN_19

#define SDA_PIN GPIO_PIN_31
#define SCL_PIN GPIO_PIN_30
#define OLED_ADDR 0x78







其它:如果需要,可以接多个屏幕,只是需要稍微修改

535a564901fa6f7457522b49d14c3ff4.jpg




附上设计思路

一、内容
互扇巴掌可以进行操作只有两个,攻击和防御。攻击如果击中可以让对方掉血,防御可以让对方打不中,
如果仅仅是这样,那攻击只有好处没有坏处,所以攻击一定要有副作用,比如攻击后硬直时间更长,若打不中则可能被对方攻击。
并且在发出攻击到对方受伤之间必须有时间差(如果一攻击立刻生效,那防御就是看运气),而且会造成谁先攻击谁胜利的局面。
所以这里可以得出,攻击必须有前摇,攻击后必须有硬直(也可以是需要攒气之类的,这里选用硬直)
防御需要前摇吗?不需要,因为防御是对应于攻击,增加防御前摇,跟减短攻击前摇效果是一样的。
而防御硬直必须比攻击硬直要短,否则防御到攻击之后,对方依然先行动,那防御就没意义了。



最后就变成玩家有3种行为:
1、攻击:收益大,风险高 => 有前摇和硬直,但可能打中对方
2、防御:收益中,风险中 => 短硬直,但可以免疫伤害
3、什么都不做:有收益,有风险 => 无硬直,可以进行任何操作,应对任何情况,但反应不过来就会被打




二、代码思路
1、逻辑层:
    肚子饿了会咕咕叫,被打中了会掉血,攻击后要硬直一会,这就是逻辑,根据这些逻辑驱动万事万物下一步应该是什么状态,事物的状态决定了下一步的状态,比如待机状态可以进行攻击操作,攻击状态只能继续硬直等,本质上可以说是一个状态机。而玩家操作只是状态转移的一个变量。
   
2、表现层:
    把需要表现的内容绘制到屏幕

三、代码逻辑
虽然看上去好像很复杂,但分解下来非常简单,新手也能看得懂,可以一步一步做出来。
1、对象管理
a、逻辑层需要驱动所有对象进入下一步的状态,但目前需要驱动的仅有对战的双方,而且也要判断他们之间的状态关系,所以按最简单的方式来做:直接写死。
b、表现层需要绘制的对象可就多了,所以通过链表管理。
渲染对象存在前后的关系,背景一定是在最后,UI一定是在最前面等等,所以把背景、人物、UI分为3层,分开来渲染会更简单。


我们通过一小段简单的伪代码来表示:


  1. // 逻辑循环
  2. logical_loop(){
  3.     player1.loop();
  4.     player2.loop();
  5.     do_something(&player1, &player2);
  6. }


  7. chain_draw(head){ // 绘制这个链表上所有对象
  8.     tmp = head;
  9.     while (tmp){
  10.         tmp->draw();
  11.         tmp = tmp -> next();
  12.     }
  13. }
  14. // 渲染
  15. render_loop(){
  16.     // 绘制3个链表
  17.     chain_draw(bg_head);
  18.     chain_draw(sp_head);
  19.     chain_draw(ui_head);
  20. }
  21. // 主函数
  22. main(){
  23.     init_all();
  24.     while(true){
  25.         logical_loop();
  26.         render_loop();
  27.     }
  28. }
复制代码


大体逻辑确定,接下来就是填充细节,从最开始双方都处于就绪状态,此时可以操作,操作后可能进入3种不同状态

  1. player.loop(){
  2.     switch this.state {
  3.         case idle_state:
  4.             switch get_input(this){
  5.                 case atk:
  6.                     this.state = atk_state;
  7.                 case def:
  8.                     this.state = def_state;
  9.                 case none:
  10.             };
  11.         case ...
  12.         
  13.     }
  14. }
复制代码


如果处于攻击状态,会有一段时间前摇,然后攻击,然后硬直,所以需要一个辅助变量记录当前是到哪阶段,我们为了简单,用帧来表示时间

  1. case atk_state:
  2.     state_frame ++;
  3.     switch state_frame {
  4.         case < N: // 假设前N帧是前摇,此时什么都做不了
  5.             this.state = atk_state;
  6.         case = N: // 第N帧是攻击,此时判断对方是否有防御并且在防御帧内,没有就扣血
  7.             if ( ! is_def_effect(player2) ){ do_something_hurt(player2)};
  8.         case <N2: // 硬直
  9.             none;
  10.         case >=N2: // 解除硬直
  11.             state_frame = 0;
  12.             this.state = idle_state;
  13.     };
复制代码


就这样一步一步填充内容,就大功告成了~



──── 2人觉得很赞 ────
g2.png

使用道具 举报

2023-12-12 08:47:17
赞!
2023-12-12 08:51:27
  有意思
2023-12-12 08:51:54
2023-12-12 09:06:24
有意思
2023-12-12 09:06:32
不错
2023-12-12 09:51:36
改成联机的,手动滑稽
2023-12-12 09:57:15
业余菜狗 发表于 2023-12-12 09:51
改成联机的,手动滑稽

再有一块板子就可以改成联机的了
2023-12-12 10:10:21
有点东西
2023-12-12 10:49:01
好厉害
您需要登录后才可以回帖 立即登录
高级模式
12下一页
统计信息
  • 会员数: 28268 个
  • 话题数: 40226 篇