小萝莉的游乐园

猜拳游戏——石头剪刀布。里面使用了LBitmapData、LBitmap、LSprite、LTextField等几个类和lufylegend库件里的鼠标事件。

一、游戏分析

游戏需要的要素:

  1. 图片描画:将石头剪刀布三张图片会知道画面上
  2. 图形绘制:背景、边框
  3. 文字绘制:统计次数的文字
  4. 鼠标点击:通过点击三个不同按钮选择出拳
  5. 电脑AI:电脑随机出拳
  6. 条件分支与判断:胜负判定结果

二、必要的Javascript知识

2.1 随机数

Math.random()函数,可以随机生成0到1之间的一个小数。如果需要随机生成5-10之间的整数,则用:
Math.floor(5 + 5*Math.random());

2.2 条件分支

if..else if..else:

if(条件1){
    条件1成立执行代码;
}else if(条件2){
    条件2成立执行代码;
}else{
    条件1、2都不成立时执行代码;
}

switch:

switch(变量){
    case 值1:
        执行代码块1
        break;    
    case 值2:
        执行代码块2
        break;
    default;
        当变量既不是值1也不是值2时执行的代码块
}

三、分层实现

层次划分:

  • 整个游戏界面一层
  • 选择出拳部分一层
  • 结果显示部分一层

3层分别显示到画面上:

init(50,"mylegend",800,400,main);

/*新建3个变量层,分别代表3个显示层*/
var backLayer,
resultLayer,
clickLayer;

function main(){
    gameInit();
}
function gameInit(){

    /*初始化层backLayer,将其作为背景层显示出来*/
    backLayer = new LSprite();    
    addChild(backLayer);

    //添加游戏界面背景
    backLayer.graphics.drawRect(10,'#008800',[0,0,LGlobal.width,LGlobal.height],true,'#000000');

    //结果显示层初始化
    initResultLayer();
    //操作层初始化
    initClickLayer();
}

/*初始化resultLayer层,将其作为结果表示层,并在层上绘制一个白色矩形,当作结果表示层的背景色*/
function initResultLayer(){
    resultLayer = new LSprite();
    resultLayer.graphics.drawRect(4,'#ff8800',[0,0,150,110],true,'#ffffff');
    resultLayer.x = 10;
    resultLayer.y = 100;
    backLayer.addChild(resultLayer);
}

/*初始化clickLayer层,并将其作为控制点击层,同时再层上绘制一个白色矩形,当作控制点击层的背景色*/
function initClickLayer(){
    clickLayer = new LSprite();
    clickLayer.graphics.drawRect(4,'#ff8800',[0,0,300,110],true,'#ffffff');
    clickLayer.x = 250;
    clickLayer.y = 275;
    backLayer.addChild(clickLayer);
}

四、各个层的基本功能

4.1 基本画面显示

将图片读取到电脑,然后按照需求显示到画面。



图片的读取,再这篇博客已经介绍过,我们这次使用lufylegend库件中另一种比较方便的图片读取方式,即静态类LLoadManage中的load函数来一次性读取多张图片:

LLoadManage.load ($list,$onupdata,$oncomplete);

$list:尧都区的图片数组
$onupdata:没读取数组中一张图片后调用的函数,可以为空
$oncomplet:读取玩数组中所有图片后调用的函数

init(50,"mylegend",800,400,main);
var loadingLayer,
backLayer,
resultLayer,
clickLayer,

/*变量imglist用来保存读取后的图片数据的数组,保存方式以key=>value的形式,key就是imgData对于的name值*/
var imglist = {};
var imgData = new Array(
        {name:"title",path:"../images/title.png"},
        {name:"shitou",path:"../images/shitou.png"},
        {name:"jiandao",path:"../images/jiandao.png"},
        {name:"bu",path:"../images/bu.png"}
        );

function main(){
    backLayer = new LSprite();    
    addChild(backLayer);

    /*加载进度条,有三种样式,这里使用样式3*/
    loadingLayer = new LoadingSample3();
    backLayer.addChild(loadingLayer);

    /*利用静态类LLoadManage的load函数来读取数组中的图片*/
    LLoadManage.load(
        imgData,
        function(progress){
            loadingLayer.setProgress(progress);
        },
        function(result){
            imglist = result;
            backLayer.removeChild(loadingLayer);
            loadingLayer = null;
            gameInit();
        }
    );
}

