基于ActionScript3.0的DoodleJump 游戏实现

基于ActionScript3.0的DoodleJump 游戏实现

<附加>:
分工:  王钊:游戏整体设计
      陈旻:算法细节实现

1.流程图:


2.UML图:


3.为了游戏性和稳定性:

<1>砖块的设置:游戏由初级阶段到高级阶段砖块数量由多到少。但必须通过算法保证始终有可踩的砖块出现。

<2>游戏中主角Doodle使用代码绘制,而不是直接贴图。

<3>游戏主循环选择合适的刷新频率,使得即能准确地进行碰撞判断,又尽可能降低系统开销。

4.游戏运行效果:




5.apk下载地址:http://pan.baidu.com/s/1i33kdCD

6.实现代码如下:

/**
 * 游戏主类
 */

import flash.desktop.NativeApplication;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.StageDisplayState;
import flash.display.StageScaleMode;
import flash.events.AccelerometerEvent;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.net.URLRequest;
import flash.sensors.Accelerometer;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.ui.Keyboard;
import flash.utils.Dictionary;
import flash.utils.Timer;
/**
 * ...
 * @author wangzhao
 */
[SWF(width=320,height=480,framerate=60)]//设置屏幕大小,帧率
public class DoodleJump extends Sprite
{
public static var stageWidth:Number;
public static var stageHeight:Number;
public static const S:Number = 20 * 20 / 2;
public static const V0:Number = -20;
 
public static const GRAVITY:Number = 1;
private var doodle:Doodle;//跳跃的doodle对象
private var time:Number;
private var keyDictionary:Dictionary;
private var score:int;//分数
private var scoreText:TextField
private var sceneLayer:Sprite;
private var charLayer:Sprite;
private var uiLayer:Sprite;
private var bgLayer:Sprite;
private var normalStickArr:Vector.<NormalStick>;
private var stageStickArr:Vector.<Stick>;
/**
 * 会左右平移的砖块
 */
private var movingStickArr:Vector.<MovingStick>;
/**
 * 碰了会碎但是还会起跳一次的砖块
 */
private var brokenStickArr:Vector.<BrokenStick>;
/**
 * 碰了就碎的无法起跳的砖块
 */
private var glassStickArr:Vector.<GlassStick>;//碰了就碎的无法起跳的砖块
private var textformat:TextFormat = new TextFormat();
private var picture1:Sprite = new Sprite();
private var picture2:Sprite = new Sprite();
private var picture3:Sprite = new Sprite();
private var picture4:Sprite = new Sprite();
private var picture5:Sprite = new Sprite();
private var picture6:Sprite = new Sprite();
private var jiluSprite:Sprite;
private var jiluText:TextField = new TextField();
private var startGameText:TextField = new TextField();
private var aboutGameText:TextField = new TextField();
private var exitGameText:TextField = new TextField();
private var returnMenu1:TextField = new TextField();
private var returnMenu2:TextField = new TextField();
private var returnMenu3:TextField = new TextField();
private var replayGame:TextField = new TextField();
private var loader1:Loader = new Loader();
private var loader2:Loader = new Loader();
private var loader3:Loader = new Loader();
private var loader4:Loader = new Loader();
private var loader5:Loader = new Loader();
private var loader6:Loader = new Loader();
private var urlre:URLRequest;
/**
 * 分数记录类
 */
private var cookie:Cookie = new Cookie("jilu");
public function DoodleJump():void
{
if (stage)
init();
else
addEventListener(Event.ADDED_TO_STAGE, init);
}
/**
 * 初始化函数,加载开始界面,开始游戏图片,开始游戏文字,游戏介绍图片,游戏介绍文字等等设置舞台长宽。
 */
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
stageWidth = stage.stageWidth;
stageHeight = stage.stageHeight;
stage.scaleMode = StageScaleMode.EXACT_FIT;
stage.displayState = StageDisplayState.FULL_SCREEN;
stage.autoOrients = false;
textformat.size = 19;
textformat.font = "Arial";
textformat.color = 0x123456;
loader1.load(new URLRequest("res/picture1.png"));
picture1.addChild(loader1);
loader2.load(new URLRequest("res/picture2.png"));
picture2.addChild(loader2);
loader3.load(new URLRequest("res/picture3.png"));
picture3.addChild(loader3);
loader4.load(new URLRequest("res/picture4.png"));
picture4.addChild(loader4);
loader5.load(new URLRequest("res/picture5.png"));
picture5.addChild(loader5);
loader6.load(new URLRequest("res/picture6.png"));
picture6.addChild(loader6);
//jiluText.border = true;
//startGameText.border = true;
//exitGameText.border = true;
//aboutGameText.border = true;
//returnMenu1.border = true;
//returnMenu2.border = true;
//returnMenu3.border = true;
//replayGame.border = true;
jiluText.selectable = false;
startGameText.selectable = false;
exitGameText.selectable = false;
aboutGameText.selectable = false;
returnMenu1.selectable = false;
returnMenu2.selectable = false;
returnMenu3.selectable = false;
replayGame.selectable = false;
jiluText.width = 90;
jiluText.height = 35;
jiluText.x = 120;
jiluText.y = 302;
startGameText.width = 80;
startGameText.height = 35;
startGameText.x = 120;
startGameText.y = 155;
exitGameText.width = 60;
exitGameText.height = 35;
exitGameText.x = 133;
exitGameText.y = 378;
aboutGameText.width = 90;
aboutGameText.height = 35;
aboutGameText.x = 120;
aboutGameText.y = 227;
returnMenu1.width = 120;
returnMenu1.height = 45;
returnMenu1.x = 100;
returnMenu1.y = 75;
returnMenu2.width = 120;
returnMenu2.height = 45;
returnMenu2.x = 110;
returnMenu2.y = 355;
returnMenu3.width = 120;
returnMenu3.height = 45;
returnMenu3.x = 95;
returnMenu3.y = 83;
replayGame.width = 120;
replayGame.height =45;
replayGame.x = 105;
replayGame.y = 260;
picture2.addChild(startGameText);
picture2.addChild(aboutGameText);
picture2.addChild(jiluText);
picture2.addChild(exitGameText);
picture3.addChild(returnMenu1);
picture5.addChild(returnMenu2);
picture5.addChild(replayGame);
picture6.addChild(returnMenu3);
initSence();
}
/**
 * 显示第一个场景,并添加对应开始游戏,介绍游戏,结束游戏的点击事件监听。
 */
