• #2020征文-开发板# 用OLED板实现FlappyBird小游戏(下)


    #2020征文-开发板# 用OLED板实现FlappyBird小游戏(下)

    (图片侵删)

            年底这段时间相信大家都和我一样挺忙的,最近稍得空闲,赶紧来更新咱的FlappyBird。上次说到要加一个联机对战的功能,想想这个小鸟也不适合改成对战类,不过没关系,这也不妨碍咱们来研究一下开发板联网的方法。所以本文主要介绍我是如何让开发板具备连接wifi并开启socket server,然后开发基于HarmonyOS的手机遥控器,或者也可以说成是虚拟手柄的雏形吧。说起来,这可是鸿蒙OS手机和鸿蒙Hi3861开发板之间的故事哦。

            咱们这个Harmony Hi3861 Wifi IoT开发板本来就是为Wifi智能家居量身定做,所以Wifi的支持一定少不了,在阅读了各种官方文档、代码,又拜读了连志安老师的几篇文章(链接),总算是有了眉目。

            一般来说,wifi相关的接口都在“vendorhisihi3861hi3861 hird_partylwip_sackincludelwip etifapi.h”头文件中,仔细阅读代码中的注释会很有帮助。这次没有把手机配网功能放进来,因为觉得每次运行还得手机一顿操作好麻烦,用的是直接STA模式连接指定AP的方式,以后可以改进成碰一碰组网的方式,留待后续研究。

            话不多说,上图:

            这是总体架构图,路由器做AP,手机和开发板分别连接到同一个Wifi。

    #2020征文-开发板# 用OLED板实现FlappyBird小游戏(下)

            这是开发板启动server的流程图:

    #2020征文-开发板# 用OLED板实现FlappyBird小游戏(下)        在启动socket server后,就是接受客户端的连接请求,然后循环接收数据,根据指令执行动作。还有一点需要注意,那就是网络相关的操作函数放到单独的一个thread中执行,即后台连接网络,避免阻塞程序主线程。这里socket server侦听端口设置为8888。

            很快我就发现,不知道开发板的IP地址啊。虽然我可以在路由器管理页面上查看到所有设备IP,但总是不方便,总不能去哪都得找路由器管理员吧。于是我又加入了一键显示IP地址的功能。具体就是调用netifapi_netif_get_addr函数(netifapi.h),函数的声明如下:

    /*
     * Func Name:  netifapi_netif_get_addr
     */
    /**
     * @ingroup Threadsafe_Network_Interfaces
     *
     * @brief
     *
     *  This is a thread safe API, used to get IP_add configuration for a network interface
     *  (including netmask and default gateway).
     *  It is recommended to use this API instead of netif_get_addr()
     *
     * @param[in]    netif          Indicates the network interface to get.
     * @param[in]    ipaddr         Indicates the IP address.
     * @param[in]    netmask        Indicates the network mask.
     * @param[in]    gw             Indicates the default gateway IP address.
     *
     * @returns
     *  0 : On success 
    
     *  Negative value : On failure 
    
     *
     * @par Related Topics
     * netif_get_addr()
     *
     * @note
     *   - netmask and/or gw can be passed NULL, if these details about the netif are not needed
     */
    err_t netifapi_netif_get_addr(struct netif *netif,
                                  ip4_addr_t *ipaddr,
                                  ip4_addr_t *netmask,
                                  ip4_addr_t *gw);

            第一个参数netif,即之前连接wifi用到的netif结构体指针,其他三个分别是用来返回的ip地址、子网掩码、网关。

            那么如何把返回的ip4_addr_t结构体转换为通用的数字加句点的字符串格式(例如192.168.1.1)呢?答案就是ip4addr_ntoa函数。

    char *ip = ip4addr_ntoa(ipAddr);
    printf("ip: %s
    ", ip);
    free(ip)//用完记得释放

            其实在vendorhisihi3861hi3861 hird_partylwip_sackincludelwipip4_addr.h头文件中定义好了一系列的转换函数,他们的定义如下,我们可以按需使用:

    u32_t ipaddr_addr(const char *cp);
    int ip4addr_aton(const char *cp, ip4_addr_t *addr);
    /** returns ptr to static buffer; not reentrant! */
    char *ip4addr_ntoa(const ip4_addr_t *addr);
    char *ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen);
    
    int inet_pton4(const char *src, unsigned char *dst);
    const char *lwip_inet_ntop4(const unsigned char *src, char *dst, u32_t size);

            手机控制器方面,我在DevEcoStudio中基于鸿蒙OS做了一版App,主要实现Tcp方式连接到指定IP,并发送指令。但由于手上没有真机,故无法调试,只能另外做了一个Android版本App代替调试,有些遗憾,希望也能借此机会拿到P40,完成这个梦想,也一睹鸿蒙OS的芳容。

            这是在DevEcoStudio中的工程截图:

    #2020征文-开发板# 用OLED板实现FlappyBird小游戏(下)

    模拟器运行起来长这样:

    #2020征文-开发板# 用OLED板实现FlappyBird小游戏(下)

            就是模拟器没法联网,比较无奈。不过这不妨碍做一个Android版本用来测试,核心代码如下:

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //添加按钮事件回调
            this.findViewById(R.id.btn_go).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
    
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            EditText editIp = findViewById(R.id.edit_ip);//界面添加了一个IP地址输入框
                            String ip = editIp.getText().toString();
                            sendCmd(ip);//向指定IP发送指令
                        }
                    }).start();
                }
            });
        }
    
        private Socket socket;
    
        private void sendCmd(String ipAddr){
            int port = 8888;//开发板socket server监听端口号8888
            try {
                if(socket == null){
                    socket = new Socket(ipAddr, port);//创建socket客户端
                    Log.i("JoyStick", "Create socket!!");
                }
                String cmdData = "A";//发送一个A
                byte data[] = cmdData.getBytes();
                socket.getOutputStream().write(data);
                Log.i("JoyStick", "Send success!!");
                showMessage("Send success!", Toast.LENGTH_SHORT);
            }
            catch (Exception e)
            {
                e.printStackTrace();
                Log.e("JoyStick", e.toString());
                showMessage("Send Error!
    " + e.toString(), Toast.LENGTH_SHORT);
            }
        }
    }

            APP在我的mate20上运行界面如下:

    查看更多内容>>>

     

    作者:老船夫

    想了解更多内容,请访问: 51CTO和华为官方战略合作共建的鸿蒙技术社区https://harmonyos.51cto.com/

  • 相关阅读:
    POJ 1018 Communication System
    POJ 1017 Packets
    Codeforces 725B Food on the Plane
    Lessons learned from manually classifying CIFAR-10
    CCF推荐国际学术期刊
    局部数组过大导致编译栈区溢出问题
    自己动手写处理器之第一阶段(3)——MIPS32指令集架构简单介绍
    C++学习笔记29,引用变量(1)
    Android视频应用去广告学习实践
    sublime编辑器怎样高速输入PHP头部版本号声明
  • 原文地址:https://www.cnblogs.com/HarmonyOS/p/14272066.html
Copyright © 2020-2023  润新知