展会信息港展会大全

AIR Android:编写主类Main android翻转黑白棋游戏开发
来源:互联网   发布日期:2016-01-19 12:03:46   浏览:2659次  

导读:第一个AIR Android程序:翻转黑白棋,本模块将编写一个完整的移动小游戏,并把它部署在手机上。因此,我们将亲历一个移动程序完整的诞生过程,从程序设计、代 码编写,到最后的安装。在这个过程中会涉及很多An ...

第一个AIR Android程序:翻转黑白棋,本模块将编写一个完整的移动小游戏,并把它部署在手机上。因此,我们将亲历一个移动程序完整的诞生过程,从程序设计、代 码编写,到最后的安装。在这个过程中会涉及很多Android开发的技术细节,读者也可以近距离感受AIR带来的开发乐趣。本文为大家介绍编写主类 Main。

编写主类Main

接下来编写主类Main的代码。按照之前的设计,主程序主要有以下两个功能:

创建棋盘

处理用户的交互动作

下面先来实现第一个功能。

1.创建棋盘

上一节使用了二维矩阵来描述地图数据,其实编写代码没那么复杂,直接用一个二维数组就可以实现这个功能,代码如下:

var gameMap:Array = new Array();

//每一行用一维数组来表示

gameMap[0] = [BLACK, WHITE, WHITE, BLACK];

gameMap[1] = [WHITE, BLACK, BLACK, WHITE];

gameMap[2] = [WHITE, BLACK, BLACK, WHITE];

gameMap[3] = [BLACK, WHITE, WHITE, BLACK];

BLACK和WHITE是两个常量,这样看起来更直观。利用数组,正好将地图上的信息全面展示出来,从中可以看到每个棋子的初始状态及在棋盘上的位 置,创建棋盘的工作就变得简单多了,如代码清单2-2所示。

代码清单2-2创建棋盘

column_number = 4;

var rowCount:uint = gameMap.length;

var rowArray:Array;

var i:uint, len:uint;

var grid:Grid;

//棋子的间距

var space:int = 10;

//根据数组创建棋盘

for ( var row:uint = 0; row < rowCount; row++)

{

//获取每一行的数据

rowArray = gameMap[row];

len = rowArray.length;

for ( i = 0; i < len; i++)

{

//创建Grid,并赋予初始值。GRID_RADIUS常量定义了棋子的尺寸

grid = new Grid(rowArray[i], GRID_RADIUS);

//计算出棋子在棋盘上的编号

grid.id = row * column_number + i;

//设置棋子的坐标

grid.x = i * (GRID_RADIUS*2 + space);

grid.y = row * (GRID_RADIUS*2 + space);

//将棋子放在一个容器中,方便管理

grid_container.addChild(grid);

//按照编号将棋子保存在数组中,待以后查找

grids[grid.id] = grid;

}

}

在创建棋盘时,使用数组grids保存了对所有棋子的引用,且棋子在数组中的索引和棋子在棋盘上的编号一一对应,这样在查找周边棋子时,只需要计算 出周边棋子的id即可。

棋盘创建完毕后,接下来处理用户交互动作。

2.处理用户交互动作

由于所有的棋子都被放在同一个容器中,因此可以只对容器添加监听器,而不用监听每个棋子的鼠标事件,如代码清单2-3所示。

代码清单2-3处理用户交互动作

grid_container.addEventListener(MouseEvent.CLICK, onClickHandler);

private function onClickHandler(e:MouseEvent):void

