世嘉MD游戏开发【四】:输入控制(下)

news/2024/11/28 3:36:05/

上一节讲了世嘉MD两种输入控制当中的一种,也是比较容易理解的一种,这一节讲一下剩下的这种控制方式:回调函数式。

建好文件夹,用vscode打开,新建main.c,依然是直觉一般的写下如下代码:

#include <genesis.h>
#include <joy.h>    //这一句不加也能编译通过,只是方便F12跳转过去看文档int main()
{while (1){VDP_waitVSync();}return 0;
}

我其实也没有背过怎么写那个回调函数,有哪些参数啊什么的我都没记住,不过不要紧,只要你记住输入相关的内容都在joy.h这个头文件中就行了,然后include一下就可以直接按F12跳转到文档了。

跳转到文档,我们会发现有一个很明显属于回调函数的代码,详情如下:

/***  \brief*      Joypad event callback.**  \param joy*      Joypad which generated the event.<br>*      <b>JOY_1</b>    = joypad 1<br>*      <b>JOY_2</b>    = joypad 2<br>*      <b>...  </b>    = ...<br>*      <b>JOY_8</b>    = joypad 8 (only possible with 2 teamplayers connected)<br>*      <b>JOY_ALL</b>  = joypad 1 | joypad 2 | ... | joypad 8<br>*  \param change*      Changed state (button for which state changed).<br>*      <b>BUTTON_UP</b>    = UP button<br>*      <b>BUTTON_DOWN</b>  = DOWN button<br>*      <b>BUTTON_LEFT</b>  = LEFT button<br>*      <b>BUTTON_RIGHT</b> = RIGHT button<br>*      <b>BUTTON_A</b>     = A button<br>*      <b>BUTTON_B</b>     = B button<br>*      <b>BUTTON_C</b>     = C button<br>*      <b>BUTTON_START</b> = START button<br>*      <b>BUTTON_X</b>     = X button<br>*      <b>BUTTON_Y</b>     = Y button<br>*      <b>BUTTON_Z</b>     = Z button<br>*      <b>BUTTON_MODE</b>  = MODE button<br>*      <b>BUTTON_LMB</b>   = Alias for A button for mouse<br>*      <b>BUTTON_MMB</b>   = Alias for B button for mouse<br>*      <b>BUTTON_RMC</b>   = Alias for C button for mouse<br>*  \param state*      Current joypad state.<br>*<br>*      Ex: Test if button START on joypad 1 just get pressed:<br>*      joy = JOY_1; changed = BUTTON_START; state = BUTTON_START | (previous state)*/
typedef void _joyEventCallback(u16 joy, u16 changed, u16 state);

就是typedef void _joyEventCallback(u16 joy, u16 changed, u16 state);这一行了,很容易联想到这肯定是另一个函数的参数,继续往下拉就能看到调用这个参数的函数了,看代码:

/***  \brief*      Set the callback function for controller state changed.<br>*<br>*      SGDK provides facilities to detect state change on controller.<br>*      It update controllers state at each V Blank period and fire event if a state change is detected.<br>**  \param CB*      Callback to call when controller(s) state changed.<br>*      The function prototype should reply to _joyEventCallback type :<br>*      void function(u16 joy, u16 changed, u16 state);<br>*      意思就是控制器状态更改的时候会调用这个函数。回调函数的形式应该是下面这样的:*      void function(u16 joy, u16 changed, u16 state);*<br>*      <b>Ex 1</b> : if player 1 just pressed START button you receive :<br>*      joy = JOY_1, changed = BUTTON_START, state = BUTTON_START<br>*      <b>Ex 2</b> : if player 2 just released the A button you receive :<br>*      joy = JOY_2, changed = BUTTON_A, state = 0<br>*/
void JOY_setEventHandler(_joyEventCallback *CB);

单看这个注释还是感觉一头雾水,那么咱们就来做个小实验吧,看看这个joychangedstate都是什么东西。

main函数上面声明一下回调函数,函数名随便写,我就叫handleInputCallback好了,然后在main函数下面实现回调函数,再回到main函数,在while循环里去调用回调函数(错误更正:其实不用在while循环里调用,直接在while循环上面调用就可以了,这是我写完文章才发现的),代码如下:

#include <genesis.h>
#include <joy.h> //这一句不加也能编译通过,只是方便F12跳转过去看文档void handleInputCallback(u16 joy, u16 changed, u16 state);int main()
{while (1){JOY_setEventHandler(handleInputCallback);VDP_waitVSync();}return 0;
}void handleInputCallback(u16 joy, u16 changed, u16 state)
{//输入
}

然后我们就在handleInputCallback函数里打印一下这几个参数,代码如下:

//省略上面的代码,只给出回调函数部分void handleInputCallback(u16 joy, u16 changed, u16 state)
{//输入char strJoy[20];        //存储joy数值的字符串char strChanged[20];char strState[20];//用sprintf函数把这几个参数存储到数组中sprintf(strJoy, "%4d", joy);sprintf(strChanged, "%4d", changed);sprintf(strState, "%4d", state);//在屏幕上打印字符串VDP_drawText("joy = ",0,1);     VDP_drawText(strJoy,5,1);VDP_drawText("changed = ",0,2); VDP_drawText(strChanged,5,2);VDP_drawText("state = ",0,3);     VDP_drawText(strState,5,3);
}

