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
其它:如果需要,可以接多个屏幕,只是需要稍微修改
附上设计思路
一、内容
互扇巴掌可以进行操作只有两个,攻击和防御。攻击如果击中可以让对方掉血,防御可以让对方打不中,
如果仅仅是这样,那攻击只有好处没有坏处,所以攻击一定要有副作用,比如攻击后硬直时间更长,若打不中则可能被对方攻击。
并且在发出攻击到对方受伤之间必须有时间差(如果一攻击立刻生效,那防御就是看运气),而且会造成谁先攻击谁胜利的局面。
所以这里可以得出,攻击必须有前摇,攻击后必须有硬直(也可以是需要攒气之类的,这里选用硬直)
防御需要前摇吗?不需要,因为防御是对应于攻击,增加防御前摇,跟减短攻击前摇效果是一样的。
而防御硬直必须比攻击硬直要短,否则防御到攻击之后,对方依然先行动,那防御就没意义了。
最后就变成玩家有3种行为:
1、攻击:收益大,风险高 => 有前摇和硬直,但可能打中对方
2、防御:收益中,风险中 => 短硬直,但可以免疫伤害
3、什么都不做:有收益,有风险 => 无硬直,可以进行任何操作,应对任何情况,但反应不过来就会被打
二、代码思路
1、逻辑层:
肚子饿了会咕咕叫,被打中了会掉血,攻击后要硬直一会,这就是逻辑,根据这些逻辑驱动万事万物下一步应该是什么状态,事物的状态决定了下一步的状态,比如待机状态可以进行攻击操作,攻击状态只能继续硬直等,本质上可以说是一个状态机。而玩家操作只是状态转移的一个变量。
2、表现层:
把需要表现的内容绘制到屏幕
三、代码逻辑
虽然看上去好像很复杂,但分解下来非常简单,新手也能看得懂,可以一步一步做出来。
1、对象管理
a、逻辑层需要驱动所有对象进入下一步的状态,但目前需要驱动的仅有对战的双方,而且也要判断他们之间的状态关系,所以按最简单的方式来做:直接写死。
b、表现层需要绘制的对象可就多了,所以通过链表管理。
渲染对象存在前后的关系,背景一定是在最后,UI一定是在最前面等等,所以把背景、人物、UI分为3层,分开来渲染会更简单。
我们通过一小段简单的
伪代码来表示:
- // 逻辑循环
- logical_loop(){
- player1.loop();
- player2.loop();
- do_something(&player1, &player2);
- }
- chain_draw(head){ // 绘制这个链表上所有对象
- tmp = head;
- while (tmp){
- tmp->draw();
- tmp = tmp -> next();
- }
- }
- // 渲染
- render_loop(){
- // 绘制3个链表
- chain_draw(bg_head);
- chain_draw(sp_head);
- chain_draw(ui_head);
- }
- // 主函数
- main(){
- init_all();
- while(true){
- logical_loop();
- render_loop();
- }
- }
复制代码
大体逻辑确定,接下来就是填充细节,从最开始双方都处于就绪状态,此时可以操作,操作后可能进入3种不同状态
- player.loop(){
- switch this.state {
- case idle_state:
- switch get_input(this){
- case atk:
- this.state = atk_state;
- case def:
- this.state = def_state;
- case none:
- };
- case ...
-
- }
- }
复制代码
如果处于攻击状态,会有一段时间前摇,然后攻击,然后硬直,所以需要一个辅助变量记录当前是到哪阶段,我们为了简单,用帧来表示时间
- case atk_state:
- state_frame ++;
- switch state_frame {
- case < N: // 假设前N帧是前摇,此时什么都做不了
- this.state = atk_state;
- case = N: // 第N帧是攻击,此时判断对方是否有防御并且在防御帧内,没有就扣血
- if ( ! is_def_effect(player2) ){ do_something_hurt(player2)};
- case <N2: // 硬直
- none;
- case >=N2: // 解除硬直
- state_frame = 0;
- this.state = idle_state;
- };
复制代码
就这样一步一步填充内容,就大功告成了~