private function initSence():void {
this.addChild(picture2);
startGameText.addEventListener(MouseEvent.CLICK,startGameClick);
aboutGameText.addEventListener(MouseEvent.CLICK,aboutGame);
jiluText.addEventListener(MouseEvent.CLICK,jilu);
exitGameText.addEventListener(MouseEvent.CLICK,exitGame);
}
protected function startGameClick(event:MouseEvent):void
{
removeSence();
startGame();
}
private function removeSence():void {
this.removeChild(picture2);
startGameText.removeEventListener(MouseEvent.CLICK,startGameClick);
aboutGameText.removeEventListener(MouseEvent.CLICK,aboutGame);
jiluText.removeEventListener(MouseEvent.CLICK,jilu);
exitGameText.removeEventListener(MouseEvent.CLICK,exitGame);
}
/**
 * 退出游戏
 */
protected function exitGame(event:MouseEvent):void
{
NativeApplication.nativeApplication.exit();
}
/**
 * 游戏介绍
 */
protected function aboutGame(event:MouseEvent):void
{
removeSence();
this.addChild(picture1);
this.addChild(picture3);
returnMenu1.addEventListener(MouseEvent.CLICK,returnMenu1Click);
}
protected function returnMenu1Click(event:MouseEvent):void
{
this.removeChild(picture1);
this.removeChild(picture3);
returnMenu1.removeEventListener(MouseEvent.CLICK,returnMenu1Click);
initSence();
}
/**
 * 游戏数据存储
 */