LLoadManage的load函数:

  • 第一个参数imgData:要读取的图片数组
  • 第二个参数function:function类型,每读取一张图片后调用的函数,其中progress指的是读完的图片数占总图片数的比例,将这个比例值通过setProgress传给LoadingSample3对象,就实现了同台的进度条
  • 第三个参数:function类型,是将读取完图片后的结果赋值给变量imglist,然后移除画面上的进度条对象,最后调用gameInit,进行游戏下一步的操作。

修改gameInit函数,添加相应变量:

init(50,"mylegend",800,400,main);

/*添加selfBitmap、enemyBitmap变量,用于显示己方的电脑的出拳结果*/
var loadingLayer,
backLayer,
resultLayer,
clickLayer,
selfBitmap,
enemyBitmap;

var imglist = {};
var imgData = new Array(
        {name:"title",path:"../images/title.png"},
        {name:"shitou",path:"../images/shitou.png"},
        {name:"jiandao",path:"../images/jiandao.png"},
        {name:"bu",path:"../images/bu.png"}
        );
var showList = new Array();
function main(){
    backLayer = new LSprite();    
    addChild(backLayer);
    loadingLayer = new LoadingSample3();
    backLayer.addChild(loadingLayer);
    LLoadManage.load(
        imgData,
        function(progress){
            loadingLayer.setProgress(progress);
        },
        function(result){
            imglist = result;
            backLayer.removeChild(loadingLayer);
            loadingLayer = null;
            gameInit();
        }
    );
}
function gameInit(){

    /*为了避免反复新建LBitmapData对象,所以将新建的LBitmapData对象添加到数组showList中。imglist是利用LLoadManage读取图片后返回的结果集。*/
    showList.push(new LBitmapData(imglist["shitou"]));
    showList.push(new LBitmapData(imglist["jiandao"]));
    showList.push(new LBitmapData(imglist["bu"]));

    //添加游戏界面背景
    backLayer.graphics.drawRect(10,'#008800',[0,0,LGlobal.width,LGlobal.height],true,'#000000');

    //显示游戏标题
    var titleBitmap = new LBitmap(new LBitmapData(imglist["title"]));
    titleBitmap.x = (LGlobal.width - titleBitmap.width)/2;
    titleBitmap.y = 10;
    backLayer.addChild(titleBitmap);
    //玩家方出拳图片
    selfBitmap = new LBitmap(showList[0]);
    selfBitmap.x = 400 - selfBitmap.width - 50;
    selfBitmap.y = 130;
    backLayer.addChild(selfBitmap);
    //电脑方出拳图片
    enemyBitmap = new LBitmap(showList[0]);
    enemyBitmap.x = 400 + 50;
    enemyBitmap.y = 130;
    backLayer.addChild(enemyBitmap);
    //玩家电脑名称设定
    var nameText;
    nameText = new LTextField();
    nameText.text = "玩家";
    nameText.weight = "bolder";
    nameText.color = "#ffffff";
    nameText.size = 24;
    nameText.x = selfBitmap.x + (selfBitmap.width - nameText.getWidth())/2;
    nameText.y = 95;
    backLayer.addChild(nameText);
    nameText = new LTextField();
    nameText.text = "电脑";
    nameText.weight = "bolder";
    nameText.color = "#ffffff";
    nameText.size = 24;
    nameText.x = enemyBitmap.x + (enemyBitmap.width - nameText.getWidth())/2;
    nameText.y = 95;
    backLayer.addChild(nameText);

    //结果显示层初始化
    initResultLayer();
    //操作层初始化
    initClickLayer();
}
function initResultLayer(){
    resultLayer = new LSprite();
    resultLayer.graphics.drawRect(4,'#ff8800',[0,0,150,110],true,'#ffffff');
    resultLayer.x = 10;
    resultLayer.y = 100;
    backLayer.addChild(resultLayer);
}
function initClickLayer(){
    clickLayer = new LSprite();
    clickLayer.graphics.drawRect(4,'#ff8800',[0,0,300,110],true,'#ffffff');
    clickLayer.x = 250;
    clickLayer.y = 275;
    backLayer.addChild(clickLayer);
}

