Browsed by
月份:2011年1月

键盘事件

键盘事件

在我们做游戏时,常常会用到用键盘事件来控制人物移动的情况,如果直接用(KeyboardEvent.KEY_DOWN)和(KeyboardEvent.KEY_UP)的话,往往会出现这样或那样的问题,不知道大家都是怎么解决的? 

用键盘事件来控制人物移动,最常见的问题是: 

1.如果用户按住一个键不释放,如何处理?比如长按向右键的话,会一直运行右键触发的函数! 

2.如果用户同时按住多个方向键,如何处理?比如同时按住向右和向上,在前进过程中跳跃;用户还可能中间松开其中一个键等! 

这些问题不解决好的话,有可能会造成电脑CPU飙升,严重拖慢系统运行速度,swf 的画面会变得非常卡。 

我的思路是 当键盘按下的时候触发一个变量,可能首先大家会想到用布尔值(Boolean),按下为true,释放为false,没错,最初我也用的是布尔值,当用户长按某个键不松时,只是让系统在刷一个布尔值,这样会大大降低程序的运行成本。但是后来我发现用Int的0和1来表示按下和释放两种状态效果更佳,因为0和1这两个数值的本身还可以做为人物移动的坐标系数,这样右进一步简化代码! 

最近在学Flash Builder,所以这次的案例是在Flash Builder下写的,用的时Flex3.5的框架,写的时候尽量运行一些架构的思想,就是尽量把视图层、数据层和控制层分开,特意又画了下UML图给大家贴出来! 

键盘事件的UML图
键盘事件的UML图

图比较简单,这次主要说的是键盘事件,这些东西顺带说一下,MoveMain是主类,NPCView是视图类,KeyLogic是进行逻辑判断的控制类,GameModel是数据类, NPCVO声明了一些变量。 

下面开始贴案例效果: 

 

说明:先用鼠标在下面的swf上点下,获取焦点,然后用上下左右方向键控制npc的移动! 

接下来是代码: 

//  代码看不懂的地方可以跳过,只要看懂其中的大意,明白思路就好了! 

MoveMain(主类): 


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="600" height="400"
applicationComplete="application1_applicationCompleteHandler(event)" xmlns:vo="com.nestor.vo.*" xmlns:view="com.nestor.view.*" >
<mx:Script>
<![CDATA[
import com.nestor.ctrl.KeyLogic;
import com.nestor.model.GameModel;
import com.nestor.vo.NPCVO;
import mx.events.FlexEvent;
private var keyLogic:KeyLogic=new KeyLogic();
private var playerVo:NPCVO=GameModel.getGameModel().playerVO;
protected function application1_applicationCompleteHandler(event:FlexEvent):void
{
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyLogic.downHandler);
stage.addEventListener(KeyboardEvent.KEY_UP,keyLogic.upHandler);
var timer:Timer=new Timer(30);
timer.addEventListener(TimerEvent.TIMER,tHandler)
timer.start();
}
private function tHandler(e:TimerEvent):void{
var spdX:int=5;
var spdY:int=5;
Npc.x += (playerVo.isLeft * (-spdX) + playerVo.isRight * spdX);
Npc.y += (playerVo.isUp * (-spdY) + playerVo.isDown * spdY);
}
]]>
</mx:Script>
<view:NPCView id="Npc" x="100" y="100"/>
</mx:Application>
 

NPCView类:(视图类)

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="100" height="100">
<mx:Button  label="NPC" width="100" height="100" fontSize="32" fontFamily="Georgia"/>
</mx:Canvas>
 

KeyLogic类(逻辑控制类) 


package com.nestor.ctrl
{
/*
* @ Nestor/斯樵
*/
import com.nestor.model.GameModel;
import com.nestor.vo.NPCVO;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
public class KeyLogic
{
private var playerVo:NPCVO=GameModel.getGameModel().playerVO;
public function KeyLogic()
{
}
public function downHandler(e:KeyboardEvent):void{
switch (e.keyCode){
case Keyboard.UP:
playerVo.isUp=1;
break;
case Keyboard.DOWN:
playerVo.isDown=1;
break;
case Keyboard.LEFT:
playerVo.isLeft=1;
break;
case Keyboard.RIGHT:
playerVo.isRight=1;
break;
}
}
public function upHandler(e:KeyboardEvent):void{
switch (e.keyCode){
case Keyboard.UP:
playerVo.isUp=0;
break;
case Keyboard.DOWN:
playerVo.isDown=0;
break;
case Keyboard.LEFT:
playerVo.isLeft=0;
break;
case Keyboard.RIGHT:
playerVo.isRight=0;
break;
}
}
}
}
 