protected function jilu(event:MouseEvent):void
{
removeSence();
this.addChild(picture1);
this.addChild(picture6);
returnMenu3.addEventListener(MouseEvent.CLICK,returnMenu3Click);
var jilu:Array = cookie.getCookie("jilu") as Array;
if(jilu == null) {
} else {
jiluSprite = new Sprite();
for(var i:int=0; i<jilu.length; i++) {
var jilutext:TextField = new TextField();
var num:int = i+1;
jilutext.text = "第"+num+"名 "+"  :  " +jilu[i]+"分";
jilutext.setTextFormat(textformat);
jilutext.autoSize = "left";
jilutext.mouseEnabled = false;
jilutext.y = 40+i*30;
jiluSprite.addChild(jilutext);
}
picture6.addChild(jiluSprite);
jiluSprite.x = 80;
jiluSprite.y = 130;
}
}
protected function returnMenu3Click(event:MouseEvent):void
{
this.removeChild(picture1);
this.removeChild(picture6);
picture6.removeChild(jiluSprite);
jiluSprite = null;
returnMenu3.removeEventListener(MouseEvent.CLICK,returnMenu3Click);
initSence();
}
/**
 * 游戏开始函数添加对应的UI,以及初始化各个vector存放游戏中的各类砖块对象。
 * 初始化分数记录
 */
private function startGame():void
{
this.addChild(picture4);
addChild(sceneLayer = new Sprite());
addChild(charLayer = new Sprite());
addChild(uiLayer = new Sprite());
keyDictionary = new Dictionary();
normalStickArr = new Vector.<NormalStick>;
movingStickArr = new Vector.<MovingStick>;
brokenStickArr = new Vector.<BrokenStick>;
glassStickArr = new Vector.<GlassStick>;
doodle = new Doodle();
scoreText = new TextField;
uiLayer.addChild(scoreText);
score = 0;
time = 0;
doodle.vVelocity = 0;
doodle.hVelocity = 0;
charLayer.addChild(doodle);
doodle.x = stage.stageWidth / 2;
doodle.y = stage.stageHeight - 100;
stageStickArr = new Vector.<Stick>;
stageStickArr.push(new NormalStick());
sceneLayer.addChild(stageStickArr[0]);
stageStickArr[0].x = stage.stageWidth / 2;
stageStickArr[0].y = stage.stageHeight - 30;
addEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
if(Accelerometer.isSupported) {
var myAcc:Accelerometer = new Accelerometer();
myAcc.addEventListener(AccelerometerEvent.UPDATE,onUpdata);
}
}
private function onKeyUp(e:KeyboardEvent):void
{
keyDictionary[e.keyCode] = false;
}
private function onKeyDown(e:KeyboardEvent):void
{
keyDictionary[e.keyCode] = true;
}
protected function onUpdata(event:AccelerometerEvent):void
{
doodle.hVelocity = -15*event.accelerationX;
}
/**
 * 游戏循环本体,检测主角是否下落,砖块平移,以及当主角起跳时所有物体向下移动。
 */