4.2 结果层的显示

在结果层中记录审理、失败和平局等各种结果的次数

定义相应变量:

var loadingLayer,
backLayer,
resultLayer,
clickLayer,
selfBitmap,
enemyBitmap,

/*LTextField对象,用于显示各种结果值*/
selfTextAll,
selfTextWin,
selfTextLoss,
selfTextDraw,
/*次数*/
win = 0,
loss = 0,
draw = 0;

初始化几个对象,并显示到结果层:

function initResultLayer(){
    resultLayer = new LSprite();
    resultLayer.graphics.drawRect(4,'#ff8800',[0,0,150,110],true,'#ffffff');
    resultLayer.x = 10;
    resultLayer.y = 100;
    backLayer.addChild(resultLayer);
    selfTextAll = new LTextField();
    selfTextAll.text = "猜拳次数 : 0";
    selfTextAll.weight = "bolder";
    selfTextAll.x = 10;
    selfTextAll.y = 20;
    resultLayer.addChild(selfTextAll);
    selfTextWin = new LTextField();
    selfTextWin.text = "胜利次数 : 0";
    selfTextWin.weight = "bolder";
    selfTextWin.x = 10;
    selfTextWin.y = 40;
    resultLayer.addChild(selfTextWin);
    selfTextLoss = new LTextField();
    selfTextLoss.text = "失败次数 : 0";
    selfTextLoss.weight = "bolder";
    selfTextLoss.x = 10;
    selfTextLoss.y = 60;
    resultLayer.addChild(selfTextLoss);
    selfTextDraw = new LTextField();
    selfTextDraw.text = "平局次数 : 0";
    selfTextDraw.weight = "bolder";
    selfTextDraw.x = 10;
    selfTextDraw.y = 80;
    resultLayer.addChild(selfTextDraw);
}

4.3 控制层的显示

添加石头、剪刀、布三个按钮:

function initClickLayer(){
    clickLayer = new LSprite();
    clickLayer.graphics.drawRect(4,'#ff8800',[0,0,300,110],true,'#ffffff');
    var msgText = new LTextField();
    msgText.text = "请出拳:";
    msgText.weight = "bolder";
    msgText.x = 10;
    msgText.y = 10;

    /*调用getButton函数,通过传入相应参数来建立按钮*/
    clickLayer.addChild(msgText);
    var btnShitou = getButton("shitou");
    btnShitou.x = 30;
    btnShitou.y = 35;
    clickLayer.addChild(btnShitou);
    var btnJiandao = getButton("jiandao");
    btnJiandao.x = 115;
    btnJiandao.y = 35;
    clickLayer.addChild(btnJiandao);
    var btnBu = getButton("bu");
    btnBu.x = 200;
    btnBu.y = 35;
    clickLayer.addChild(btnBu);
    clickLayer.x = 250;
    clickLayer.y = 275;
    backLayer.addChild(clickLayer);
}

五、出拳

给按钮添加鼠标点击事件:

function initClickLayer(){
clickLayer = new LSprite();
clickLayer.graphics.drawRect(4,'#ff8800',[0,0,300,110],true,'#ffffff');
var msgText = new LTextField();
msgText.text = "请出拳:";
msgText.weight = "bolder";
msgText.x = 10;
msgText.y = 10;
clickLayer.addChild(msgText);

/*建立3个按钮之后,分别给按钮加上MOUSE_UP事件,当鼠标单击按钮并弹起时候,调用onclick函数*/
var btnShitou = getButton("shitou");
btnShitou.x = 30;
btnShitou.y = 35;
clickLayer.addChild(btnShitou);
btnShitou.addEventListener(LMouseEvent.MOUSE_UP,onclick);
var btnJiandao = getButton("jiandao");
btnJiandao.x = 115;
btnJiandao.y = 35;
clickLayer.addChild(btnJiandao);
btnJiandao.addEventListener(LMouseEvent.MOUSE_UP,onclick);
var btnBu = getButton("bu");
btnBu.x = 200;
btnBu.y = 35;
clickLayer.addChild(btnBu);
btnBu.addEventListener(LMouseEvent.MOUSE_UP,onclick);
clickLayer.x = 250;
clickLayer.y = 275;
backLayer.addChild(clickLayer);

}
function onclick(event,display){
    var selfValue,enemyValue;
    if(display.name == "shitou"){
        selfValue = 0;
    }else if(display.name == "jiandao"){
        selfValue = 1;
    }else if(display.name == "bu"){
        selfValue = 2;
    }
    enemyValue = Math.floor(Math.random()*3);
    selfBitmap.bitmapData = showList[selfValue];
    enemyBitmap.bitmapData = showList[enemyValue];
}

