JoyStick Shield V1.a库编写+封装
昨天给L同学展示了一下这个遥控器,今天为它封装一个库吧
上面的接口可以加诺基亚的屏幕或者与外界沟通的器件
(A)1个PS2带按钮十字摇杆,4颗圆形按钮,2个小按键。
(B)板载的开关电压可以在3.3V和5V之间切换。
(C)1个复位按键
(D)xbee/Bluetooh Bee/APC220蓝牙无线数传接口
(E)2.4G NRF24L01 RF无线数传接口
(F)Nokia 5110 LCD接口
其中对于摇杆来说,摇杆有两个电位器,可连接到Arduino上的模拟引脚A0和A1。A0的值对应于X位置。A1的值对应于Y位置。要读取这些模拟值,请使用AnalogRead()函数。
在这里
找到了一些对应的引脚映射图
https://cdn.sparkfun.com/datasheets/Dev/Arduino/Shields/Joystick_Shield-v14.pdf
包括一个原理图,其实用万用表就可以测出来
接下来就给我们的板子写个驱动吧!在写之前,先写一个关于摇杆的代码~
我们先把引脚安排了
两个数字口,检测XY
SW检测是否摁下
#define x A5 //定义X轴对应的引脚为A5
#define y A4 //定义y轴对应的引脚为A4
#define sw 2 //定义按键对应的引脚为2
void setup() {
pinMode(sw, INPUT); //设置为输入模式
digitalWrite(sw,HIGH); //给sw高电平,非按下状态为1,按下状态为0
Serial.begin(115200); //设置波特率
}
void loop() {
Serial.print("x = "); //串口输出x值
Serial.print(analogRead(x));
Serial.print(" | ");
Serial.print("y = "); //串口输出y值
Serial.print(analogRead(y));
Serial.print(" | ");
Serial.print("key = "); //串口输出sw值
Serial.println(digitalRead(sw));
delay(50); //延时50毫秒
}
结果,中间加 | 好看
库的组织形式是这样的
例子+实现的头+源码+关键词+reademe+授权
#ifndef JoystickShield_H
#define JoystickShield_H
#define CENTERTOLERANCE 5
// 兼容 Arduino 1.0
#if ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
先写点头,其实有时候不知道先写头是身子
/**
* 枚举来保存操纵杆的不同状态
*
*/
enum JoystickStates
{
CENTER, // 0
UP,
RIGHT_UP,
RIGHT,
RIGHT_DOWN,
DOWN,
LEFT_DOWN,
LEFT,
LEFT_UP //8
};
用枚举来保存状态
头文件的组织形式
我们要编写的子函数是这么多
涉及到的回调和一些变量
static const bool ALL_BUTTONS_OFF[7] = {false, false, false, false, false, false, false};
//将按钮状态数组初始化为所有未按下的按钮
管理一些板子上面按钮的初始情况
public:
JoystickShield(); // 构造函数
void setJoystickPins(byte pinX, byte pinY);
void setButtonPins(byte pinSelect, byte pinUp, byte pinRight, byte pinDown, byte pinLeft, byte pinF, byte pinE
void setButtonPinsUnpressedState(byte pinSelect, byte pinUp, byte pinRight, byte pinDown, byte pinLeft, byte p
void setThreshold(int xLow, int xHigh, int yLow, int yHigh);
void processEvents();
void processCallbacks();
void calibrateJoystick();
// 摇杆的事件
bool isCenter();
bool isUp();
bool isRightUp();
bool isRight();
bool isRightDown();
bool isDown();
bool isLeftDown();
bool isLeft();
bool isLeftUp();
bool isNotCenter();
// 摇杆坐标
int xAmplitude();
int yAmplitude();
// Button events
bool isJoystickButton();
bool isUpButton();
bool isRightButton();
bool isDownButton();
bool isLeftButton();
bool isFButton();
bool isEButton();
// 摇杆回调
void onJSCenter(void (*centerCallback)(void));
void onJSUp(void (*upCallback)(void));
void onJSRightUp(void (*rightUpCallback)(void));
void onJSRight(void (*rightCallback)(void));
void onJSRightDown(void (*rightDownCallback)(void));
void onJSDown(void (*downCallback)(void));
void onJSLeftDown(void (*leftDownCallback)(void));
void onJSLeft(void (*leftCallback)(void));
void onJSLeftUp(void (*leftUpCallback)(void));
void onJSnotCenter(void (*notCenterCallback)(void));
// 按钮回调
void onJoystickButton(void (*jsButtonCallback)(void));
void onUpButton(void (*upButtonCallback)(void));
void onRightButton(void (*rightButtonCallback)(void));
void onDownButton(void (*downButtonCallback)(void));
void onLeftButton(void (*leftButtonCallback)(void));
void onFButton(void (*FButtonCallback)(void));
void onEButton(void (*EButtonCallback)(void));
这些函数统一是共有的,用public修饰一下
具体的作用和参数后面实现的时候再讲
// 阈值
int x_threshold_low;
int x_threshold_high;
int y_threshold_low;
int y_threshold_high;
// 操纵杆的引脚
byte pin_analog_x;
byte pin_analog_y;
// 按钮摇杆
byte pin_joystick_button;
byte pin_up_button;
byte pin_right_button;
byte pin_down_button;
byte pin_left_button;
byte pin_F_button;
byte pin_E_button;
byte pin_joystick_button_unpressed;
byte pin_up_button_unpressed;
byte pin_right_button_unpressed;
byte pin_down_button_unpressed;
byte pin_left_button_unpressed;
byte pin_F_button_unpressed;
byte pin_E_button_unpressed;
// 摇杆
byte joystickStroke;
int x_position;
int y_position;
//当前的摇杆状态
JoystickStates currentStatus;
// 按钮状态数组,允许同时按下多个按钮
//顺序是上、右、下、左、e、f、操纵杆
bool buttonStates[7];
使用到的变量用private修饰
// 摇杆回调
void (*centerCallback)(void);
void (*upCallback)(void);
void (*rightUpCallback)(void);
void (*rightCallback)(void);
void (*rightDownCallback)(void);
void (*downCallback)(void);
void (*leftDownCallback)(void);
void (*leftCallback)(void);
void (*leftUpCallback)(void);
void (*notCenterCallback)(void);
// 按钮回调
void (*jsButtonCallback)(void);
void (*upButtonCallback)(void);
void (*rightButtonCallback)(void);
void (*downButtonCallback)(void);
void (*leftButtonCallback)(void);
void (*FButtonCallback)(void);
void (*EButtonCallback)(void);
// 辅助函数
void clearButtonStates();
void initializeCallbacks();
所有的回调函数,同理
下面开始写实现,一开始嘛~写个构造函数不为过,走你!
/**
* 构造函数
*
*/
JoystickShield::JoystickShield()
{
// 定义一些阈值。如果你的操纵杆不同,改这里
setThreshold(510, 530, 510, 540);
// 摇杆将操纵杆连接到引脚 0 和 1。自己也是可以去更改的
setJoystickPins(0, 1);
// 扩展板的按钮引脚
setButtonPins(8, 2, 3, 4, 5, 7, 6);
// 默认情况下的居中的位置
currentStatus = CENTER;
// 将按钮状态数组初始化为所有未按下的按钮
memcpy(buttonStates, ALL_BUTTONS_OFF, sizeof(ALL_BUTTONS_OFF));
// 将所有回调函数指针初始化为 NULL
initializeCallbacks();
}
上面的一些函数是子函数,接下来慢慢实现
/**
* 设置连接到操纵杆的Analyog引脚
*
*/
void JoystickShield::setJoystickPins(byte pinX, byte pinY)
{
pin_analog_x = pinX;
pin_analog_y = pinY;
// 将操纵杆引脚设置为输入模式
pinMode(pin_analog_x, INPUT);
pinMode(pin_analog_y, INPUT);
}
就是XY的电位器引脚的设置,函数是自带的
在头文件按内部有定义
/**
* 设置按钮使用的引脚
* 要停用按钮,请使用 arduino 范围之外的引脚,例如 255
*/
void JoystickShield::setButtonPins(byte pinSelect, byte pinUp, byte pinRight, byte pinDown, byte pinLeft, byte pinF, byte pinE)
{
pin_joystick_button = pinSelect;
pin_up_button = pinUp;
pin_right_button = pinRight;
pin_down_button = pinDown;
pin_left_button = pinLeft;
pin_F_button = pinF;
pin_E_button = pinE;
//将按钮引脚设置为输入模式
pinMode(pin_joystick_button, INPUT);
pinMode(pin_up_button, INPUT);
pinMode(pin_right_button, INPUT);
pinMode(pin_down_button, INPUT);
pinMode(pin_left_button, INPUT);
pinMode(pin_E_button, INPUT);
pinMode(pin_F_button, INPUT);
//按钮默认使用上拉电阻
setButtonPinsUnpressedState(HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH);
}
对这些按钮进行设置,在上面得调用里面也是有的
/* *
* 配置来自未按下按钮的输入是高还是低。
* 这将相应地为按钮的引脚启用上拉或下拉电阻。
*/
void JoystickShield::setButtonPinsUnpressedState(byte pinSelect, byte pinUp, byte pinRight, byte pinDown, byte pinLeft, byte pinF, byte pinE)
{
//存储未按下状态
pin_joystick_button_unpressed = pinSelect ? HIGH : LOW;
pin_up_button_unpressed = pinUp ? HIGH : LOW;
pin_right_button_unpressed = pinRight ? HIGH : LOW;
pin_down_button_unpressed = pinDown ? HIGH : LOW;
pin_left_button_unpressed = pinLeft ? HIGH : LOW;
pin_F_button_unpressed = pinF ? HIGH : LOW;
pin_E_button_unpressed = pinE ? HIGH : LOW;
//为按钮启用上拉或下拉电阻
digitalWrite(pin_joystick_button, pin_joystick_button_unpressed);
digitalWrite(pin_up_button, pin_up_button_unpressed);
digitalWrite(pin_right_button, pin_right_button_unpressed);
digitalWrite(pin_down_button, pin_down_button_unpressed);
digitalWrite(pin_left_button, pin_left_button_unpressed);
digitalWrite(pin_F_button, pin_F_button_unpressed);
digitalWrite(pin_E_button, pin_E_button_unpressed);
}
按钮按下后的传感器情况,一次7个按钮,单独管理很呆,写个函数就好了
/**
* 为操纵杆配置阈值
*/
void JoystickShield::setThreshold(int xLow, int xHigh, int yLow, int yHigh)
{
x_threshold_low = xLow;
x_threshold_high = xHigh;
y_threshold_low = yLow;
y_threshold_high = yHigh;
XY的阈值时多少,也要约束
太那啥了,模糊.懂就行
/**
*
*校准操纵杆
*
*/
void JoystickShield::calibrateJoystick()
{
byte i;
// 校准 x
int xCenter = 0;
for (i = 0; i < 10; i++)
xCenter += analogRead(pin_analog_x);
xCenter /= i;
// 校准 y
int yCenter = 0;
for (i = 0; i < 10; i++)
yCenter += analogRead(pin_analog_y);
yCenter /= i;
// 保存摇杆行程
joystickStroke = max(pin_analog_x, pin_analog_y) * 1.01;
// 设置中心差
setThreshold(xCenter - CENTERTOLERANCE, xCenter + CENTERTOLERANCE, yCenter - CENTERTOLERANCE, yCenter + CENTERTOLERANCE);
}
作为我们的遥控器,怎么能少的了校准功能呢
整一个!
精华代码,想法就是先假定我们已经知道中心位置了
然后去加减实际的数值,获得一个修正的校准值
/**
* 处理的函数,在loop()中不停轮回,它们真累
*
*/
void JoystickShield::processEvents()
{
int x_direction = 0;
int y_direction = 0;
// 从操纵杆引脚读取
x_position = analogRead(pin_analog_x);
y_position = analogRead(pin_analog_y);
// 确定操纵杆方向
if (x_position > x_threshold_high)
{
x_direction = 1;
x_position = map(x_position, x_threshold_high, x_threshold_high + x_threshold_low, 0, 100);
x_position = constrain(x_position, 0, 100);
}
else if (x_position < x_threshold_low)
{
x_direction = -1;
x_position = map(x_position, 0, x_threshold_low, -100, 0);
}
else
x_position = 0;
if (y_position > y_threshold_high)
{
y_direction = 1;
y_position = map(y_position, y_threshold_high, y_threshold_high + y_threshold_low, 0, 100);
y_position = constrain(y_position, 0, 100);
}
else if (y_position < y_threshold_low)
{
y_direction = -1;
y_position = map(y_position, 0, y_threshold_low, -100, 0);
}
else
y_position = 0;
if (x_direction == -1)
{
if (y_direction == -1)
{
currentStatus = LEFT_DOWN;
}
else if (y_direction == 0)
{
currentStatus = LEFT;
}
else
{
currentStatus = LEFT_UP;
}
}
else if (x_direction == 0)
{
if (y_direction == -1)
{
currentStatus = DOWN;
}
else if (y_direction == 0)
{
currentStatus = CENTER;
}
else
{
currentStatus = UP;
}
}
else
{
if (y_direction == -1)
{
currentStatus = RIGHT_DOWN;
}
else if (y_direction == 0)
{
currentStatus = RIGHT;
}
else
{
currentStatus = RIGHT_UP;
}
}
全场最--\(˙<>˙)/--的代码来啦!
我们先认为,现在不做任何动作的时候是原点(这不废话)
然后我们去读传感器的数值
实在不好看,我再画个简图
x = map(t,fromMAX,fromMIN,toMAX,forMIN);
x,t为同类型变量
formMAX与fromMIN为t变量本身的上下界
toMAX与toMIN为x变量的上下界
该函数将t变量值根据范围比例变换后将结果存入x变量。
看不懂?
map(num,旧区间初值,旧区间终值,新区间初值,新区间终值);
意思就是把num这个数从旧区间映射到新区间
这个看懂了吧
也用到了这个函数
对一个方向的映射和计算
对一个方向的完整版
两个方向的映射计算
这里的代码是按钮对角线的位置
大概就是这样
if (x_direction == -1)
{
if (y_direction == -1)
{
currentStatus = LEFT_DOWN;//6
}
else if (y_direction == 0)
{
currentStatus = LEFT;//7
}
else
{
currentStatus = LEFT_UP;//8
}
}
else if (x_direction == 0)
{
if (y_direction == -1)
{
currentStatus = DOWN;
}
else if (y_direction == 0)
{
currentStatus = CENTER;
}
else
{
currentStatus = UP;
}
}
else
{
if (y_direction == -1)
{
currentStatus = RIGHT_DOWN;
}
else if (y_direction == 0)
{
currentStatus = RIGHT;
}
else
{
currentStatus = RIGHT_UP;
}
通过简单的判断标志位,想不出来别的巧妙的办法了
//确定按下了哪些按钮,相应地将按钮状态数组值设置为 true/false
buttonStates[0] = digitalRead(pin_up_button) != pin_up_button_unpressed;
buttonStates[1] = digitalRead(pin_right_button) != pin_right_button_unpressed;
buttonStates[2] = digitalRead(pin_down_button) != pin_down_button_unpressed;
buttonStates[3] = digitalRead(pin_left_button) != pin_left_button_unpressed;
buttonStates[4] = digitalRead(pin_E_button) != pin_E_button_unpressed;
buttonStates[5] = digitalRead(pin_F_button) != pin_F_button_unpressed;
buttonStates[6] = digitalRead(pin_joystick_button) != pin_joystick_button_unpressed;
来判断摁下了什么按钮,更改标志位
if (isCenter() && centerCallback != NULL)
{
centerCallback();
}
先展示一个回调事件
摇杆的回调就这么多
// 按钮回调
if (isJoystickButton() && jsButtonCallback != NULL)
{
jsButtonCallback();
}
和上面一样,写一个按钮回调样子
同理
/**
* 处于中心状态的操纵杆
*
*/
bool JoystickShield::isCenter()
{
if (currentStatus == CENTER)
{
return true;
}
else
{
return false;
}
}
/**
*
* 摇杆x位置,从-100到100,0为中心
*/
int JoystickShield::xAmplitude()
{
return x_position;
}
数组读取法
/**
* 摇杆按钮按下
*
*/
bool JoystickShield::isJoystickButton()
{
return buttonStates[6];
}
摇杆的按钮,CW
/**
* 将所有函数指针初始化为 NULL
*
*/
void JoystickShield::initializeCallbacks()
{
// 操纵杆回调
centerCallback = NULL;
upCallback = NULL;
rightUpCallback = NULL;
rightCallback = NULL;
rightDownCallback = NULL;
downCallback = NULL;
leftDownCallback = NULL;
leftCallback = NULL;
leftUpCallback = NULL;
notCenterCallback = NULL;
// 按钮回调
jsButtonCallback = NULL;
upButtonCallback = NULL;
rightButtonCallback = NULL;
downButtonCallback = NULL;
leftButtonCallback = NULL;
FButtonCallback = NULL;
EButtonCallback = NULL;
}
写回调函数前,把指针的事情理明白
/**
* 操纵杆回调
*
*/
/****************************************************************** */
void JoystickShield::onJSCenter(void (*centerCallback)(void))
{
this->centerCallback = centerCallback;
}
void JoystickShield::onJSUp(void (*upCallback)(void))
{
this->upCallback = upCallback;
}
void JoystickShield::onJSRightUp(void (*rightUpCallback)(void))
{
this->rightUpCallback = rightUpCallback;
}
void JoystickShield::onJSRight(void (*rightCallback)(void))
{
this->rightCallback = rightCallback;
}
void JoystickShield::onJSRightDown(void (*rightDownCallback)(void))
{
this->rightDownCallback = rightDownCallback;
}
void JoystickShield::onJSDown(void (*downCallback)(void))
{
this->downCallback = downCallback;
}
void JoystickShield::onJSLeftDown(void (*leftDownCallback)(void))
{
this->leftDownCallback = leftDownCallback;
}
void JoystickShield::onJSLeft(void (*leftCallback)(void))
{
this->leftCallback = leftCallback;
}
void JoystickShield::onJSLeftUp(void (*leftUpCallback)(void))
{
this->leftUpCallback = leftUpCallback;
}
void JoystickShield::onJSnotCenter(void (*notCenterCallback)(void))
{
this->notCenterCallback = notCenterCallback;
}
摇杆回调
/**
* 按钮回调
*
*/
/****************************************************************** */
void JoystickShield::onJoystickButton(void (*jsButtonCallback)(void))
{
this->jsButtonCallback = jsButtonCallback;
}
void JoystickShield::onUpButton(void (*upButtonCallback)(void))
{
this->upButtonCallback = upButtonCallback;
}
void JoystickShield::onRightButton(void (*rightButtonCallback)(void))
{
this->rightButtonCallback = rightButtonCallback;
}
void JoystickShield::onDownButton(void (*downButtonCallback)(void))
{
this->downButtonCallback = downButtonCallback;
}
void JoystickShield::onLeftButton(void (*leftButtonCallback)(void))
{
this->leftButtonCallback = leftButtonCallback;
}
void JoystickShield::onFButton(void (*FButtonCallback)(void))
{
this->FButtonCallback = FButtonCallback;
}
void JoystickShield::onEButton(void (*EButtonCallback)(void))
{
this->EButtonCallback = EButtonCallback;
}
按钮回调
非静态成员函数实际上的形参个数比程序员写的多一个。
多出来的参数就是所谓的“this指针”。
这个“this指针”指向了成员函数作用的对象,在成员函数执行的过程中,正是通过“Ihis指针”才能找到对象所在的地址,因而也就能找到对象的所有非静态成员变量的地址。
this 指针是一个隐含于每一个成员函数中的特殊指针。它指向正在被该成员函数操作的那个对象。
当对一个对象调用成员函数时,编译程序先将对象的地址赋给 this 指针,然后调用成员函数,每次成员函数存取数据成员时,由隐含使用 this 指针。
当一个成员函数被调用时,自动向它传递一个隐含的参数,该参数是一个指向这个成员函数所在的对象的指针。
this 指针被隐含地声明为: ClassName const this,这意味着不能给 this 指针赋值;在 ClassName 类的 const 成员函数中,this 指针的类型为:const ClassName const,这说明不能对 this 指针所指向的这种对象是不可修改的(即不能对这种对象的数据成员进行赋值操作);
由于 this 并不是一个常规变量,所以,不能取得 this 的地址。
在以下场景中,经常需要显式引用 this 指针:
为实现对象的链式引用;
为避免对同一对象进行赋值操作;
在实现一些数据结构时,如 list。
void JoystickShield::onJSCenter(void (*centerCallback)(void))
上面这个写法是定义一个指向函数的函数指针
满足 void xxx(int, char*) 的函数
这样的形式就是回调函数
回调函数是由用户撰写,而由操作系统调用的一类函数,回调函数可以把调用者和被调用者分开,调用者(例如操作系统)不需要关心被调用者到底是哪个函数,它所知道的就是有这么一类函数,这类满足相同的函数签名(函数原型,参数,返回值等),由用户书写完毕后在被调用就可以了。实现上回调函数一般都是通过函数指针来实现的。回调函数就是一个通过函数指针调用的函数.回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。当你调用一个方法A,并不需要等待A的执行结果,而是直接往下执行,A会主动通知你,这就是回调。
https://blog.csdn.net/u014488388/article/details/54891057
http://c.biancheng.net/view/170.html
这个老哥写的demo不错
#include <JoystickShield.h>
JoystickShield joystickShield; // 创建一个实例
void setup()
{
Serial.begin(9600);
delay(100);
joystickShield.calibrateJoystick();
// 校准函数
// 摇杆回调
joystickShield.onJSUp(&up);
joystickShield.onJSRightUp(&rightUp);
joystickShield.onJSRight(&right);
joystickShield.onJSRightDown(&rightDown);
joystickShield.onJSDown(&down);
joystickShield.onJSLeftDown(&leftDown);
joystickShield.onJSLeft(&left);
joystickShield.onJSLeftUp(&leftUp);
joystickShield.onJSnotCenter(¬Center);
// 按钮回调
joystickShield.onJoystickButton(&joystickButton);
joystickShield.onUpButton(&upButton);
joystickShield.onRightButton(&rightButton);
joystickShield.onDownButton(&downButton);
joystickShield.onLeftButton(&leftButton);
joystickShield.onFButton(&FButton);
joystickShield.onEButton(&EButton);
}
void loop()
{
joystickShield.processCallbacks(); // 你什么也没有做
delay(500);
}
/** 定义回调函数 **/
void up()
{
Serial.println("Up from callback");
}
void rightUp()
{
Serial.println("Right Up from callback");
}
void right()
{
Serial.println("Right from callback");
}
void rightDown()
{
Serial.println("Right Down from callback");
}
void down()
{
Serial.println("Down from callback");
}
void leftDown()
{
Serial.println("Left Down from callback");
}
void left()
{
Serial.println("Left from callback");
}
void leftUp()
{
Serial.println("Left Up from callback");
}
void joystickButton()
{
Serial.println("Joystick from callback");
}
void upButton()
{
Serial.println("Up Button from callback");
}
void rightButton()
{
Serial.println("Right Button from callback");
}
void downButton()
{
Serial.println("Down Button from callback");
}
void leftButton()
{
Serial.println("Left Button from callback");
}
void FButton()
{
Serial.println("F Button from callback");
}
void EButton()
{
Serial.println("E Button from callback");
}
void notCenter()
{
Serial.println("回调不在中心");
// 新的位置函数
Serial.print("x ");
Serial.print(joystickShield.xAmplitude());
Serial.print(" y ");
Serial.println(joystickShield.yAmplitude());
}
写个回调的例子
#################################################
#######################################
# Datatypes (KEYWORD1)
#######################################
JoystickShield KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
setJoystickPins KEYWORD2
setButtonPins KEYWORD2
setThreshold KEYWORD2
processEvents KEYWORD2
processCallbacks KEYWORD2
# Joystick Functions
isCenter KEYWORD2
isUp KEYWORD2
isRightUp KEYWORD2
isRight KEYWORD2
isRightDown KEYWORD2
isDown KEYWORD2
isLeftDown KEYWORD2
isLeft KEYWORD2
isLeftUp KEYWORD2
isnotCenter KEYWORD2
# Button Functions
isJoystickButton KEYWORD2
isUpButton KEYWORD2
isRightButton KEYWORD2
isDownButton KEYWORD2
isLeftButton KEYWORD2
isFButton KEYWORD2
isEButton KEYWORD2
# Joystick coordinates
xAmplitude KEYWORD2
yAmplitude KEYWORD2
# Joystick callbacks Functions
onJSCenter KEYWORD2
onJSUp KEYWORD2
onJSRightUp KEYWORD2
onJSRight KEYWORD2
onJSRightDown KEYWORD2
onJSDown KEYWORD2
onJSLeftDown KEYWORD2
onJSLeft KEYWORD2
onJSLeftUp KEYWORD2
onJSnotCenter KEYWORD2
# Button callbacks
onJoystickButton KEYWORD2
onUpButton KEYWORD2
onRightButton KEYWORD2
onDownButton KEYWORD2
onLeftButton KEYWORD2
onFButton KEYWORD2
onEButton KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
#Joystick states
CENTER LITERAL1
UP LITERAL1
RIGHT_UP LITERAL1
RIGHT LITERAL1
RIGHT_DOWN LITERAL1
DOWN LITERAL1
LEFT_DOWN LITERAL1
LEFT LITERAL1
LEFT_UP LITERAL1
#Button states
NO_BUTTON LITERAL1
JOYSTICK_BUTTON LITERAL1
UP_BUTTON LITERAL1
RIGHT_BUTTON LITERAL1
DOWN_BUTTON LITERAL1
LEFT_BUTTON LITERAL1
F_BUTTON LITERAL1
E_BUTTON LITERAL1
keyword的列表也写一下
学C++去了,基础不牢,地动山摇.哭哭