再看结果之前先给出几个键值和手柄端口值:

#define JOY_1           0x0000        //1P
#define JOY_2           0x0001        //2P
#define JOY_3           0x0002
#define JOY_4           0x0003
#define JOY_5           0x0004
#define JOY_6           0x0005
#define JOY_7           0x0006
#define JOY_8           0x0007
#define JOY_NUM         0x0008
#define JOY_ALL         0xFFFF#define BUTTON_UP       0x0001      //十进制    1
#define BUTTON_DOWN     0x0002      //十进制    2
#define BUTTON_LEFT     0x0004      //十进制    4
#define BUTTON_RIGHT    0x0008      //十进制    8
#define BUTTON_A        0x0040      //十进制    64
#define BUTTON_B        0x0010      //十进制    16
#define BUTTON_C        0x0020      //十进制    32
#define BUTTON_START    0x0080      //十进制    128
#define BUTTON_X        0x0400      //十进制    1024
#define BUTTON_Y        0x0200      //十进制    512
#define BUTTON_Z        0x0100      //十进制    256
#define BUTTON_MODE     0x0800      //十进制    2048

回到main.cCtrl+Shift+B编译一下,运行rom,尝试一下按键,对照一下键值表很直观的就能得出joychangedstate是什么东西了。

joy就是手柄端口号了,1P的端口号是0,所以屏幕上得到的joy也是0.

changed是当前按键的值,如果先按住A键再按住B键,那么changed显示的是B键的值。

state是所有按键的和,如果先按住A键再按住B键,那么changed显示的就是A+B两个键的和。

配合 世嘉MD游戏开发【三】:输入控制(上)效果更好

未完待续。。。

复古游戏开发群:879063892


http://www.ppmy.cn/news/535658.html

相关文章

世嘉MD游戏开发【九】:Sprite精灵

终于讲到Sprite精灵了&#xff0c;我自己也很希望快点讲精灵&#xff0c;但是欲速则不达&#xff0c;自己要是还没研究透彻这个知识点就去讲下一个&#xff0c;感觉文章肯定是写不好的。 我用下图来做演示&#xff0c;SFC幽游白书-魔界最强列传里的雷禅&#xff1a; 怎么处理图…

世嘉MD游戏开发【五】:显示Tile图块

显示Tile图块&#xff0c;首先要有tile图块&#xff0c;这就要用到一个小工具了&#xff0c;叫Sega Genesis Tile Designer&#xff0c;软件界面如下&#xff1a; 看起来很复杂&#xff0c;其实自己亲自操作一下几分钟就能搞懂了&#xff0c;都是些很基础的功能&#xff0c;软件…

世嘉MD游戏开发【十二】:伪3D地面,Pseudo-3D

终于讲到伪3D效果了&#xff0c;这一块比较棘手&#xff0c;我从github上下载的老外写的例子一点点研究&#xff0c;研究了两三天才研究出原理&#xff0c;其实原理很TM简单&#xff0c;主要是那个老外写的代码太烂了&#xff0c;写了很多没用的东西&#xff0c;而且算法上还啰…

世嘉MD游戏开发【二】:Hello World

上一节课已经讲了SGDK环境的配置&#xff0c;这一节课来开发我们的第一个世嘉MD程序&#xff1a;Hello World 编辑器我用的vscode&#xff0c;本文就以vscode为主。 一、新建一个工程&#xff0c;其实不用说的这么正式&#xff0c;意思就是在你喜欢的任意位置新建一个文件夹&…

世嘉MD游戏开发【七】:绘制图片,drawImage

这一期讲绘制图片。 上一期讲的是绘制tile&#xff0c;还要用那个不怎么好用的工具导出数组数据&#xff0c;很繁琐&#xff0c;这次就不用那个蹩脚的工具了&#xff0c;随便一个图片用photoshop处理一下就可以了&#xff0c;对于图片的要求有这么几点&#xff1a; 1.图片分辨…

神龟对打java_谁知道世嘉游戏忍者神龟对打的出招表!

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 忍者神龟之格斗大会 Teenage Mutant Hero Turtles Tournament Fighters (E) KONAMI/93.12.10/机种MD/类型FTG 基本操作-出招-- A 轻斩 B 轻踢 C 挑衅 投技&#xff1a; 近身 → A或B 当血槽减少呈闪灭状态时可使用超必杀 ~~~~~~~…

【数据库七】MySQL主从复制与读写分离

MySQL主从复制与读写分离 1.案例概述2.什么是读写分离&#xff1f;3.为什么要读写分离呢&#xff1f;4.什么时候要读写分离&#xff1f;5.主从复制与读写分离6.MySQL主从复制原理6.1 mysql的复制类型 7.主从复制的工作过程7.1 MySQL架构图7.2 口语化工作工程 8.MySQL 读写分离原…

构建安全架构的 Azure 云:深入了解零信任体系结构

文章目录 前言一、零信任安全模型的概念以及背景介绍二、传统安全模型&#xff08;边界模型&#xff09;三、零信任模型&#xff08;现阶段主流云厂商策略&#xff09;四、Azure 中的零信任体系结构&#xff08;本文重点&#xff09;4.1 基础知识点&#xff08;必须了解&#x…