六、结果判定

为方便判断结果,我们准备一个结果判定数组:

function onclick(event,display){
    var selfValue,enemyValue;
    if(display.name == "shitou"){
        selfValue = 0;
    }else if(display.name == "jiandao"){
        selfValue = 1;
    }else if(display.name == "bu"){
        selfValue = 2;
    }
    enemyValue = Math.floor(Math.random()*3);
    selfBitmap.bitmapData = showList[selfValue];
    enemyBitmap.bitmapData = showList[enemyValue];
    var result = checkList[selfValue][enemyValue];
    if(result == -1){
        loss += 1;
    }else if(result == 1){
        win += 1;
    }else{
        draw += 1;
    }
    selfTextWin.text = "胜利次数 : " + win;
    selfTextLoss.text = "失败次数 : " + loss;
    selfTextDraw.text = "平局次数 : " +  draw;
    selfTextAll.text = "猜拳次数 : " + (win + loss + draw);
}

运行效果:

七、完整代码

init(50,"mylegend",800,400,main);
var loadingLayer,
backLayer,
resultLayer,
clickLayer,
selfBitmap,
enemyBitmap,
selfTextAll,
selfTextWin,
selfTextLoss,
selfTextDraw,
win = 0,
loss = 0,
draw = 0;
var imglist = {};
var imgData = new Array(
        {name:"title",path:"../images/title.png"},
        {name:"shitou",path:"../images/shitou.png"},
        {name:"jiandao",path:"../images/jiandao.png"},
        {name:"bu",path:"../images/bu.png"}
        );
