import sys,os
#调用数学库和时间库
import math,time
#调用多线程库
import threading
#定义全局变量
program_running_flag = False
accel = 0
#标准getch部分,不重复说明
def getch():
# tty = teletypewriter, termios = terminal io interface
import tty, termios
# stdin = standard input, fileno = filestream number
fd = sys.stdin.fileno()
# tcgetattr = termios configuration get attribute
old_settings = termios.tcgetattr(fd)
# 尝试
try:
# 通过tty模块获取stdin的file stream,然后用read(1)读取1个字节
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
# 尝试部分执行完成后执行的“善后”代码
finally:
# termios configuration set attribute
# TCSADRAIN,在termios传输完成后生效,具体参照Unix termios模块的说明
# 不确定通过tty模块读取输入会对配置造成什么影响,这段代码是用来消除这个影响的
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
# 返回并输出读取到的ch
return ch
#定义输入任务
def input_task():
#设定获取全局变量
#全局变量可被跨线程访问
global accel, program_running_flag
#设置本地变量
#可以调整sleep时间来看下实际影响
input_task_sleep_time=0.1
#用flag控制主程序循环,这样在需要的时候可以更好的控制退出的时机和行为
while program_running_flag:
#获取输入
input_key = getch()
#如果输入是ESC按键
if ord(input_key) == 27:
#通过改变flag状态控制所有线程退出
program_running_flag = False
#如果输入是w则加速
elif ord(input_key) == ord("w"):
accel+=1
#如果输入是s则加速
elif ord(input_key) == ord("s"):
accel-=1
#如果输入是空格则加速度清零
elif ord(input_key) == ord(" "):
accel = 0
#通过inline if来控制accel的范围
#math.copysign(x,y)返回y的符号和x的值
accel = accel if abs(accel)<=10 else math.copysign(10,accel)
#通过控制线程睡眠时间避免跑得过快抢占系统资源
time.sleep(input_task_sleep_time)
#定义输出任务
def output_task():
#设定获取全局变量
#全局变量可被跨线程访问
global accel, program_running_flag
#删除整行文字的控制符,具体可以参考下面链接(仅适用linux):
# https://tldp.org/HOWTO/Bash-Prompt-HOWTO/x361.html
erase_str = "\r\033[k"
# 设置本地变量
speed = 0
#可以调整sleep时间来看下实际影响
output_task_sleep_time = 0.1
#用flag控制主程序循环,这样在需要的时候可以更好的控制退出的时机和行为
while program_running_flag:
#更新速度
speed += accel*output_task_sleep_time
#通过inline if来控制speed的范围
speed = speed if abs(speed)<=100 else math.copysign(100,speed)
#组合显示信息
display_str = "Speed:\t {0:.2f}m/s Accel:\t{1:.0f}m/s^2".format(speed,accel)
#通过write写入stdout
sys.stdout.write(erase_str+display_str)
#通过控制线程睡眠时间避免跑得过快抢占系统资源
time.sleep(output_task_sleep_time)
#定义主函数
def main():
#设定获取全局变量
#全局变量可被跨线程访问
global program_running_flag
#通过改变flag状态确保所有线程能运行
program_running_flag = True
#设置输入线程任务目标
input_thread = threading.Thread(target=input_task)
#启动输入线程
input_thread.start()
#设置输出线程任务目标
output_thread = threading.Thread(target=output_task)
#启动输出线程
output_thread.start()
#等待输入输出线程正常退出
input_thread.join()
output_thread.join()
#启动main函数
main()