GameModel类(数据类) 


package com.nestor.model
{
import com.nestor.vo.NPCVO;
public class GameModel
{
public var playerVO:NPCVO;
public var CrtLabel:String;
private static var instance:GameModel=null;
public function GameModel()
{
playerVO=new NPCVO();
}
public static function getGameModel():GameModel{
return instance ||= new GameModel();
}
}
}
 

NPCVO类(声明Model中数据) 


package com.nestor.vo
{
public class NPCVO
{
public var isLeft:int=0;
public var isRight:int=0;
public var isUp:int=0;
public var isDown:int=0;
public function NPCVO()
{
}
}
}

源码下载:

[download id=”2″]

也说AS3自定义事件

也说AS3自定义事件

看到网上有很多关于AS3自定义事件的文章,写的或简洁到不知所云,或复杂到云山雾罩,大多属于懂的人不用看,不懂的人看不懂。不禁想起前端时间刚接触自定义事件时的纠结,看了几篇相关的文章后,也明白作者的意思,结合自己工作中的一些想法,于是就也写篇文章说说自己的理解,凑凑热闹!

自我感觉自定义事件并不太难,主要还是得理解自定义事件的意义,明白自定义事件有什么用处,懂得自定义事件用在什么地方。

下面就结合我最近做一个小游戏时用到自定义事件的情况介绍下用法。

思路:通过抛出自定义事件,改变当前游戏状态! 由MainView来管理GameStartView、GamingView和GameEndView三个游戏状态,每个状态有一个按钮,点击后,抛出自定义事件,MainView侦听到事件后,根据参数改变游戏状态;自定义事件类MyGameEvent继承于Event,含有一个nextStatus的属性。

UML图:

代码方面列出最关键的类:MyGameEvent类。

[codesyntax lang=”actionscript3″ container=”pre”]

package com.nestor.event
{
import flash.events.Event;

	public class MyGameEvent extends Event
		{
		// 默认事件类型
		public static const Status_Change:String = "MyGameEvent.Status_Change";
		// 下一游戏状态;
		public var nextStatus:String;
		public function MyGameEvent(type:String=Status_Change, bubbles:Boolean=false, cancelable:Boolean=false)
		{
			super(type, bubbles, cancelable);
		}
		public function clone():MyGameEvent {
			return new MyGameEvent (type, bubbles, cancelable);
		}
	}
}

[/codesyntax]

 

 

源码下载:

[download id=”3″]

像素级移动(SetPixel)

像素级移动(SetPixel)

常规的建个元件,做段时间轴动画,或者加上一些缓动代码,都可以实现移动的效果,这个是flash的入门知识。

今天要说的是,像素级的运动,通过BitmapData 的 setPixel和copyPixel 方法,改变位图的数据源,实现运动的效果,这个方法在项目实际运用中会大大提高系统的效率。

效果展示:

思路:注册Enter_Frame事件,每次通过 setPixel 刷新 位图BMP的 数据源BMD,形成动画的效果!

源码如下:


/*
by Nestor/斯樵
sqstudio.com
*/
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
[SWF(width="600",height="300",frameRate="30")]
public class setpixel extends Sprite
{
private var bmd:BitmapData,bm:Bitmap
private var id:int=1
public function setpixel()
{
bmd=new BitmapData(800,600,true,0)
bm=new Bitmap(bmd)
addChild(bm)
addEventListener(Event.ENTER_FRAME,efHandler)
}
private function efHandler(e:Event):void{
bmd=new BitmapData(800,600,false,0x000000)
bm.bitmapData=bmd
bmd.lock();
for(var i:int=stage.stageHeight/2-5;i<5+stage.stageHeight/2;i++){
for (var j:int=id;j< 10 +id ;j++){ bmd.setPixel(j,i,0xffffff) } } bmd.unlock(); id +=10; if(id>stage.stageWidth){
id=0;
}
}
}
}

下载地址:千脑网盘

有问题,欢迎留言讨论!