{

//由于没有其他地方监听对象的鼠标事件,因此中止冒泡事件

e.stopImmediatePropagation();

var grid:Grid = e.target as Grid;

//只有单击对象是棋子才执行后面的代码

if ( grid == null) return;

//翻转当前单击的棋子

grid.doFlip();

//翻转周围的四个棋子,用一个临时数组存放周围棋子的id

var ids:Array = new Array(grid.id - column_number, grid.id + column_number);

//如果棋子是在最左端,则左边是空的,反之左边存在棋子

if ( grid.id % column_number != 0 )

{

ids.push(grid.id - 1);

}

//如果棋子是在最右端,则右边是空的,反之右边存在棋子

if ( grid.id % column_number != (column_number-1) )

{

ids.push(grid.id + 1);

}

//记录下棋子的总数

var totalGrid:int = grids.length;

//循环数组,翻转周围棋子

for ( var i:uint = 0, len:uint = ids.length; i < len; i++)

{

var index:int = ids[i];

//上面或下面的棋子可能不存在,需要判断,如果超过数组界限,则不存在

if (index <0 || index >= totalGrid) continue;

grid = grids[index];

if ( grid != null )

{

grid.doFlip();

}

}

//处理完棋子的翻转后,最后检查当前棋子是不是都变白了

if ( isAllWhite() )

{

//game over

gameOver();

}

}

编写主类Main

在翻转周边棋子时,由于要验证棋子的真实性,代码稍显烦琐。总的说来,就是先获取上下两个棋子的id,以及左右存在的棋子的id,然后对棋子进行翻 转。

翻转完毕后,判断棋子是否全部变白的代码也很简单。代码如下:

var grid:Grid;

for ( var i:uint = 0, len:uint = grids.length; i < len; i++)

{

grid = grids[i];

//只要发现有一个棋子不是白色,则表明游戏还没有结束

if( grid.isWhite() == false )

{

//只要一个为false,则表示游戏还没有结束

}

}

}

我们的游戏只有一关,因此用户过关就意味着游戏结束。gameOver函数中,使用了一个文本框来显示提示信息,由于和程序逻辑没有联系,这里略去 不提。

至此,主程序的主要代码介绍完毕,完整的代码见代码清单2-4。

代码清单2-4FlipIt项目的Main.as文件

package