var checkList = [
[0,1,-1],
[-1,0,1],
[1,-1,0]
];
var showList = new Array();
function main(){
    LGlobal.setDebug(true);    
    backLayer = new LSprite();    
    addChild(backLayer);
    loadingLayer = new LoadingSample3();
    backLayer.addChild(loadingLayer);    
    LLoadManage.load(
        imgData,
        function(progress){
            loadingLayer.setProgress(progress);
        },
        function(result){
            imglist = result;
            backLayer.removeChild(loadingLayer);
            loadingLayer = null;
            gameInit();
        }
    );
}
function gameInit(){
    showList.push(new LBitmapData(imglist["shitou"]));
    showList.push(new LBitmapData(imglist["jiandao"]));
    showList.push(new LBitmapData(imglist["bu"]));
    //添加游戏界面背景
    backLayer.graphics.drawRect(10,'#008800',[0,0,LGlobal.width,LGlobal.height],true,'#000000');

    //显示游戏标题
    var titleBitmap = new LBitmap(new LBitmapData(imglist["title"]));
    titleBitmap.x = (LGlobal.width - titleBitmap.width)/2;
    titleBitmap.y = 10;
    backLayer.addChild(titleBitmap);
    //玩家方出拳图片
    selfBitmap = new LBitmap(showList[0]);
    selfBitmap.x = 400 - selfBitmap.width - 50;
    selfBitmap.y = 130;
    backLayer.addChild(selfBitmap);
    //电脑方出拳图片
    enemyBitmap = new LBitmap(showList[0]);
    enemyBitmap.x = 400 + 50;
    enemyBitmap.y = 130;
    backLayer.addChild(enemyBitmap);
    //玩家电脑名称设定
    var nameText;
    nameText = new LTextField();
    nameText.text = "玩家";
    nameText.weight = "bolder";
    nameText.color = "#ffffff";
    nameText.size = 24;
    nameText.x = selfBitmap.x + (selfBitmap.width - nameText.getWidth())/2;
    nameText.y = 95;
    backLayer.addChild(nameText);
    nameText = new LTextField();
    nameText.text = "电脑";
    nameText.weight = "bolder";
    nameText.color = "#ffffff";
    nameText.size = 24;
    nameText.x = enemyBitmap.x + (enemyBitmap.width - nameText.getWidth())/2;
    nameText.y = 95;
    backLayer.addChild(nameText);

    //结果显示层初始化
    initResultLayer();
    //操作层初始化
    initClickLayer();
}
function initResultLayer(){
    resultLayer = new LSprite();
    resultLayer.graphics.drawRect(4,'#ff8800',[0,0,150,110],true,'#ffffff');
    resultLayer.x = 10;
    resultLayer.y = 100;
    backLayer.addChild(resultLayer);
    selfTextAll = new LTextField();
    selfTextAll.text = "猜拳次数 : 0";
    selfTextAll.weight = "bolder";
    selfTextAll.x = 10;
    selfTextAll.y = 20;
    resultLayer.addChild(selfTextAll);
    selfTextWin = new LTextField();
    selfTextWin.text = "胜利次数 : 0";
    selfTextWin.weight = "bolder";
    selfTextWin.x = 10;
    selfTextWin.y = 40;
    resultLayer.addChild(selfTextWin);
    selfTextLoss = new LTextField();
    selfTextLoss.text = "失败次数 : 0";
    selfTextLoss.weight = "bolder";
    selfTextLoss.x = 10;
    selfTextLoss.y = 60;
    resultLayer.addChild(selfTextLoss);
    selfTextDraw = new LTextField();
    selfTextDraw.text = "平局次数 : 0";
    selfTextDraw.weight = "bolder";
    selfTextDraw.x = 10;
    selfTextDraw.y = 80;
    resultLayer.addChild(selfTextDraw);
}
function initClickLayer(){
    clickLayer = new LSprite();
    clickLayer.graphics.drawRect(4,'#ff8800',[0,0,300,110],true,'#ffffff');
    var msgText = new LTextField();
    msgText.text = "请出拳:";
    msgText.weight = "bolder";
    msgText.x = 10;
    msgText.y = 10;
    clickLayer.addChild(msgText);
    var btnShitou = getButton("shitou");
    btnShitou.x = 30;
    btnShitou.y = 35;
    clickLayer.addChild(btnShitou);
    btnShitou.addEventListener(LMouseEvent.MOUSE_UP,onclick);
    var btnJiandao = getButton("jiandao");
    btnJiandao.x = 115;
    btnJiandao.y = 35;
    clickLayer.addChild(btnJiandao);
    btnJiandao.addEventListener(LMouseEvent.MOUSE_UP,onclick);
    var btnBu = getButton("bu");
    btnBu.x = 200;
    btnBu.y = 35;
    clickLayer.addChild(btnBu);
    btnBu.addEventListener(LMouseEvent.MOUSE_UP,onclick);
    clickLayer.x = 250;
    clickLayer.y = 275;
    backLayer.addChild(clickLayer);
}
function onclick(event,display){
    var selfValue,enemyValue;
    if(display.name == "shitou"){
        selfValue = 0;
    }else if(display.name == "jiandao"){
        selfValue = 1;
    }else if(display.name == "bu"){
        selfValue = 2;
    }
    enemyValue = Math.floor(Math.random()*3);
    selfBitmap.bitmapData = showList[selfValue];
    enemyBitmap.bitmapData = showList[enemyValue];
    var result = checkList[selfValue][enemyValue];
    if(result == -1){
        loss += 1;
    }else if(result == 1){
        win += 1;
    }else{
        draw += 1;
    }
    selfTextWin.text = "胜利次数 : " + win;
    selfTextLoss.text = "失败次数 : " + loss;
    selfTextDraw.text = "平局次数 : " +  draw;
    selfTextAll.text = "猜拳次数 : " + (win + loss + draw);
}
function getButton(value){
    var btnUp = new LBitmap(new LBitmapData(imglist[value]));
    btnUp.scaleX = 0.5;
    btnUp.scaleY = 0.5;
    var btnOver = new LBitmap(new LBitmapData(imglist[value]));
    btnOver.scaleX = 0.5;
    btnOver.scaleY = 0.5;
    btnOver.x = 2;
    btnOver.y = 2;
    var btn = new LButton(btnUp,btnOver);
    btn.name = value;
    return btn;
}