Flash/Flex学习笔记(17):按键捕获

先来看简单的单个按键捕获:

package {
	import flash.display.Sprite;
	import fl.controls.Label;
	import flash.events.KeyboardEvent;
	import flash.ui.Keyboard;

	public class KeyDown extends Sprite {

		private var lbl:Label;
		private var ball:Sprite;		

		public function KeyDown():void {
			init();
		}

		private function init():void {
			stage.focus=this;//N多资料上说要先设置焦点,但是在实际测试中,发现不加这一行,好象也能处理键盘事件?
			
			lbl = new Label();
			lbl.text="请按键,这里将显示您的按键值,按方向键可以移动小球";
			lbl.autoSize="center";
			addChild(lbl);
			lbl.width=stage.stageWidth;
			lbl.height=20;
			lbl.move(0,10);

			ball = new Sprite();
			addChild(ball);
			
			//画小球 
			ball.graphics.beginFill(0xff0000);
			ball.graphics.drawCircle(0,0,30);
			ball.graphics.endFill();
			
			//定位到舞台中心
			ball.x=stage.stageWidth/2;
			ball.y=stage.stageHeight/2;

			stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyDownHandler);			
		}

		public function KeyDownHandler(e:KeyboardEvent):void {
			lbl.text="您的按键值是:"+e.keyCode.toString()+";按键是:"+String.fromCharCode(e.keyCode);
			switch (e.keyCode) {
				case Keyboard.UP :
					ball.y-=10;
					break;
				case Keyboard.DOWN :
					ball.y+=10;
					break;
				case Keyboard.LEFT :
					ball.x-=10;
					break;
				case Keyboard.RIGHT :
					ball.x+=10;
				default :
					break;
			}

			if (e.ctrlKey) {
				lbl.text="您按下了Ctrl键!";
			}
			if (e.shiftKey) {
				lbl.text="您按下了Shift键!";
			}
			//注:实际上,在很多浏览器,包括flash播放器里,Alt都是默认用做菜单激活键的,所以Alt键会被他们拦截,从而导致Flash无法捕获
			if (e.altKey) {
				lbl.text="您按下了Alt键!";
			}
		}
	}
}

再来看下类似: A + B + C 的这种组合键捕获:

先分析一下过程,比如用户按下Ctrl + A 时,实际上是先按下Ctrl键,同时触发KeyDown事件,然后在Ctrl不放的同时,再按下A键,再次触发KeyDown事件,然后松开(触发KeyUp事件),这是一个顺序的过程。

思路:在用户按下键且尚未松开任何键时,可以考虑用一个数据,把本次按下的所有的键值都存储起来,然后等待用户松开,一旦松开,就可以认为本次组合键 输入完成,这时再清空数据,准备下次使用,这样数组中保存的就是用户按下的组合键。

按这个思路把上面的代码改进一下:

package {
	import flash.display.Sprite;
	import fl.controls.Label;
	import flash.events.KeyboardEvent;
	import flash.ui.Keyboard;
	import flash.ui.*;

	public class KeyDown extends Sprite {

		private var lbl:Label;
		private var ball:Sprite;
		private var keyValueArr:Array;//捕获组合键时,用来存放本次(在未触KeyUp事件前)所有按下的所有键值
		private var keyNameArr:Array;//按键值对应的字符

		public function KeyDown():void {
			init();
		}

		private function init():void {
			stage.focus=this;//N多资料上说要先设置焦点,但是在实际测试中,发现不加这一行,好象也能处理键盘事件?

			lbl = new Label();
			lbl.text="请按键(支持Ctrl,Shift组合键),这里将显示您的按键值,按方向键可以移动小球";
			lbl.autoSize="center";
			addChild(lbl);
			lbl.width=stage.stageWidth;
			lbl.height=20;
			lbl.move(0,10);

			ball = new Sprite();
			addChild(ball);

			//画小球 
			ball.graphics.beginFill(0xff0000);
			ball.graphics.drawCircle(0,0,30);
			ball.graphics.endFill();

			//定位到舞台中心
			ball.x=stage.stageWidth/2;
			ball.y=stage.stageHeight/2;

			stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyDownHandler);
			stage.addEventListener(KeyboardEvent.KEY_UP,KeyUpHandler);

			keyValueArr = new Array();
			keyNameArr = new Array();
		}

		public function KeyDownHandler(e:KeyboardEvent):void {
			//注:既然Alt总是被浏览器或播放器菜单栏 拦截,干脆就不检测了
			if (!(e.keyCode==Keyboard.SHIFT||e.keyCode==Keyboard.CONTROL)) {
				keyValueArr.push(e.keyCode);
				keyNameArr.push(String.fromCharCode(e.keyCode));
			}

			lbl.text="您的按键值是:" + e.keyCode.toString()+";按键是:" + String.fromCharCode(e.keyCode);
			switch (e.keyCode) {
				case Keyboard.UP :
					ball.y-=10;
					break;
				case Keyboard.DOWN :
					ball.y+=10;
					break;
				case Keyboard.LEFT :
					ball.x-=10;
					break;
				case Keyboard.RIGHT :
					ball.x+=10;
				default :
					break;
			}

			if (e.ctrlKey) {
				if (keyValueArr.length>0) {
					lbl.text="您按下了Ctrl + "+keyNameArr.join(',');
				}
			}
			if (e.shiftKey) {
				if (keyValueArr.length>0) {
					lbl.text="您按下了Shift + "+keyNameArr.join(',');
				}
			}		

		}

		public function KeyUpHandler(e:KeyboardEvent):void {
			keyValueArr.length=0;
			keyNameArr.length=0;
		}
	}
}

最后再来看看所谓的"八方向"移动:很多小游戏都可以用方向键控制人物的移动方向,上面的示例中,只能沿水平垂直四个方向移动,如果要做到8方向移动,就要用到组合键,仍然在上面的代码基本上做些修改:

package {
	import flash.display.Sprite;
	import fl.controls.Label;
	import flash.events.KeyboardEvent;
	import flash.ui.Keyboard;
	import flash.ui.*;

	public class KeyDown extends Sprite {

		private var lbl:Label;
		private var ball:Sprite;
		private var keyValueArr:Array;//捕获组合键时,用来存放本次(在未触KeyUp事件前)所有按下的所有键值
		private var keyNameArr:Array;//按键值对应的字符

		public function KeyDown():void {
			init();
		}

		private function init():void {
			stage.focus=this;//N多资料上说要先设置焦点,但是在实际测试中,发现不加这一行,好象也能处理键盘事件?

			lbl = new Label();
			lbl.text="请按键(支持Ctrl,Shift组合键),这里将显示您的按键值,按方向键可以移动小球(支持8方向)";
			lbl.autoSize="center";
			addChild(lbl);
			lbl.width=stage.stageWidth;
			lbl.height=20;
			lbl.move(0,10);

			ball = new Sprite();
			addChild(ball);

			//画小球 
			ball.graphics.beginFill(0xff0000);
			ball.graphics.drawCircle(0,0,30);
			ball.graphics.endFill();

			//定位到舞台中心
			ball.x=stage.stageWidth/2;
			ball.y=stage.stageHeight/2;

			stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyDownHandler);
			stage.addEventListener(KeyboardEvent.KEY_UP,KeyUpHandler);

			keyValueArr = new Array();
			keyNameArr = new Array();
		}

		public function KeyDownHandler(e:KeyboardEvent):void {
			//注:既然Alt总是被浏览器或播放器菜单栏 拦截,干脆就不检测了
			if (!(e.keyCode==Keyboard.SHIFT||e.keyCode==Keyboard.CONTROL)) {
				if (keyValueArr.indexOf(e.keyCode)==-1) {
					keyValueArr.push(e.keyCode);
					keyNameArr.push(String.fromCharCode(e.keyCode));
				}
			}

			lbl.text="您的按键值是:"+ keyValueArr.join(',') +";按键是:" + keyNameArr.join(',');

			//单方向移动
			if (keyValueArr.length==1) {
				switch (e.keyCode) {
					case Keyboard.UP :
						ball.y-=10;
						break;
					case Keyboard.DOWN :
						ball.y+=10;
						break;
					case Keyboard.LEFT :
						ball.x-=10;
						break;
					case Keyboard.RIGHT :
						ball.x+=10;
					default :
						break;
				}
			} else if (keyValueArr.length>1) {
				//trace(keyValueArr.join(','));				
				if (keyValueArr.indexOf(Keyboard.UP)!=-1 && keyValueArr.indexOf(Keyboard.LEFT)!=-1) {		
					//左上
					ball.x -= 10;
					ball.y -= 10;
				} else if (keyValueArr.indexOf(Keyboard.UP)!=-1 && keyValueArr.indexOf(Keyboard.RIGHT)!=-1) {
					//右上
					ball.x += 10;
					ball.y -= 10;
				}
				else if (keyValueArr.indexOf(Keyboard.DOWN)!=-1 && keyValueArr.indexOf(Keyboard.RIGHT)!=-1) {
					//右下
					ball.x += 10;
					ball.y += 10;
				}
				else if (keyValueArr.indexOf(Keyboard.DOWN)!=-1 && keyValueArr.indexOf(Keyboard.LEFT)!=-1) {
					//左下
					ball.x -= 10;
					ball.y += 10;
				}
			}

			if (e.ctrlKey) {
				if (keyValueArr.length>0) {
					lbl.text="您按下了Ctrl + "+keyNameArr.join(',');
				}
			}
			if (e.shiftKey) {
				if (keyValueArr.length>0) {
					lbl.text="您按下了Shift + "+keyNameArr.join(',');
				}
			}

		}

		public function KeyUpHandler(e:KeyboardEvent):void {
			keyValueArr.length=0;
			keyNameArr.length=0;
		}
	}
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏全栈架构