{

import flash.display.Sprite;

import flash.display.StageScaleMode;

import flash.display.StageAlign;

import flash.events.Event;

import flash.events.MouseEvent;

import flash.text.TextField;

import flash.text.TextFormat;

import flash.text.TextFormatAlign;

[SWF(backgroundColor="#B6B5C1")]

public class Main extends Sprite

{

//使用常量增强程序的灵活性和可读性

private const BLACK:Boolean = false;

private const WHITE:Boolean = true;

private const GRID_RADIUS:int = 30;

private var grid_container:Sprite;

private var game_tip:TextField;

//在数组元素的类型确定的情况下,尽量使用Vector,而不用Array,性能更佳

private var grids:Vector.<Grid> = new Vector.<Grid>();

private var column_number:uint;

public function Main():void

{

init();

}

private function init():void

{

//设置舞台属性,为了自动适应屏幕尺寸,必须设置

stage.scaleMode = StageScaleMode.NO_SCALE;

stage.align = StageAlign.TOP_LEFT;

//创建棋子容器

grid_container = new Sprite();

addChild(grid_container);

//创建文本框,用来显示游戏结果

game_tip = new TextField();

var tf:TextFormat = new TextFormat("Droid Serif", 24);

tf.align = TextFormatAlign.CENTER;

game_tip.defaultTextFormat = tf;

game_tip.width = stage.stageWidth;

game_tip.y = 500;

game_tip.selectable = false;

addChild(game_tip);

//创建棋盘

createMap();

//将棋盘屏幕居中放置

grid_container.x = (stage.stageWidth - grid_container.width) / 2;

grid_container.y = 120;

//利用事件流的冒泡机制,只监听容器的鼠标单击事件

grid_container.addEventListener(MouseEvent.CLICK, onClickHandler);

}

private function createMap():void

{

var gameMap:Array = new Array();

gameMap[0] = [BLACK, WHITE, WHITE, BLACK];

gameMap[1] = [WHITE, BLACK, BLACK, WHITE];

gameMap[2] = [WHITE, BLACK, BLACK, WHITE];

gameMap[3] = [BLACK, WHITE, WHITE, BLACK];

//列数

column_number = 4;

//总行数

var rowCount:uint = gameMap.length;

//临时变量

var rowArray:Array;

var i:uint, len:uint;

var grid:Grid;

//棋子的间距

var space:int = 10;

//根据数组创建棋盘

for ( var row:uint = 0; row < rowCount; row++)

{

//获取每一行的数据

rowArray = gameMap[row];

len = rowArray.length;

for ( i = 0; i < len; i++)

{

//创建Grid,并赋予初始值。GRID_RADIUS常量定义了棋子的尺寸

grid = new Grid(rowArray[i], GRID_RADIUS);

//计算出棋子在棋盘上的编号

grid.id = row * column_number + i;

//设置棋子的坐标

grid.x = i * (GRID_RADIUS*2 + space);

grid.y = row * (GRID_RADIUS*2 + space);

grid_container.addChild(grid);

//按照编号将棋子保存在数组中,待以后查找

grids[grid.id] = grid;

}

}

}

private function onClickHandler(e:MouseEvent):void

{

e.stopImmediatePropagation();

var grid:Grid = e.target as Grid;

//只有单击的对象是棋子才执行后面的代码

if ( grid == null) return;

//翻转当前单击的棋子

grid.doFlip();

//同时翻转周围的4个棋子

var ids:Array = new Array(grid.id - column_number, grid.id + column_number);

//如果棋子是在最左端,则左边是空的,反之左边存在棋子

if ( grid.id % column_number != 0 )

{

ids.push(grid.id - 1);

}

//如果棋子是在最右端,则右边是空的,反之右边存在棋子

if ( grid.id % column_number != (column_number-1) )

{

ids.push(grid.id + 1);

}

var totalGrid:int = grids.length;

for ( var i:uint = 0, len:uint = ids.length; i < len; i++)

{

var index:int = ids[i];

if (index <0 || index >= totalGrid) continue;

grid = grids[index];

//上面或下面的棋子可能不存在,需要判断

if ( grid != null )

{

grid.doFlip();

}

}

if ( isAllWhite() )

{

//game over

gameOver();

}

}

private function gameOver():void

{

grid_container.removeEventListener(MouseEvent.CLICK, onClickHandler);

game_tip.text = "顺利过关!";

}

private function isAllWhite():Boolean

{

var grid:Grid;

for ( var i:uint = 0, len:uint = grids.length; i < len; i++)

{

grid = grids[i];

if( grid.isWhite() == false )

{

return false;

}

}

return true;

}

}

}

编写主类Main

最后有一点要提醒读者,在主类Main的初始化过程中,设置了舞台的属性,即下面两行代码:

stage.scaleMode = StageScaleMode.NO_SCALE;

stage.align = StageAlign.TOP_LEFT;

将scaleMode设置为StageScaleMode.NO_SCALE,则舞台尺寸总是适应屏幕的尺 寸;StageAlign.TOP_LEFT表示舞台内容顶部居左对齐。这两行代码保证程序的尺寸总是适应设备的屏幕尺寸,所有界面上元素的布局和定位都 依据stage的stageWidth和stageHeight来定。比如要把棋盘在屏幕居中显示,代码如下:

grid_container.x = (stage.stageWidth - grid_container.width) / 2;

在移动设备上开发时,使用这种方式可以兼容不同尺寸的设备,在后面还有专门章节讨论这方面的内 容。

代码编写完毕后,就可以直接在计算机上测试了。在FlashDevelop中单击顶部工具条的 三角按钮,以Debug或Release模式运行程序。

小技巧利用事件流的冒泡特性来简化对可视对象的事件监听,可以减少资源开销,避免不必要的内 存泄漏,是常用的优化手法之一。

赞助本站

人工智能实验室

相关热词: 主类Main 游戏开发

AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港