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;
		}
	}
}
时间: 2024-08-19 09:20:58

Flash/Flex学习笔记(17):按键捕获的相关文章

Flash/Flex学习笔记(5):捕获摄像头(续)--在线抓屏并保存到客户端本地

必须有摄像头上面的演示才能正常播放. 思路 使用摄像头以及在线抓屏在上一节Flash/Flex学习笔记(2)捕获摄像头 里已经讲过了就不重复粘贴了至于在客户端保存文件Flash里用起来也很简单:直接调用 FileReference 即可另外为了减少图片大小还可能借助AS3.0的扩展库项目地址http://code.google.com/p/as3corelib/把bmp格式的位置转换成jpeg再保存   扩展 结合本文的方法再配合Flash/Flex学习笔记(4)如何打开网页及Get/Post数

Flash/Flex学习笔记(2):捕获摄像头

Flash中使用摄像头个人感觉比silverlight要更容易   时间轴第一帧上敲以下代码就可以了 //import fl.controls.Label; //var camera:Camera = Camera.getCamera(); //trace(camera==null?"未检测到摄像头":"已安装了摄像头"); var W:int=stage.stageWidth;//场景的原始宽度 var H:int=stage.stageHeight;//场景的原

Flash/Flex学习笔记(6):制作基于xml数据源的flv视频播放器

今天折腾了大半天,总算搞出了一个功能简单的视频播放器,可以向公司领导交差了 :) 步骤: 1.Flash CS4 中 先拖一个"FLVPlayback"组件到舞台上 注:FLVPlayback本身已经具备了flv播放的基本功能,简单设置下属性就能播放视频了 2.加载xml数据源 xml数据源格式如下: <?xml version="1.0" encoding="utf-8"?> <data> <item flv=&q

Flash/Flex学习笔记(37):不用系统组件(纯AS3)的视频播放器--只有8.82K

以前为了赶项目,利用系统组件制作过一款视频播放器(见Flash/Flex学习笔记(6):制作基于xml数据源的flv视频播放器),但是系统组件实在是太大了,最终生成的swf居然有103K,随着AS3的深入学习,昨天又弄了一个只用AS3的播放器,最终只有8.82K,呵呵,这肥减得那是相当厉害. 用到了上一篇(Flash/Flex学习笔记(35):自己动手实现一个滑块控件(JimmySilder))里自己写的的滑块控件,主要代码如下(关键是NetConnection与NetStream对象的使用):

Flash/Flex学习笔记(57):实用技巧

布朗运动: varnumDots:uint=50; varfriction:Number=0.9; vardots:Array; varlife:uint=0; functioninit(){ graphics.lineStyle(0,0xffffff,.5); dots=newArray(); for(vari:uint=0;i<numDots;i++){ vardot:Ball=newBall(2,0x00ff00); dot.x=Math.random()*stage.stageWidth

Flash/Flex学习笔记(46):正向运动学

所谓"正向运动学"通俗点讲就是把几个连接部件的一端固定起来,另一个端可以自由(向前/向外)运动.比如人的行走,单个下肢可以理解为脚连接小腿,小腿连接大腿,大腿连接腰.行走的过程,相当于二条腿相对固定于腰部,大腿运动驱动小腿,小腿又驱动脚,从而带动整个连接系统的一系列运动. 先来一个基本的关节类Segment:(就是一个圆角矩形+二个小圆圈) package { import flash.display.Sprite; import flash.geom.Point; public cl

Flash/Flex学习笔记(24):粒子效果

粒子爆炸: 仍然要用到以前的小球类,不过稍加改造 package { import flash.display.Sprite; //小球 类 public class Ball extends Sprite { public var radius:uint;//半径 public var color:uint;//颜色 public var vx:Number=0;//x轴速度 public var vy:Number=0;//y轴速度 public function Ball(r:Number

Flash/Flex学习笔记(25):摩擦力与屏幕环绕

摩擦力: 假如一个物体在某个方向上沿直线运行,摩擦力会使该方向上的速度越来越小,直到停止. 上图示意了该过程,物体以moveAngle角度正向运动,最终的速度speed矢量为vx矢量与vy矢量的矢量和,在每个单位时间内的位移即Speed矢量的大小,分解到x,y轴后,即为vx与vy:加入摩擦力后,speed矢量每单位时间将减少Friction值,也就是视觉上的越来越慢. var ball:Ball = new Ball(10); ball.x = stage.stageWidth/2; ball.

Flash/Flex学习笔记(30):不用startDrag和stopDrag的对象拖动

对于从Sprite类继承来的对象,要实现拖放当然是Flash/Flex学习笔记(13):对象拖动(startDrag/stopDrag) 里讲的方法最方便,但是对于不是从Sprite类继承得来的对象,这startDrag/stopDrag是不能用的,这时候只能采用最通常用做法:利用Mouse_Down,Mouse_UP,Mouse_Move事件来处理 注意:对象的Mouse_Move事件,只有当鼠标在对象上时才能被监听,如果用户鼠标移动过快,超出了对象的范围,该事件就不起作用了,所以监听Mous