看微信小程序 wx.canvasToTempFilePath 方法之巨坑的解决之道

当然这个项目是可以用的,但是生成不了图片,打开 tempFilePath直接报错,发现了什么原因了吗?

33410
来自专栏木宛城主

ASP.NET MVC使用Bootstrap系列(3)——使用Bootstrap 组件

Bootstrap为我们提供了十几种的可复用组件,包括字体图标、下拉菜单、导航、警告框、弹出框、输入框组等。在你的Web Application中使用这些组件...

733100
来自专栏前端小叙

父组件中vuex方法更新state,子组件不能及时更新并渲染的解决方法

33340
来自专栏散尽浮华

MongoDB副本(一主一备+仲裁)环境部署记录

MongoDB复制集是一个带有故障转移的主从集群。是从现有的主从模式演变而来,增加了自动故障转移和节点成员自动恢复。 MongoDB复制集模式中没有固定的主结点...

554100
来自专栏猿人谷

Cocoa编程中视图控制器与视图类详解

iPhone编程规则是:一个窗口,多个视图。UIView是iPhone屏幕上很多控件的基础类。每个iPhone用户界面都是由显示在UIWindow(这其实也是个...

25550
来自专栏Golang语言社区

golang简单tls协议用法完整示例

本文实例讲述了golang简单tls协议用法。分享给大家供大家参考,具体如下: 生成私钥: openssl genrsa -out key.pem 2048 生...

38170
来自专栏macOS 开发学习

Mac开发跬步积累(二):NSViewController 转场动画精耕细作

在macOS 10.10之后,关于NSViewController,苹果公司专门在一个extension中提供了四个方法用来处理控制器之间的关系以及切换转场处理...

25140
来自专栏乐沙弥的世界

MongoDB 复制集节点增加移除及节点属性配置

有关MongoDB复制集概念及其搭建,可以参考:MongoDB 复制集(Replica Set)

11020
来自专栏梧雨北辰的开发录

iOS屏幕旋转及其基本适配方法

前段时间抽空总结了一下iOS视频播放的基本用法,发现这其中还有一个我们无法绕过的问题,那就是播放界面的旋转与适配。的确,视频播放与游戏类型的App经常会遇到这个...

1.6K50
来自专栏非著名程序员

基础篇章:关于 React Native 之 KeyboardAvoidingView 组件的讲解

友情提示:RN学习,从最基础的开始,大家不要嫌弃太基础,会的同学请自行略过,希望不要耽误已经会的同学的宝贵时间) 看完了这个组件的名字 KeyboardAvoi...

48050

扫码关注云+社区

领取腾讯云代金券