AS3 - 简单游戏源码(移动,碰撞,道具拾取,火把照明,录像回放)
这个是一个很简单的flash游戏源码。


--- 角色元件 Player.as ---
--- 雷达元件 Radar.as ---
--- 墙壁元件 Wall.as ---
--- 火把元件 Light.as ---
--- 目标元件 Goal.as ---
4,在线试玩
1,游戏说明:
(1)鼠标按下就开始游戏,同时墙壁隐藏看不见。
(2)鼠标拖拽可以移动角色元件。
(3)右上角有个感应雷达,显示角色与墙壁的距离,越靠近墙壁会变得越小,说明越危险。
(4)火把道具可拾取,捡到后会照亮周围一定的范围,墙壁在附近的话可以照出来。(光线忽明忽暗模拟火把光线,光线被墙挡住还有阴影)
(5)碰到墙壁或到达终点则游戏结束,同时会播放录像
2,游戏界面


3,游戏源码
--- 主应用 Main.as ---
package { import flash.display.GradientType; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.geom.Matrix; import flash.geom.Point; [SWF(backgroundColor="#000000", frameRate="40", width="650", height="270")] public class Main extends Sprite { // 玩家角色元件 private var player:Player=new Player(); // 鼠标实际的位置 private var mousePoint:Point; // 墙壁元件 private var wall:Wall=new Wall(); // 雷达元件(显示离墙的距离) private var radar:Radar=new Radar(); // 火把元件 private var light:Light=new Light(); // 目标元件 private var goal:Goal=new Goal(); // 火把画布(用来绘制火把光纤的) private var lightCanvas:Sprite=new Sprite(); // 是否获得火把 private var hasLight:Boolean=false; // 保存所有的鼠标移动轨迹 private var mouseVector:Vector.=new Vector. (); // 是否开始录制录像(鼠标移动动作) private var recordMouse:Boolean=false; // 是否开始播放录像(鼠标移动动作) private var playMouse:Boolean=false; public function Main() { // 添加玩家角色 addChild(player); player.x=40; player.y=40; // 添加墙壁 addChild(wall); // 添加墙壁雷达 addChild(radar); radar.x=600; radar.y=40; // 添加火把 addChild(light); light.x=120; light.y=200; // 添加火把光线容器 addChild(lightCanvas); // 添加目的地 addChild(goal); goal.x=600; goal.y=200; // 添加鼠标按下监听 stage.addEventListener(MouseEvent.MOUSE_DOWN,mousePressed); // 添加帧播放响应(改变光线强弱,记录播放录像) addEventListener(Event.ENTER_FRAME,update); } private function mousePressed(e:MouseEvent):void { // 移除鼠标按下监听 stage.removeEventListener(MouseEvent.MOUSE_DOWN,mousePressed); // 添加鼠标移动和释放监听 stage.addEventListener(MouseEvent.MOUSE_MOVE,mouseMoved); stage.addEventListener(MouseEvent.MOUSE_UP,mouseReleased); // 保存鼠标位置 mousePoint=new Point(mouseX,mouseY); // 隐藏墙壁 wall.visible=false; // 开始记录运动轨迹 recordMouse=true; } private function mouseMoved(e:MouseEvent):void { var dx:Number=mouseX-mousePoint.x; var dy:Number=mouseY-mousePoint.y; // 移动角色元件相同的距离 player.x+=dx; player.y+=dy; // 保存当前鼠标的位置 mousePoint.x=mouseX; mousePoint.y=mouseY; // a couple of temporary variables var rayAngle:Number; // 精度 precision is the... precision of the radar system. I suggest a number which divides 360 var precision:Number=20; // rayStep is the number of steps in pixels the raycast performs to find an obstacle var rayStep:Number=1; // 角色距墙壁的最小距离(默认最小距离 50像素,再远雷达也显示50) var minDistance:Number=50; // looping and looking for the closest point to the player for (var i:Number=0; i<=precision; i++) { // 根据精度,算出角色元件 一圈判断点的角度 rayAngle=2*Math.PI/precision*i; // 因为角色元件的半径是16px,而我们只要找离墙最近点距离小于50px,所以范围是16~66 // the bigger rayStep, the faster and less accurate the process for (var j:Number=16; j<=66; j+=rayStep) { // 判断点是否与墙壁碰撞 if (wall.hitTestPoint(player.x+j*Math.cos(rayAngle),player.y+j*Math.sin(rayAngle),true)) { // 发现并记录该点 minDistance=Math.min(j-16,minDistance); break; } } } // 更新雷达尺寸; radar.width=minDistance; radar.height=minDistance; // 碰到墙壁则游戏结束 if (minDistance<1) { mouseVector.push(new Point(player.x,player.y)); wall.visible=true; stage.removeEventListener(MouseEvent.MOUSE_MOVE,mouseMoved); stage.removeEventListener(MouseEvent.MOUSE_UP,mouseReleased); removeChild(lightCanvas); removeChild(radar); recordMouse=false; playMouse=true; } // 如果还没拿到火把,且碰到火把则获得火把 if (! hasLight) { var playerToLightX:Number=player.x-light.x; var playerToLightY:Number=player.y-light.y; // 1024 = (16 (player radius) + 16 (light radius))^2 if (playerToLightX*playerToLightX+playerToLightY*playerToLightY<1024) { // you got light powerup!! hasLight=true; removeChild(light); } } else { // 如果捡到火把则绘制光线 lightCanvas.graphics.clear(); lightCanvas.graphics.lineStyle(0,0xffffff,0); var mtx:Matrix = new Matrix(); mtx.createGradientBox(306,306,0,player.x-158,player.y-158); // we are drawing a gradient this time; lightCanvas.graphics.beginGradientFill(GradientType.RADIAL,[0xffffff,0xffffff],[0.5,0],[0,255],mtx); precision=60; for (i=0; i<=precision; i++) { rayAngle=2*Math.PI/precision*i; for (j=16; j<=158; j+=rayStep) { if (wall.hitTestPoint(player.x+j*Math.cos(rayAngle),player.y+j*Math.sin(rayAngle),true)) { break; } } if (i==0) { // moving the graphic pen if it's the first point we find lightCanvas.graphics.moveTo(player.x+j*Math.cos(rayAngle), player.y+j*Math.sin(rayAngle)); } else { // or drawing if it's not the first point we find lightCanvas.graphics.lineTo(player.x+j*Math.cos(rayAngle), player.y+j*Math.sin(rayAngle)); } } lightCanvas.graphics.endFill(); } // 判断是否碰到终点 var playerToGoalX:Number=player.x-goal.x; var playerToGoalY:Number=player.y-goal.y; // 1296 = (16 (player radius) + 20 (goal radius))^2 if (playerToGoalX*playerToGoalX+playerToGoalY*playerToGoalY<1296) { // 到达终点 mouseVector.push(new Point(player.x,player.y)); wall.visible=true; stage.removeEventListener(MouseEvent.MOUSE_MOVE,mouseMoved); stage.removeEventListener(MouseEvent.MOUSE_UP,mouseReleased); removeChild(lightCanvas); removeChild(radar); recordMouse=false; playMouse=true; } } private function mouseReleased(e:MouseEvent):void { // 如果释放鼠标,移除鼠标移动和释放监听,添加按下监听 stage.removeEventListener(MouseEvent.MOUSE_MOVE,mouseMoved); stage.removeEventListener(MouseEvent.MOUSE_UP,mouseReleased); stage.addEventListener(MouseEvent.MOUSE_DOWN,mousePressed); } private function update(e:Event):void { // 改变火把光线透明度,造成闪烁的效果 lightCanvas.alpha=0.5+Math.random()*0.5; // 记录鼠标轨迹(录像) if (recordMouse) { mouseVector.push(new Point(player.x,player.y)); } // 播放鼠标轨迹(录像) if(playMouse){ var currentPoint:Point=mouseVector.shift(); player.x=currentPoint.x; player.y=currentPoint.y; if(mouseVector.length==0){ removeEventListener(Event.ENTER_FRAME,update); } } } } }
--- 角色元件 Player.as ---
package { import flash.display.Sprite; import flash.text.TextField; import flash.text.TextFieldAutoSize; public class Player extends Sprite { public function Player() { super(); this.graphics.beginFill(0x0000ff); this.graphics.drawCircle(0,0,16); this.graphics.endFill(); var tf:TextField = new TextField; tf.autoSize = TextFieldAutoSize.LEFT; tf.htmlText = "玩家"; tf.y = - 9; tf.x = - 14; addChild(tf); } } }
--- 雷达元件 Radar.as ---
package { import flash.display.Sprite; import flash.text.TextField; import flash.text.TextFieldAutoSize; public class Radar extends Sprite { public function Radar() { super(); this.graphics.beginFill(0xff00aa); this.graphics.drawCircle(0,0,25); this.graphics.endFill(); var tf:TextField = new TextField; tf.autoSize = TextFieldAutoSize.LEFT; tf.htmlText = "雷达"; tf.y = - 9; tf.x = - 14; addChild(tf); } } }
--- 墙壁元件 Wall.as ---
package { import flash.display.Sprite; import flash.text.TextField; import flash.text.TextFieldAutoSize; public class Wall extends Sprite { public function Wall() { this.graphics.beginFill(0xffffff); this.graphics.drawRect(300,0,50,100); this.graphics.endFill(); this.graphics.beginFill(0xffffff); this.graphics.drawRect(300,150,50,100); this.graphics.endFill(); var tf1:TextField = new TextField; tf1.autoSize = TextFieldAutoSize.LEFT; tf1.text = "墙"; tf1.x = 315; tf1.y=40; addChild(tf1); } } }
--- 火把元件 Light.as ---
package { import flash.display.Sprite; import flash.text.TextField; import flash.text.TextFieldAutoSize; public class Light extends Sprite { public function Light() { super(); this.graphics.beginFill(0xff8800); this.graphics.drawCircle(0,0,16); this.graphics.endFill(); var tf:TextField = new TextField; tf.autoSize = TextFieldAutoSize.LEFT; tf.htmlText = "火把"; tf.y = - 9; tf.x = - 14; addChild(tf); } } }
--- 目标元件 Goal.as ---
package { import flash.display.Sprite; import flash.text.TextField; import flash.text.TextFieldAutoSize; public class Goal extends Sprite { public function Goal() { super(); this.graphics.beginFill(0x00aa00); this.graphics.drawCircle(0,0,20); this.graphics.endFill(); var tf:TextField = new TextField; tf.autoSize = TextFieldAutoSize.LEFT; tf.htmlText = "终点"; tf.y = - 9; tf.x = - 13; addChild(tf); } } }
4,在线试玩