private function onEnterFrame(e:Event):void
{
time += 1 / stage.frameRate;
//move control
if (keyDictionary[Keyboard.LEFT])
doodle.hVelocity -= 4;
if (keyDictionary[Keyboard.RIGHT])
doodle.hVelocity += 4;
//moving visual
doodle.x += doodle.hVelocity;
if (doodle.y <= stage.stageHeight - S - 35 && doodle.vVelocity < 0)
{
for each (var stick:Stick in stageStickArr)
stick.y -= doodle.vVelocity;
score -= doodle.vVelocity;
scoreText.text = String(score);
}
else
{
for (var i:int = 0; i < 2; i++)   //incase break through
{
if (doodle.vVelocity >= 0)
for each (stick in stageStickArr)
if (doodle.legs.hitTestObject(stick))
if (stick is BrokenStick)
BrokenStick(stick).drop();
else
{
doodle.vVelocity = V0;
if (stick is GlassStick)
stick.y = stageHeight + 200;
}
doodle.y += doodle.vVelocity / 2;
}
}
//moving sticks  the Math.random()<0.01 drive them crazy
for each (stick in stageStickArr)
{
if (stick is MovingStick)
{
var temp:MovingStick = stick as MovingStick;
temp.x += temp.hVelocity;
if ((temp.x > stageWidth-temp.width) && temp.hVelocity > 0 || (temp.x < temp.width) && temp.hVelocity < 0 || Math.random()<0.01)
temp.hVelocity *= -1;
}
}
refreashSticks();
doodle.vVelocity += GRAVITY;
doodle.hVelocity *= 0.5;
//outside
if (doodle.x > stage.stageWidth + 25)
doodle.x -= stage.stageWidth + 25;
if (doodle.x < -25)
doodle.x += stage.stageWidth + 25;
//char direction
if (doodle.hVelocity > 0)
doodle.scaleX = -1;
else if (doodle.hVelocity < 0)
doodle.scaleX = 1;
//game over 
if(doodle.y > stage.stageHeight + 50) 
gameOver();
}
private function gameOver():void
{
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
var jilu:Array = cookie.getCookie("jilu") as Array;
if(jilu == null) {
var newjilu:Array = new Array();
newjilu.push(score);
cookie.setCookie("jilu",newjilu);
} else {
for(var i:int=0; i<jilu.length; i++) { 
if(score > jilu[i]) {
if(jilu.length < 5) {
jilu.push(100);
}
for(var k:int=jilu.length-1; k>i; k--){
jilu[k] = jilu[k-1];
}
jilu[i] = score;
break;
}
}
cookie.setCookie("jilu",jilu);
}
this.addChild(picture5);
returnMenu2.addEventListener(MouseEvent.CLICK,returnMenu2Click);
replayGame.addEventListener(MouseEvent.CLICK,replayGameClick);
}
/**
 * 重新开始游戏
 */
protected function replayGameClick(event:MouseEvent):void
{
this.removeChild(picture5);
returnMenu2.removeEventListener(MouseEvent.CLICK,returnMenu2Click);
removeChild(sceneLayer);
sceneLayer.removeChildren(0,sceneLayer.numChildren-1);
removeChild(charLayer);
charLayer.removeChild(doodle);
removeChild(uiLayer);
uiLayer.removeChild(scoreText);
startGame();
}
protected function returnMenu2Click(event:MouseEvent):void
{
this.removeChild(picture5);
returnMenu2.removeEventListener(MouseEvent.CLICK,returnMenu2Click);
removeChild(sceneLayer);
sceneLayer.removeChildren(0,sceneLayer.numChildren-1);
removeChild(charLayer);
charLayer.removeChild(doodle);
removeChild(uiLayer);
uiLayer.removeChild(scoreText);
initSence();
}
private function refreashSticks():void
{
var stick:Stick;
//add new sticks
while (stageStickArr[0].y > stage.stageHeight)
{
sceneLayer.removeChild(stageStickArr[0]);
stick = stageStickArr.shift();
if (stick is NormalStick)
normalStickArr.push(stick);
else if (stick is MovingStick)
movingStickArr.push(stick);
else if (stick is GlassStick)
glassStickArr.push(stick);
}
//remove old sticks
while (stageStickArr[stageStickArr.length - 1].y > -300)
{
stick = getNewStick();
stick.x = Math.random() * (stage.stageWidth - stick.width) + stick.width / 2;
var max:Number = -S * Math.min(1, score / 10000 + 0.5) + 10;
var min:Number = -S * Math.min(0.5, score / 10000) - 20;
stick.y = stageStickArr[stageStickArr.length - 1].y  + min + Math.random()*(max-min);
stageStickArr.push(stick);
sceneLayer.addChild(stick);
var distance:Number = stageStickArr[stageStickArr.length - 2].y - stageStickArr[stageStickArr.length - 1].y;
if (Math.random() < 0.1 && distance>60)
{
stick = new BrokenStick();
stick.x = Math.random() * (stage.stageWidth - stick.width) + stick.width / 2;
stick.y = stageStickArr[stageStickArr.length - 1].y + Math.random() * (distance-40) + 20;
stageStickArr.splice(stageStickArr.length - 1,0, stick);
sceneLayer.addChild(stick);
}
}
}
public function getNewStick():Stick
{
if (Math.random() < (score<85000?(9000-score)/10000:0.05))
{
if (normalStickArr.length)
return normalStickArr.pop();
return new NormalStick();
}
else if (Math.random() < 0.5)
{
if (movingStickArr.length)
return movingStickArr.pop();
return new MovingStick();
}
else
{
if (glassStickArr.length)
return glassStickArr.pop();
return new GlassStick();
}
}
}
}
 


