赞
踩
可不可以用香橙派来玩游戏呢?当然可以,今天用它来玩贪吃蛇!
在踩坑之旅(四)中,我们介绍了设置声卡的两款工具alsamixer和amixer,很显然alsamixer这种图形化的界面更加人性化,更适合人机互动,那这个界面是如何实现的呢?亲自动手完成变身MP3播放器的同学会发现,alsamixer用到了一个依赖包ncurses。Ncurses是一个能提供功能键定义(快捷键),屏幕绘制以及基于文本终端的图形互动功能的动态库[1]。Ncurses可以:
有心的同学可能会记得,在踩坑之旅(一)中make menuconfig也用到了ncurses库,没错,就是我们看到的那个配置界面。事实上,make menuconfig最终修改了buildroot-2020.11目录下的.config文件,这个文件就是个文本文档,可以手工修改,但还是用make menuconfig更直观。
由此看来,Ncurses可以实现终端界面下的图形互动,虽然略显简陋。本文介绍的贪吃蛇就是Ncurses的一个典型应用。当然,这里不是要讲贪吃蛇的具体算法实现,我们直接使用他人开源的代码。下载地址:
https://codeload.github.com/CoinsJack/my_snake_game/zip/master
将代码下载到桌面上。对源代码感兴趣的同学可以访问作者的博客:
https://www.cnblogs.com/litran/p/10640893.html
将代码包解压到桌面,此时可以看到目录中有个可执行文件hungry_snake,这个文件是电脑端运行的文件,你可以双击运行体验一下。我们需要重新编译可在香橙派运行的可执行文件,也就是传说中的交叉编译。在终端进入该目录,输入如下命令对代码进行编译
dpmicro@dpmicro-PC:~/Desktop/my_snake_game-master$ arm-linux-gnueabihf-gcc -o snake main.c snake.c -L ../buildroot-2020.11/output/target/usr/lib -lncurses -I ../buildroot-2020.11/output/host/arm-buildroot-linux-gnueabihf/sysroot/usr/include/
将生成的snake文件传送到香橙派上
- dpmicro@dpmicro-PC:~/Desktop/my_snake_game-master$ scp snake root@192.168.1.10:/root
- root@192.168.1.10's password:
- snake 100% 23KB 681.9KB/s 00:00
在香橙派的SSH命令中输入
- # ls
- snake
- # ./snake
按下字母e键开始游戏吧。
画面颜色不好看?我们来改代码,很简单。打开main.c,将第25行至32行修改如下
- init_pair(1,COLOR_GREEN,COLOR_BLACK);//前景色,背景色
- init_pair(2,COLOR_BLACK,COLOR_WHITE);
-
- attron(COLOR_PAIR(1));//增加一行,其余不变
- print_snake_logo(stdscr);
- mvprintw(LINES-1,COLS-20,"Producted by Jack");
看看效果
画面颜色太单调?继续改main.c
- #include <unistd.h>
- #include <stdlib.h>
- #include "snake.h"
- #include <ncurses.h>
- #include "wellcome.h"
- #include <pthread.h>
-
-
- int ch;
- int GAMEOVER;
-
- int main()
- {
- initscr();
- start_color();
- keypad(stdscr,TRUE);
- curs_set(0);
- noecho();
- halfdelay(4);
- init_pair(1, COLOR_GREEN,COLOR_BLACK);
- init_pair(2, COLOR_BLACK,COLOR_WHITE);
- //增加7种前景色,加上背景色黑色,一共支持8种颜色
- init_pair(4, COLOR_RED, COLOR_BLACK);
- init_pair(5, COLOR_GREEN, COLOR_BLACK);
- init_pair(6, COLOR_YELLOW,COLOR_BLACK);
- init_pair(7, COLOR_BLUE, COLOR_BLACK);
- init_pair(8, COLOR_MAGENTA,COLOR_BLACK);
- init_pair(9, COLOR_CYAN, COLOR_BLACK);
- init_pair(10, COLOR_WHITE, COLOR_BLACK);
-
- attron(COLOR_PAIR(1));
- print_snake_logo(stdscr);
- mvprintw(LINES-1,COLS-20,"Producted by Jack");
-
-
-
- mvprintw(LINES-4,(COLS-21)/2,"|-> START");
- printw(" (? for help)");
-
-
- refresh();
- int choice;
- char goout = 0;
- while (!goout)
- {
-
- switch (choice = getch() )
- {
- case 'q':
- endwin();
- return 0;
- case 'e':
- goout = 1;
- break;
- }
-
- }
-
-
- Psnake jack = init_snake();
- init_show_snake(jack);
- ch = mvgetch(LINES-1,0);
- srand((unsigned)time(0));
-
- for (int i = 0; i<10; i++)
- putfood(jack);
- refresh();
- int noout = 1;
- int c = 0;
- int i=4;//颜色循环
- while(noout)
- {
- attron(COLOR_PAIR(i));//使用i指向的颜色
- ch = getch();
- switch (ch)
- {
-
- case KEY_RIGHT:
- c = snake_go_right(jack);
- if ( c == -1)
- {
- noout = 0;
- GAMEOVER = 1;
- break;
- }
- continue;
-
- case KEY_DOWN :
- c = snake_go_down(jack);
- if ( c == -1)
- {
- noout = 0;
- GAMEOVER = 1;
- break;
- }
- continue;
-
- case KEY_LEFT:
- c = snake_go_left(jack);
- if ( c == -1)
- {
- noout = 0;
- GAMEOVER = 1;
- break;
- }
- continue;
-
- case KEY_UP:
- c = snake_go_up(jack);
- if ( c == -1)
- {
- noout = 0;
- GAMEOVER = 1;
- break;
- }
- continue;
- case 'q':
- game_over(jack);
- endwin();
- return 0;
- }
-
- if (jack->righting)
- {
- c = snake_go_right(jack);
- if (c == -1)
- {
- GAMEOVER = 1;
- break;
- }
- }
- else if (jack->lefting)
- {
- c = snake_go_left(jack);
- if (c == -1)
- {
- GAMEOVER = 1;
- break;
- }
-
- }
- else if(jack->uping)
- {
- c = snake_go_up(jack);
- if (c == -1)
- {
- GAMEOVER = 1;
- break;
- }
-
- }
- else if(jack->downing)
- {
- c = snake_go_down(jack);
- if (c == -1)
- {
- GAMEOVER = 1;
- break;
- }
-
- }
-
- if (food_num < 30)
- putfood(jack);
- mvprintw(LINES-1,2,"-- socre %d --",jack->length);
- attroff(COLOR_PAIR(i));
- refresh();
- i++;
- if(i==11)i=4;//颜色循环结束
- }
-
- if(GAMEOVER)
- game_over(jack);
-
- refresh();
-
- endwin();
- return 0;
- }