/**
 * Doodle 主角类
 */

import flash.display.BlendMode;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.NetStatusEvent;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.net.SharedObject;

class Doodle extends Sprite
{
public var body:Shape;
public var legs:Shape;
public var vVelocity:Number;
public var hVelocity:Number;
private var direction:String = "left";
/**
 * 通过两个Shape绘画出游戏主角的本体。
 */
public function Doodle():void
{
body = new Shape();
legs = new Shape();
addChild(body);
addChild(legs);
hVelocity = 0;
hVelocity = 0;
with (body)
{
graphics.lineStyle(1);
graphics.moveTo(-25, -4);
graphics.lineTo(-15, -4);
graphics.cubicCurveTo(-10, -24, 10, -24, 15, -4);
graphics.lineTo(15, 18);
graphics.lineTo(-15, 18);
graphics.lineTo(-15, 2);
graphics.lineTo(-25, 2);
graphics.drawEllipse(-30, -5, 5, 8);
graphics.drawCircle(-10, -6, 1);
graphics.drawCircle(-4, -6, 1);
drawLine(-15, 5, 15, 5);
drawLine(-15, 10, 15, 10);
drawLine(-15, 15, 15, 15);
drawLine(-15, 5, 15, 5);
}
with (legs)
{
drawLine(-10, 18, -10, 20);
drawLine(-2, 18, -2, 20);
drawLine(4, 18, 4, 20);
drawLine(12, 18, 12, 20);
drawLine(-10, 20, -15, 20);
drawLine(-2, 20, -7, 20);
drawLine(4, 20, -1, 20);
drawLine(12, 20, 7, 20);
graphics.drawRect(-15, 18, 30, 2);
}
}
public function setDirection(direction:String):void
{
if (direction == "right")
this.scaleX = -1;
else
this.scaleX = 1;
}
private function drawLine(x1:Number, y1:Number, x2:Number, y2:Number):void
{
graphics.lineStyle(1);
graphics.moveTo(x1, y1);
graphics.lineTo(x2, y2);
}
}



/**
 * 砖块类基类
 */

class Stick extends Sprite
{
public static const STICK_WIDTH:Number = 50;
static public const STICK_HEIGHT:Number = 10;
public function Stick():void
{
}
}
 


/**
 * 普通砖块类
 */

class NormalStick extends Stick
{
public function NormalStick():void
{
graphics.lineStyle(1);
graphics.beginFill(0x6BB600);
graphics.drawRoundRect(-STICK_WIDTH / 2, -STICK_HEIGHT / 2, STICK_WIDTH, STICK_HEIGHT, 10);
graphics.endFill();
}
}
 


/**
 * 平移砖块类
 */