漂亮多了吧?好似满天繁星
如此好玩的游戏只能借助SSH才能使用实在是不舒服,我们来给香橙派接个显示器。香橙派自带HDMI和AV模拟输出,而我只有VGA接口的显示器,所以使用HDMI转VGA再连接显示器。开机上电,uboot启动内核后好像没有画面了,只剩一个光标在左上角闪烁,这是怎么回事?刚通电的时候,可以看到显示器上有uboot的启动信息,说明是可以通过HDMI输出画面的,问题出在哪里呢?回到SSH,查看uboot传递给内核的启动参数
- # cat /proc/cmdline
- console=ttyS0,115200 earlyprintk root=/dev/mmcblk0p2 rootwait
可以看到,console参数只配置了串口,也就是说内核启动、初始化的信息只会输出到串口。这个配置在哪里修改呢?打开buildroot-2020.11/board/orangepi/orangepi-pc目录下的boot.cmd文件可以看到,这些参数均属于环境变量bootargs
- setenv fdt_high ffffffff
-
- setenv bootargs console=ttyS0,115200 earlyprintk root=/dev/mmcblk0p2 rootwait
-
- fatload mmc 0 $kernel_addr_r zImage
- fatload mmc 0 $fdt_addr_r sun8i-h3-orangepi-pc.dtb
-
- bootz $kernel_addr_r - $fdt_addr_r
如果我们将第三行修改为
setenv bootargs console=ttyS0,115200 console=tty0 earlyprintk root=/dev/mmcblk0p2 rootwait
然后回到buildroot-2020.11目录下,先make再烧录镜像,你会发现,完全没有效果,哈哈。这是因为uboot实际读取的是boot.scr,然而make命令并没有生成新的文件。我们来手工生成一下,终端打开buildroot-2020.11/board/orangepi/orangepi-pc目录
- dpmicro@dpmicro-PC:~/Desktop/buildroot-2020.11/board/orangepi/orangepi-pc$ ../../../output/build/uboot-2020.07/tools/mkimage -A arm -O linux -T script -C none -a 0 -e 0 -n "OrangePi Boot Script" -d boot.cmd boot.scr
- Image Name: OrangePi Boot Script
- Created: Fri Jan 1 18:00:47 2021
- Image Type: ARM Linux Script (uncompressed)
- Data Size: 249 Bytes = 0.24 KiB = 0.00 MiB
- Load Address: 00000000
- Entry Point: 00000000
- Contents:
- Image 0: 241 Bytes = 0.24 KiB = 0.00 MiB
- dpmicro@dpmicro-PC:~/Desktop/buildroot-2020.11/board/orangepi/orangepi-pc$ ls
- boot.cmd boot.scr genimage.cfg linux.fragment readme.txt
将刚刚生成的boot.scr传送到香橙派TF卡的第一分区,也就是那个FAT32格式的分区。我们先将该分区进行挂载,然后用scp传过去
- # mount /dev/mmcblk0p1 /mnt/
- # ls /mnt/
- boot.scr sun8i-h3-orangepi-pc.dtb zImage
- dpmicro@dpmicro-PC:~/Desktop/buildroot-2020.11/board/orangepi/orangepi-pc$ scp boot.scr root@192.168.1.10:/mnt
- root@192.168.1.10's password:
- boot.scr 100% 313 55.3KB/s 00:00
好,现在重启香橙派。可以看到,在屏幕上也显示了内核启动的各项信息。但是,启动完并不能登陆啊,纯粹只是显示内核打印的信息而已。。。
突然回想起踩坑之旅(一)当中的一个配置
这个配置项用于配置系统启动后终端模式的启动方式,当然啦,这里配置的是串口,那这个配置实际修改了哪个文件呢?是/etc/inittab,我们来查看一下
- # /etc/inittab
- #
- # Copyright (C) 2001 Erik Andersen <andersen@codepoet.org>
- #
- # Note: BusyBox init doesn't support runlevels. The runlevels field is
- # completely ignored by BusyBox init. If you want runlevels, use
- # sysvinit.
- #
- # Format for each entry: <id>:<runlevels>:<action>:<process>
- #
- # id == tty to run on, or empty for /dev/console
- # runlevels == ignored
- # action == one of sysinit, respawn, askfirst, wait, and once
- # process == program to run
-
- # Startup the system
- ::sysinit:/bin/mount -t proc proc /proc
- ::sysinit:/bin/mount -o remount,rw /
- ::sysinit:/bin/mkdir -p /dev/pts /dev/shm
- ::sysinit:/bin/mount -a
- ::sysinit:/sbin/swapon -a
- null::sysinit:/bin/ln -sf /proc/self/fd /dev/fd
- null::sysinit:/bin/ln -sf /proc/self/fd/0 /dev/stdin
- null::sysinit:/bin/ln -sf /proc/self/fd/1 /dev/stdout
- null::sysinit:/bin/ln -sf /proc/self/fd/2 /dev/stderr
- ::sysinit:/bin/hostname -F /etc/hostname
- # now run any rc scripts
- ::sysinit:/etc/init.d/rcS
-
- # Put a getty on the serial port
- ttyS0::respawn:/sbin/getty -L ttyS0 115200 vt100 # GENERIC_SERIAL
-
- # Stuff to do for the 3-finger salute
- #::ctrlaltdel:/sbin/reboot
-
- # Stuff to do before rebooting
- ::shutdown:/etc/init.d/rcK
- ::shutdown:/sbin/swapoff -a
- ::shutdown:/bin/umount -a -r

# Put a getty on the serial port这一句已经很明显了,我们来增加一句,修改如下
- # Put a getty on the serial port
- ttyS0::respawn:/sbin/getty -L ttyS0 115200 vt100 # GENERIC_SERIAL
- tty0::respawn:/sbin/getty tty0 0
大体格式上照抄,但tty0实际上是虚拟的设备,不是串口,也就没有波特率,这里写0,其实任何值都无所谓。这样就将终端同时在串口和屏幕上启动。保存文件然后重启。
这样就达到了在屏幕上显示终端的目的。事实上,上文的boot.cmd可以不修改,不过踩坑嘛,没坑还踩啥。没错,不用揉眼睛,这个SNAKE不是彩色的,我也很奇怪,明明是可以显示颜色的呀,有知道的小伙伴请留言哦。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。