class MovingStick extends Stick
{
public var hVelocity:Number;
public static const SPEED_X:Number = 3.5;
public function MovingStick():void
{
graphics.lineStyle(1);
graphics.beginFill(0x0998C2);
graphics.drawRoundRect(-STICK_WIDTH / 2, -STICK_HEIGHT / 2, STICK_WIDTH, STICK_HEIGHT, 10);
graphics.endFill();
hVelocity = Math.random() > 0.5 ? SPEED_X : -SPEED_X;
}
}
 



/**
 * 可以踩一次的砖块类
 */

class BrokenStick extends Stick
{
public var leftPart:Shape = new Shape();
public var rightPart:Shape = new Shape();
private var vVelocity:Number = 0;
public function BrokenStick():void
{
graphics.lineStyle(1);
addChild(leftPart);
addChild(rightPart);
leftPart.graphics.lineStyle(1);
leftPart.graphics.beginFill(0x7C5A2C);
leftPart.graphics.drawRoundRectComplex(-STICK_WIDTH / 2, -STICK_HEIGHT / 2, 23, 10, 10, 0, 10, 0);
rightPart.graphics.lineStyle(1);
rightPart.graphics.beginFill(0x7C5A2C);
rightPart.graphics.drawRoundRectComplex(2, -5, STICK_WIDTH / 2-2, STICK_HEIGHT, 0, 10, 0, 10);
//graphics.endFill();
addEventListener(Event.REMOVED_FROM_STAGE, onRemove);
}
public function drop():void
{
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(e:Event):void
{
leftPart.y += vVelocity;
leftPart.x -= 2;
rightPart.y += vVelocity;
rightPart.x += 2;
vVelocity += DoodleJump.GRAVITY;
}
private function onRemove(e:Event):void
{
removeEventListener(Event.REMOVED_FROM_STAGE, onRemove);
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
}
}
 


/**
 * 一次都不能踩的砖块
 */

class GlassStick extends Stick
{
public function GlassStick():void
{
graphics.lineStyle(1);
graphics.beginFill(0xFFFFFF);
graphics.drawRoundRect(-STICK_WIDTH / 2, -STICK_HEIGHT / 2, STICK_WIDTH, STICK_HEIGHT, 10);
graphics.endFill();
}
}
 



/**
 * 游戏数据存储类
 */

class Cookie {
private var _so:SharedObject;
/**
 *设置cookie名 ,程序会根据cookie名得到相应的sharedObject,这样可以在此cookie下面通过键值获取相应的值
 * @param cookieName_ cookie名字
 * 
 */
public function Cookie(cookieName_:String)
{
if (cookieName_ == "")
{
throw new Error("name must not be empty!!!");
}
_so = SharedObject.getLocal(cookieName_,'/');//允许级别最高
_so.addEventListener(NetStatusEvent.NET_STATUS, handler);
}
private function handler(param1:NetStatusEvent) : void
{
}
/**
 *存入cookie资源 
 * @param name_ cookie key值
 * @param value_ 欲存入的资源
 * 
 */
public function setCookie(name_:String, value_:Object) : void
{
//if(SmartSourceCacher.getInstance().isAllowSo)//防止那个无聊的面板
//{
var name:String = name_;
var value:Object = value_;
try
{
_so.data[name] = value;
_so.flush();
}catch (e:Error){
}
//}
}
/**
 *通过索引得到cookie值 
 * @param name_
 * @return 
 * 
 */
public function getCookie(name_:String) : Object
{
return _so.data[name_];
}
/**
 *清理cookie,若不传入参数,则为深度清理,清理所有cookie资源 
 * @param name_
 * 
 */
public function clear(name_:String = "") : void
{
if (name_)
{
_so.data[name_] = "";
}else{
_so.clear();
}
}
/**
 *是否包含该索引的cookie资源 
 * @param name_
 * @return 
 * 
 */
public function contains(name_:String):Boolean{
return (_so.data[name_]);
}
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值