Silverlight游戏设计:(五)面向对象的思想塑造游戏对象(共6篇)由网友“腿总麻”投稿提供,下面就是小编给大家整理后的Silverlight游戏设计:(五)面向对象的思想塑造游戏对象,希望您能喜欢!
篇1:Silverlight游戏设计:(五)面向对象的思想塑造游戏对象
传说,面向对象的开发模式最初是因为程序员偷懒而不小心诞生的,发展至今,人们从最初的热忠于 讨论某某语言是否足够面向对象到现在开始更广泛的关注面向对象的思想而不是具体内容。面向对象的思 想其实并不深奥,它存在的目的只有一个:让程序开发更贴近我们的现实世界。
还记得猫、猫叫;狗、狗吃东西吗?无数的程序员都喜欢将此类似的情形设计当作面向对象最好的例 子。是的,非常生动且形象;但实际运用中你是否能真正做到举一反三?
回述到游戏设计中,大家是否时常会感觉游戏世界与我们的真实世界如此贴近?游戏中的精灵好比我 们人类,更广泛的,你可以将精灵看做游戏世界中任意的生命体。在现实世界里,“人”是我这样的家伙 的统称,“人”可以站立,可以移动,可以战斗,可以受伤,可以死亡;在游戏世界里,“精灵(Sprite) ”是所有生命体的统称,“精灵”同样可以站立(Stand),可以移动(MoveTo),可以战斗(Attack),可以 受伤(Injured),可以死亡(Death)。当然,梦幻般的它们或许还能施法(Casting)甚至飞行(Fly)。能够移 动,因此必须有速度(Speed)和方向(Direction);可以死亡,因此必须有它活着的证明(Life)……于是, 一个非常非常贴近我们现实生活的游戏“精灵类”出现了:
每个“人”都生活在各自的“城市”里,“城市”有路,有桥,有山,有水……多种多样的地况形成 了整个城市的立面结构;“精灵”存在于各自所处的“场景(Scene)”中,每个“场景”都拥有一张生动 的背景地图(Map)展示着美丽的风景,精灵们就是在这样铺设着坐标系(Coordinates)的“场景”里自由自 在的生活。只要高兴,它们随时都可以到不同的“场景”走亲访友或者探险旅游。因此,“场景”管理着 它内部的所有对象如“精灵”、“魔法”等,作为承载游戏各元素的重要枢纽,它有着非凡的意义:
玩家是游戏世界中的 “上帝”,他经营着游戏中所能掌控的一切;精灵去血了,升级了得报告“上帝” ;雷达发现敌情了得通知“上帝”;场景切换了,要让“上帝”看见;GameOver了 , “上帝”要知道。假如说“人”生活在城市里,而所有的人、城市又构成了整 个地球,更广义的说就是整个世界,所以,“世界”就是我们“人”所生活的舞台 。同样的,在游戏世界里的所有一切对象如“精灵”,“场景”,以及向“ 上帝”打报告的各种“面板”,它们之间要连通,要交互也同样需要这样一个平台。没 错,它就是“游戏窗口(Window)”,类似于MainPage.xaml。游戏世界中所有对象如果需要和 其他外部的对象进行交互,只需为自己添加委托事件,在“游戏窗口”中需要的地方触发这个 事件即可实现。举个最最简单的例子,“精灵”在不断的移动,移动是“精灵”与 生俱来的能力,因此它自己就可以轻松搞定:sprite.MoveTo(…),
但是,此时“上帝 ”想要通过“雷达地图面板”了解该“精灵”所处的准确位置,我们不能再 通过sprite.TellRadar(….)了,因为“雷达地图面板”是“游戏世界”的 财产而非某个“精灵”的内部资源。于是乎“精灵”想到了一个好办法,它决定每 走一步都在地上做个自己所特有的记号,从而告诉“游戏世界”:我现在在这儿了。转换成编 程语言就是定义“精灵”坐标变化事件及相应的委托:
public delegate void CoordinateEventHandler(Sprite sprite, DependencyPropertyChangedEventArgs e);
public event CoordinateEventHandler CoordinateChanged;
当“精灵”移动且坐标改变时触发(即做记号):
private static void ChangeCoordinateProperty(DependencyObject d, DependencyPropertyChangedEventArgs e) {
……
if (sprite.CoordinateChanged != null) {
sprite.CoordinateChanged(sprite, e);
}
……
}
最后,通过在“游戏窗口”中注册这个事件,一旦“精灵”坐标改变即通过“雷达地图面板”告诉“ 上帝”:
sprite.CoordinateChanged += (s, e) =>{
radar.TellGod(……);
};
由此得到,“游戏窗口”就是游戏中万物之间的交流平台,对象与对象之间的交互都在其内部完成:
到此,大家是否已能理清“精灵”,“场景”,“游戏窗口”这3个“游戏世界”中最基础且必不可少 的重要元素之间的关系了?亲爱的朋友们,请放飞思想,用现实世界的现象和原理去反向叙述机器所操控 的“游戏世界”,你定会发现其实一切都是那么的轻松而惬意。是的,这就是面向对象思想给我们带来的 福利:让程序开发更简单!
仿佛又废话了一节,保守估计又要开始有朋友给这个仍不知悔改并坚持以大无畏的精神忽悠读者的深 蓝丢鸡蛋了。其实,我写的每篇文章都有它存在的原因或价值,承上启下是外因,更重要的是我发现就算 再简单再好理解的代码都能让很多朋友望而生畏,其实并非不懂编程,我理解的是大家更多缺少的是属于 自己的思维,那种勇于创新不害怕失败的自我潜能深挖掘的精神,这才是我最终想要传达的思想,同样也 是这新一部系列教程所要阐述的Silverlight游戏设计理念。
在这样的思路的指引下,历时大半个月利用业余时间制作完成了这个Silverlight场景编辑器,可谓呕 心沥血之作。但是,至从它出现后,更多的朋友反而会这样觉得:“深蓝的作品真是一部不如一部,哎, 失败,失败中的失败。”真的是这样吗?俗话说内行人看门道,外行人看味道。懂行的一看就知道是个好 宝贝,豪不惭愧的说,它可以制作你目前所玩过的一切2D游戏的图形框架,而它的核心算法仅有两个,而 且还是我第一部教程第十节中早已提到的那两组公式;更重要的是,它的结构非常简单且代码量少,绝对 的通俗易懂。
下一节,我将开源这个场景编辑器。紧接下去后面的章节,我会向世界展示这个Silverlight-2D游戏 场景编辑器的伟大!还是不相信哪??嘿嘿,关注哦~
在线演示地址:silverfuture.cn
篇2:Flash ActionScript2.0面向对象游戏开发
对象
概述:
Flash ActionScript2.0是一种面向对向的编程语言,利用它可以开发出功能强大的应用程序.以早期的ActionScript. 1.0相比,它在结构化编程上具有明显的优势,可以使程序具有更强的可移植性,可重性,和伸缩性.
本文通过一个推箱子游戏的开发过程来逐步讲述如何利用ActionScript2.0 进行开发.
结构分析:
在进行一个项目的开发前,项目规化是必不可少的.我们先来思考一下推箱子游戏包含哪些必要的元素呢?
一个玩家(Player)
至少一个箱子(Box)
和箱子数目一样的目标地(Target)
数目不定的砖块(Brick)
砖块连在一下组成了墙壁(Wall)
一个游戏管理者(Manager)
一些显示游戏信息的控件
我们都需要将这些元素抽象化为对象(Object),各个对象包含有各自特有的属性和方法.比如,玩家具有位置属性(currentPos),它表示玩家当全的位置,玩家还有move方法,它使玩家移到下一个位置.等腰三角形这些问题搞清楚了,我们就要进行具体的实现.
实现过程:
打开Flash,新建“动作脚本文件”,依次建立如下.as文件,注意要把它们放在同一个目录下.源文件如下:
//*********Pos.as*********
//用来表示游戏中物体位置的类
//游戏中所有对象的位置都为此类的实例
//用col,row 两个量确定物体的位置
class Pos {
var col:Number;// 列值
var row:Number;// 行值
//构造函数
function Pos(c, r) {
col = c;
row = r;
}
//判断两个位置是否重合
function equals(t):Boolean {
return (col == t.col && row == t.row);
}
//根据方向值,取得此位置的下一个位置
function getNextPos(d):Pos{
var nextPos:Pos;
nextPos=new Pos(col,row);
switch (d) {
case 0 :
nextPos.col++;
break;
case 1 :
nextPos.row++;
break;
case 2 :
nextPos.col--;
break;
case 3 :
nextPos.row--;
break;
}
return nextPos;
}
}
//************Wall.as************
//用来构建游戏中的墙壁
class Wall extends MovieClip {
var brickMatrix:Array;//表示墙壁形状的数组
var left:Number;//左偏移量
var top:Number;//上偏移量
var bricks:Array;//用来存放砖块电影剪辑的数组
var _stepSize:Number;//每块砖的偏移量
//构造函数
function Wall {
left = 0;
top = 0;
_stepSize = 40;
}
//设置墙壁形状数组
function setMatrix(b) {
bricks = new Array();
brickMatrix = b;
}
//按照墙壁形状数组修墙
function build():Void {
var index = 0;
for (var i = 0; i
for (var j = 0; j
if (brickMatrix[i][j] == 1) { //数组值为1,画一块砖
bricks[index] = attachMovie(“Brick”, “bricks”+index, this.getNextHighestDepth());
bricks[index]._x = left+j*_stepSize;
bricks[index]._y = top+i*_stepSize;
index++;
}
}
}
}
}
//*************Target.as*****************
class Target extends MovieClip{
var pos:Pos;
var finished:Boolean;
var left:Number;
var top:Number;
var _stepSize:Number;
function Target(){
finished=false;
left=0;
top=0;
_stepSize=40;
}
function setPos(p){
pos=p;
this._x=left+pos.col*_stepSize;
this._y=top+pos.row*_stepSize;
}
}
//*************Player.as**************
//游戏中的player
class Player extends MovieClip {
var _stepSize:Number;//步长
var _wall:MovieClip;//墙壁电影剪彩辑
var startPos:Pos;//初始置
var currentPos:Pos;//当前位置
var left:Number;//左边距
var top:Number;//上边距
var dir:Number;//移动方向
var boxes:Array;
var player_path_stack:Array;//玩家移动的路线
var boxes_path_stack:Array;//箱子移动的路线
//构造函数,初始化
function Player() {
_stepSize = 40;
currentPos = null;
left = 0;
top = 0;
dir = 0;
player_path_stack=new Array();
boxes_path_stack=new Array();
boxes = new Array();
}
//设置玩家的起始位置
function setStartPos(p) {
startPos = new Pos(p.col, p.row);
currentPos = startPos;
this._x = currentPos.col*_stepSize+left;
this._y = currentPos.row*_stepSize+top;
}
//为玩家指定一个wall实例
function setWall(w) {
_wall = w;
}
//为玩家指定一个boxes数组,存有所有的箱子实例
function setBoxes(b) {
boxes = b;
}
//通过按键控制玩家
function setKeyHandle() {
this.onKeyDown = function() {
if (Key.isDown(Key.LEFT)) {
dir = 2;//左键
} else if (Key.isDown(Key.RIGHT)) {
dir = 0;//右键
} else if (Key.isDown(Key.UP)) {
dir = 3;//上键
} else if (Key.isDown(Key.DOWN)) {
dir = 1;//下键
}
var nextObject = this.getNextObject(); //取得玩家下一个位置上的物体
if (nextObject == “BOX”) { //玩家下一个位置上是个箱子
var box_pushed = getPushedBox();//取得此位置上的这个箱子
//被推到的箱子存在
if (box_pushed) {
if (box_pushed.getNextObject() == “NOTHING”) {//被推箱子的下个位置没有障碍
boxes_path_stack.push({box:box_pushed,pos:new Pos(box_pushed.pos.col,box_pushed.pos.row)});
box_pushed.move();//被推箱子移一步
this.move();//玩家移一步
}
}
} else if (nextObject == “NOTHING”) {//玩家的下个位置玩障碍
this.move();
boxes_path_stack.push(null);
}
};
Key.addListener(this); //监听按键输入
}
//取得被推到的箱子
function getPushedBox() {
var nextPos:Pos;
nextPos =currentPos.getNextPos(dir);
for (var i = 0; i if (boxes[i].pos.equals(nextPos)) { return boxes[i]; break; //trace(box_pushed); } } return null; } //取得玩家下个位置上的物块类型( 墙壁, 箱子, 无障碍) function getNextObject():String { //var obj:String; var nextPos:Pos; nextPos = currentPos.getNextPos(dir); if (_wall.brickMatrix[nextPos.row][nextPos.col] == 1) { return “WALL”; } for (var i = 0; i if (boxes[i].pos.equals(nextPos)) { return “BOX”; } } return “NOTHING”; } //移到下个位置 function move() { player_path_stack.push(currentPos); var c=currentPos.getNextPos(dir); currentPos=c; this._x = left+this.currentPos.col*_stepSize; this._y = top+this.currentPos.row*_stepSize; } //返回上一步 function reback(){ if(player_path_stack.length>0){ var pre=player_path_stack.pop(); currentPos=pre; this._x = left+this.currentPos.col*_stepSize; this._y = top+this.currentPos.row*_stepSize; } if(boxes_path_stack.length>0 ){ var bj=boxes_path_stack.pop(); if(obj!=null){ var box=obj.box; var pos=obj.pos; box.pos=pos; box._x=box.left+box.pos.col*box._stepSize; box._y=box.top+box.pos.row*box._stepSize; } } } } class Box extends MovieClip { var pos:Pos; var left:Number; var top:Number; var _wall:MovieClip; var player:MovieClip; var _stepSize:Number; var _targets:Array; var finished:Boolean;//此箱子是否到达目标地 function Box() { left = 0; top = 0; finished = false; _stepSize = 40; } //设置目标地 function setTargets(t) { _targets = new Array(); _targets = t; } //设置箱子的起始位置若罔闻 function setStartPos(p) { pos = new Pos(p.col, p.row); this._x = pos.col*_stepSize+left; this._y = pos.row*_stepSize+top; } //移到下一个位置 function move() { var c = pos.getNextPos(player.dir); pos = c; this._x = left+pos.col*_stepSize; this._y = top+pos.row*_stepSize; gotTarget(); } //是否到达目标地 function gotTarget() { for (var i = 0; i<_targets.length; i++) { if (this.pos.equals(_targets[i].pos)) { if (this.getDepth()>_targets[i].getDepth()) { this.swapDepths(_targets[i]); } this.finished = true; return; } } this.finished = false; } //取得一下个位置上物体的类型 function getNextObject():String { //var obj:String; var nextPos:Pos; nextPos = pos.getNextPos(player.dir); if (_wall.brickMatrix[nextPos.row][nextPos.col] == 1) { return “WALL”; } for (var i = 0; i if (player.boxes[i].pos.equals(nextPos)) { return “BOX”; } } return “NOTHING”; } } class Matrix{ //用来存放游戏各关中初始界面 static var matrixs:Array; function Matrix(){ matrixs=new Array(); //0:null //1:wall //2:player //3:box //4:target //5:target and box //1 2 3 4 5 6 7 8 9 matrixs[0]= [[0, 0, 0, 0, 0, 0, 0, 0, 0],//1 [0, 0, 0, 0, 0, 0, 0, 0, 0],//2 [0, 0, 0, 0, 0, 0, 0, 0, 0],//3 [0, 0, 0, 0, 0, 0, 0, 0, 0],//4 [0, 0, 0, 0, 0, 0, 0, 0, 0],//5 [0, 0, 0, 0, 0, 0, 0, 0, 0],//6 [0, 0, 0, 0, 0, 0, 0, 0, 0],//7 [0, 0, 0, 0, 0, 0, 0, 0, 0],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ]; //1 2 3 4 5 6 7 8 9 matrixs[1]= [[0, 1, 1, 1, 1, 1, 1, 0, 0],//1 [1, 1, 1, 0, 0, 0, 1, 0, 0],//2 [1, 0, 3, 0, 1, 0, 1, 1, 0],//3 [1, 0, 1, 0, 0, 4, 0, 1, 0],//4 [1, 0, 0, 0, 0, 1, 0, 1, 0],//5 [1, 1, 0, 1, 0, 0, 0, 1, 0],//6 [0, 1, 2, 0, 0, 1, 1, 1, 0],//7 [0, 1, 1, 1, 1, 1, 0, 0, 0],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ]; //1 2 3 4 5 6 7 8 9 matrixs[2]= [[0, 0, 1, 1, 1, 1, 1, 0, 0],//1 [1, 1, 1, 0, 0, 0, 1, 0, 0],//2 [1, 0, 3, 0, 1, 0, 1, 1, 0],//3 [1, 0, 1, 0, 0, 4, 0, 1, 0],//4 [1, 0, 0, 0, 0, 1, 0, 1, 0],//5 [1, 1, 3, 1, 4, 0, 0, 1, 0],//6 [0, 1, 2, 0, 0, 1, 1, 1, 0],//7 [0, 1, 1, 1, 1, 1, 0, 0, 0],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ]; //1 2 3 4 5 6 7 8 9 matrixs[3]= [[1, 1, 1, 1, 1, 1, 1, 1, 0],//1 [1, 0, 0, 0, 1, 0, 0, 1, 0],//2 [1, 0, 0, 0, 0, 0, 0, 1, 0],//3 [1, 1, 3, 1, 1, 0, 0, 1, 0],//4 [0, 1, 0, 4, 1, 0, 1, 1, 1],//5 [0, 1, 0, 0, 0, 0, 2, 0, 1],//6 [0, 1, 0, 0, 1, 0, 0, 0, 1],//7 [0, 1, 1, 1, 1, 1, 1, 1, 1],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ]; //1 2 3 4 5 6 7 8 9 matrixs[4]= [[1, 1, 1, 1, 1, 1, 1, 1, 0],//1 [1, 0, 0, 0, 1, 0, 0, 1, 0],//2 [1, 0, 0, 0, 0, 0, 0, 1, 0],//3 [1, 1, 5, 1, 1, 0, 0, 1, 0],//4 [0, 1, 0, 4, 1, 0, 1, 1, 1],//5 [0, 1, 0, 5, 0, 3, 2, 0, 1],//6 [0, 1, 0, 0, 1, 0, 0, 0, 1],//7 [0, 1, 1, 1, 1, 1, 1, 1, 1],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ]; //1 2 3 4 5 6 7 8 9 matrixs[5]= [[0, 0, 1, 1, 1, 1, 0, 0, 0],//1 [0, 1, 1, 0, 0, 1, 1, 1, 1],//2 [1, 1, 0, 0, 0, 0, 0, 0, 1],//3 [1, 0, 3, 0, 1, 2, 1, 0, 1],//4 [1, 0, 1, 0, 4, 0, 0, 0, 1],//5 [1, 0, 0, 3, 0, 1, 1, 1, 1],//6 [1, 1, 1, 0, 4, 1, 0, 0, 0],//7 [0, 0, 1, 1, 1, 1, 0, 0, 0],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ]; //1 2 3 4 5 6 7 8 9 matrixs[6]= [[0, 0, 1, 1, 1, 1, 0, 0, 0],//1 [0, 1, 1, 0, 0, 1, 1, 1, 1],//2 [1, 1, 0, 0, 3, 0, 0, 0, 1],//3 [1, 0, 3, 0, 1, 2, 1, 0, 1],//4 [1, 0, 1, 0, 4, 0, 0, 0, 1],//5 [1, 0, 4, 3, 0, 1, 1, 1, 1],//6 [1, 1, 1, 0, 4, 1, 0, 0, 0],//7 [0, 0, 1, 1, 1, 1, 0, 0, 0],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ]; //1 2 3 4 5 6 7 8 9 matrixs[7]= [[0, 1, 1, 1, 1, 1, 0, 0, 0],//1 [0, 1, 0, 0, 0, 1, 0, 0, 0],//2 [1, 1, 3, 1, 0, 1, 1, 1, 0],//3 [1, 0, 0, 0, 3, 2, 0, 1, 0],//4 [1, 0, 1, 0, 0, 1, 0, 1, 0],//5 [1, 0, 1, 4, 0, 4, 0, 1, 0],//6 [1, 0, 0, 0, 1, 1, 1, 1, 0],//7 [1, 1, 1, 1, 1, 0, 0, 0, 0],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ]; //1 2 3 4 5 6 7 8 9 matrixs[8]= [[0, 1, 1, 1, 1, 1, 0, 0, 0],//1 [0, 1, 0, 0, 0, 1, 0, 0, 0],//2 [1, 1, 3, 1, 0, 1, 1, 1, 0],//3 [1, 0, 0, 4, 3, 2, 0, 1, 0],//4 [1, 0, 1, 0, 0, 1, 0, 1, 0],//5 [1, 0, 1, 4, 4, 3, 0, 1, 0],//6 [1, 0, 0, 0, 1, 1, 1, 1, 0],//7 [1, 1, 1, 1, 1, 0, 0, 0, 0],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ]; //1 2 3 4 5 6 7 8 9 matrixs[9]= [[0, 1, 1, 1, 1, 1, 1, 1, 0],//1 [0, 1, 0, 2, 4, 4, 4, 1, 0],//2 [0, 1, 0, 0, 0, 1, 1, 1, 1],//3 [1, 1, 1, 3, 0, 0, 0, 0, 1],//4 [1, 0, 0, 0, 1, 3, 1, 0, 1],//5 [1, 0, 3, 0, 1, 0, 0, 0, 1],//6 [1, 0, 0, 0, 1, 1, 1, 1, 1],//7 [1, 1, 1, 1, 1, 0, 0, 0, 0],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ]; //1 2 3 4 5 6 7 8 9 matrixs[10]= [[0, 0, 1, 1, 1, 1, 0, 0, 0],//1 [0, 0, 1, 0, 0, 1, 0, 0, 0],//2 [0, 0, 1, 0, 0, 1, 0, 0, 0],//3 [0, 0, 1, 0, 0, 1, 1, 1, 0],//4 [0, 0, 1, 4, 3, 3, 2, 1, 0],//5 [0, 0, 1, 0, 0, 4, 0, 1, 0],//6 [0, 0, 1, 0, 0, 1, 1, 1, 0],//7 [0, 0, 1, 1, 1, 1, 0, 0, 0],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ]; } function getMatrix(d){ return matrixs[d]; } } //****************Manager.as************* //用来管理游戏 //所有的对象都入其中 //MovieClip类的子类 class Manager extends MovieClip { var wall:MovieClip; var player:MovieClip; var boxes:Array; var targets:Array; var stageNum:Number;//游戏的当前关数 function Manager() { _x=50; _y=50; } //游戏初始化 function init(s) { stageNum = s; boxes = new Array(); targets = new Array(); var brickMatrixT = new Matrix().getMatrix(stageNum);//根据关数从矩阵类中取得相应的矩阵 //修墙 wall = attachMovie(“Wall”, “wall”, this.getNextHighestDepth()); wall.setMatrix(brickMatrixT); wall.build(); //创建一个玩家 player = attachMovie(“Player”, “plyaer”, this.getNextHighestDepth()); player.setWall(wall); player.setKeyHandle();//监听键盘输入 for (var i = 0; i for (var j = 0; j if (brickMatrixT[i][j] == 2) { player.setStartPos(new Pos(j, i)); } if (brickMatrixT[i][j] == 3) { var d = this.getNextHighestDepth(); var box = attachMovie(“Box”, “box”+i+j, d); box.setStartPos(new Pos(j, i)); box.player = player; box._wall = wall; boxes.push(box); } if (brickMatrixT[i][j] == 4) { var d = this.getNextHighestDepth(); var t = attachMovie(“Target”, “target”+i+j, d); t.setPos(new Pos(j, i)); targets.push(t); } if (brickMatrixT[i][j] == 5) { var d = this.getNextHighestDepth(); var box = attachMovie(“Box”, “box”+i+j, d); box.setStartPos(new Pos(j, i)); box.player = player; box._wall = wall; box.finished = true; boxes.push(box); var d1 = this.getNextHighestDepth(); var t = attachMovie(“Target”, “target”+i+j, d1); t.setPos(new Pos(j, i)); targets.push(t); } } } for (var i = 0; i boxes[i].setTargets(targets); } player.setBoxes(boxes); player.swapDepths(this.getNextHighestDepth()); } //判断游戏是否结束 function ifWin() { var win = true; for (var i = 0; i win = boxes[i].finished && win; } return win; } } 新建“Flash文档”,命名为“push_box”,并将它和以上脚本文件存在同一目录下.以下要做的就是建立要用到的电影剪辑,并将其和相应的脚本文件建立链接. 按“Ctrl+F8”,新建一个电影剪辑,命名为“Player”,在编辑状态下画一个长,宽都为40象素的小人(_stepSize=40),注意,小人的注册点放在左上脚.画完后在电影库中,右击“Player”,选择“为动作脚下本导出”,其它不选.“标识符”,“As 2.0类”都为电影剪辑名“Player”.要注意,大小写不能搞错,否则会出错. 按上述方法依次建立“Box”,“Target”剪辑. 按10建立名为“Brick”的剪辑,不过由于它不需要外部脚本文件,故“As 2.0”中不要添. 按10建立“Wall”剪辑,稍有不同的是,在编辑状态下,第一帧中加“stop()”,第二帧中加入一个“Brick”剪辑.这样做是因为“Wall”在修建时需要用到“Brick”. 按12建立“Manager”剪辑,不同的是需要点中“在第一帧导出”,而且第二帧加入的不是“Brick”,而是“Wall”,“Player”,“Box”,“Target”. 好了,一切就绪,我们可以测试一下了.在主时间轴上第一帧中中入语句:attachMovie(“Manager”,“game1”,_root.getNextHighestDepth()); game1.init(1);就可以运行第一关了. 至于如何建立友好的用户界面,我们只需稍花点力气就搞定了.
示例:
点击这里下载源文件
如果你还有任何不明白之处,可发邮件或QQ给我.xiake1860@ncepubj.edu.cnQQ:4077130
篇3:面向对象设计的优点
一旦明白了软件设计的真谛(参见《软件设计的真谛》),我们就更能理解面向对象设计的优点,简单说来,它更便于我们在软件中构建更真实的虚拟世界。
首先,对象的引入方便了在软件虚拟世界中模拟现实世界。现实世界是由很多独立的抽象或具体物体组成的,比如房子、汽车、空调、书等等。为了构建更真实的虚拟世界,在软件中需要存在用于表达类似现实物体的编程元素,这正是引入对象概念的意义所在。
以对象为设计中心,迫使设计者在关注程序所需实现功能的同时不至于忘记通过抽象去塑造概念,以便用对象表达之。由于抽象获得的对象有助于隐藏复杂度,这在一定程度上简化了通过对象表达和理解软件虚拟世界的难度。也由于对象的存在,使得设计更加的生动和具有更强的自我解释能力。
从软件设计者的角度:如果希望塑造的对象在现实生活中存在,这有助于他借助现实引导自己的设计,他也应尽量将虚拟世界中对象的行为塑造成与现实世界的相近;如果希望塑造的对象在现实生活中并不存在,他只能借助对象的行为和状态去塑造对象(的概念),此时应注意行为、状态与概念间关系的合理性,否则所塑造的对象将令人费解。
从软件维护者的角度:如果对象在现实生活中存在,这有助于他借助生活经验快速掌握设计;如果在现实中找不到对象的影子,他仍可以通过对象的行为掌握对象的概念,这同样有助于他更方便地维护软件,
其次,面象对象设计由于强调以对象为中心,因而具备更强的封装能力。在大多支持面向对象设计的编程语言中,更强的封装能力除了意味着更具信息隐藏能力外,还使得封装的边界既明显又更不易被突破,这有助于在软件的维护过程中维持“形”。某种程度上,面向对象设计强化了软件行业推崇的模块化设计。
再次,面向对象设计中的继承和多态技术除了进一步提高通过软件模拟现实世界的能力外,还能让设计更灵活、易变更和方便复用。
显然,面向对象设计的优势是通过使得设计方法更抽象而获得的,这也解释了为什么掌握面向对象设计比掌握面向过程设计更难。现实中,由于有些工程师难以转变为从对象、继承和多态的角度思考设计,使得运用面向对象设计这一方法举步为艰。
面向对象设计的关键是用对象表达抽象概念,如果抽象出的概念并不清晰,则所获得的设计一定不会好。千万不要误以为运用面向对象设计所获得的设计就一定比面向过程的好。好方法获得好结果的前提仍需要我们运用好。
有了面向对象设计以后并不是说我们就可以抛弃面向过程设计。实际上,即使我们采用了面向对象设计,但在局部范围内我们还是离不开运用面向过程的设计思想。比如,类的构建需要运用面向对象设计,而类方法的实现却得用到面向过程设计。
篇4:Silverlight 图形:如何裁剪对象
可以通过裁剪掉对象的某个显示区域来裁剪对象,这是使用 Clip 属性来完成的。将此属 性设置为 Geometry,这意味着可以从对象中裁剪掉各种几何形状(例如,椭圆、直线或复杂 路径)。
说明:
创建裁剪效果的另一种方法是通过使用渐变来应用 OpacityMask。因为您使用的是 Opacity 属性,因此可以在裁剪中创建“模糊边缘”。
下面的示例演示如何从矩形中裁剪掉椭圆形(圆形)区域。为了从概念上描述此示例,请 考虑下图中的矩形。
一个矩形
下图显示了一个半径为 50、中心位于 200, 100 的椭圆。
一个中心位于 200, 100 的椭圆
下图显示了这两个形状的重叠方式,
形状重叠
下图显示了使用椭圆作为裁剪几何图形裁剪矩形的结果。
裁剪的结果形状
下面的代码演示如何使用 Clip 属性创建上图中的形状。
XAML
StrokeThickness=“2” Stroke=“Black”>
篇5:php面向对象面试题
面向对象模型
面向对象的概念:
oop(面向对象的编程)它能是其代码更加简洁易于维护并且具有更强的可重性
什么是类:
类是具有相同属性和服务的一组对象的集合比如说人,书,轮船,车都属于类,他为属于该类的对象做了一个统一的抽象描述,在编程的语言中类是一个单独的程序,它应该有一个类名包括属性的说明和服务两个部分。
什么是对象:
对象是系统中描述客观事件的一个实体,他是构成系统的一个基本单位。*数据与代码都被捆绑在一个实体当中*,一个对象由一组属性和对这组属性进行操作的一组行为组成。
从抽象的角度来说,对象是问题域或实现域中某些事物的一个抽象。他反映该事物在系统中保存的信息和发挥的作用:它是一组属性和有权对这些属性进行操作的一个封装体。客观世界是由对象和对象之间的联系组成的。
类和对象的关系:
类与对象的关系就如模具和铸件的关系,类的实力化的结果就是对象,而对对象的抽象就是类,类描述了一组有相同特性(属性)和相同行为的对象。
类与属性和方法
PHP中定义类语法格式:
复制代码代码如下:
class classname [可选属性]{
public $property [=value];… //用public声明一个公共标识 然后给予一个变量 变量也可以赋值
function functionname ( args ){ //类的方法里的成员函数
代码} …
//类的方法(成员函数)
}
生成对象(类的实例化): $对象名=new classname( );
使用对象的属性
在一个类中,可以访问一个特殊指针$this当在该类中通过一个操作设置或访问该变量时,使用$this->name来引用.
对象的生成
定义好类后用一个new来声明,由于对象资料的封装特性,对象是无法由主程序区块直接访问的须通过对象来调用类中所定义的属性和行为函数,间接地达成存取控制类中资料的目的。
对象和类的关系
对象和类的关系:
对象是实际存在的,占有动态资源。
类是对象的蓝图,可能占有静态资源。
对象属性占有动态资源
类(静态)属性实际上是有类名字空间上的“全局变量”
性能考虑:
每个对象要单独占用数据空间
增加的调用层次可能消耗执行时间
方法的参数形式和传递方式
方法的参数可以是基本数据类型、数组和类对象。
基本数据类型:值参传递
数组:值参传递
类对象:引用传递
构造函数
构造函数是在类中起到初始化的作用
构造函数的生成方法与其他函数一样只是其名称必须是__construct.
语法格式:
function __construct(参数){
。。。。。。。。
}
范例:
复制代码代码如下:
class Person{
public $name;
public $sex;
public $age;
function __construct($name,$sex,$age){
echo “我是构造函数
”;
$this->name=$name;
$this->sex=$sex;
$this->age=$age;
}
输出结果:初始化
析构函数
当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数。应在退出前在析构函数中用释放内存。
析构函数__destruct 析构函数没有任何参数
范例:
复制代码代码如下:
class person{
function _ _destruct( )
{ echo “bye bye !”; }
}
$a=new person();
访问类型
public 公共的(公共修饰符) 类内部与类外部都可以访问的
private 私有的(私有修饰符) 只能在类内部访问
protected 受保护的(保护成员修饰符) 子类可以访问 类外部不可以访问
oop的三个重要特性
封装,继承,多态
封装性:封装性就是把对象的属性和行为结合成一个独立的单位。
封装一个类需要两步 第一步是私有化一个类 第二步是用set和get 做出读取赋值的操作
他的好处是:隐藏类的实现细节,可以方便加入逻辑控制性,限制对属性的不合理操作,便于修改增强代码的可维护性。
__get与__set
一般说把类私有话更符合现实的逻辑。
预定义两种函数来进行获取与敷值操作。
__get 获取值通常是域的值
__set 设置值通常是域的值
__call 调用一个对象中不存在的方法时,就会产生错误call()这个方法来处理这种情况。
静态属性和方法
static关键字 来声明静态方法
static静态变量 在类的内部生成一个静态变量 就是能够被所有类的实力化共想 也就是说静态成员则放到了“初始化静态段”,在类第一次被加载的时候放入的,可以让堆内存里面的每个对象所共享
使用方法:self::$静态属性、self::静态方法
static function p(){
echo self::$country;
echo self::PI;//访问常量
//echo $this->name;在静态方法中只能操作静态属性
//self::p();
}
外部调用:类::$静态属性、类::静态方法
const关键字:用来生成常量 常量是唯一的不能改变的 惯例常量为大写
const CONSTANT = 'constant value'; 生成一个常量
echo self::CONSTANT;//类内部访问
echo ClassName::CONSTANT;//类外部访问
继承性
B类的对象拥有A类的全部属性与行为,称作B对A类的继承。
假如一个类从多个类中继承了属性与服务,这称为多继承,通常我们成为继承类为子类被继承类为父类,在PHP中只有单继承,但一个父类可以被多个类继承,但是一个子类只能有一个父类,但是允许关联继承,通过继承可以减化类的定义。
extende声明继承关系
语法格式:class B extends A 此范例指明 B继承了A
类的外部访问对子类是有效的
子类与父类的属性与方法
子类继承父类的所有内容,但父类中的private部分不能直接访问
子类中新增加的属性和方法是对父类的扩展
子类中定义的与父类同名的属性是对父类属性的覆盖,同名的方法也是对父类方法的覆盖
重写的方法
在子类中,使用parent访问父类中的被覆盖的属性和方法
parent::__construce();
parent::$name;
parent::fun();
覆盖父类原有属性
clone克窿对象 语法格式$c=clone $p; $c克窿的对象$p 输出echo $c->name;
对象比较
===两个比较运算符。
==是比较两个对象的内容。
===是比较对象的句柄,即引用地址。
instanceof操作符用于检测对象实力是否属于某一个类的类型 属于返回true 不属于返回false
__clone()如果想在克隆后改变原对象的内容,需要在__clone()中重写原本的属性和方法
function __clone(){
$this->name=“我是一个克隆人”;
}
final表示一个类是最终版本 也就是说它不能在被子类调用
多态性
多态性是指在父类中定义的属性或行为被子类继承之后,可以具有不同的数据类型或表现出不同的行为。这使得同一个属性或行为在父类及其各个子类中具有不同的语义。
就是说同一种方法在子类与父类中执行的结果不同。
复制代码代码如下:
class A {
function info(){
echo “A INFO”;
}
}
class B extends A {
function info(){
echo “B INFO”;
}
}
class C extends A {
function info(){
echo “C INFO”;
}
}
function printinfo($obj){
function printinfo(A $obj){
if($obj instanceof A)
$obj->info();
$obj->info();
}
}
$a=new A(); $b=new B(); $c=new C();
printinfo($a); //输出A INFO
printinfo($b); //输出B INFO
printinfo($c); //输出C INFO
抽象方法和抽象类
抽象方法是作为子类摸版使用的。
复制代码代码如下:
abstract class Person{
public $name;
abstract function getInfo();
}
抽象类不能被实力话,一个抽象类中,必须有一个抽象方法。但是抽象类中可以定义动态函数。
接口
当一个类继承了一个接口之后,它要覆盖接口的所有方法,接口只能声明常量,接口的方法必须定义为共有否则无法继承,接口可以与多个接口间继承
语法:
复制代码代码如下:
interface PCI{
const TYPE=“PCI”;
//public $name; error
function start();
function stop();
}
接口中的方法可以声明为static
复制代码代码如下:
interface A{ function a();}
interface B{ function b();}
interface C extends A{ function c();}
class D implements B,C{
function a(){}
function b(){}
function c(){}
}
类
类的声明:
复制代码代码如下:
权限修饰符 class 类名{ //权限修士符号:public,protected,private 或者省略3者.
//类体; //class 是建类关键字
} //类名必须跟在class 后面,且跟上{}.{}之间放类的成员.
?>
//ps:在class关键字前可以加权限修饰符外,还可以加static,abstract等关键字.一个类,即一对大括号之间的全部内容都要在一段代码段中,不允许将类中的内容分割成对块.
class ConnDB{
//....
?>
//...
};
?>
成员属性:
在类中直接声明的变量称为成员属性/变量.其类型可以为php中的标量类型和复合类型,使用资源类型和空类型是无效的.
此外,成员属性的声明时,必须要有关键字来修饰:有特定意义的关键字:public,protected,private ;不需要特定意义:var.声明成员属性时,没有必要赋初始值.
成员常量:
以const常量修饰,例如:const PI = 3.1415926;
常量的输出不需要实例化,直接由类名+常量名调用即可,格式为: 类名::常量名
ps. 特殊的访问方法:--------“$this” 和 “::”
1) $“this” 存在于每个成员方法当中,它是一个特殊的对象以用方法.成员方法属于那个对象,$this应用就代表那个对象,其作用就是专门完成对象内部成员之间的访问.
2) “::”成为作用域操作符,使用这个操作符可以在不创建对象的情况下调用类中的常量,变量和方法. 其语法格式如下:
关键字::变量名/常量名/方法名
关键字:parent,可以调用父类成员中的成员变量,成员方法和常量;
self,可以调用当前类中的静态成员和常量;
类名,可以调用类中的常量,变量和方法;
成员方法:
在类中声明的函数成为成员方法,在一个类中可以声明多个函数,即对象可以拥有多个成员方法.成员方法的声明和函数的声明相同,唯一特殊之处就是成员方法可以有关键字对它进行修饰,从而控制其访问权限.
类的实例化
创建对象:
$变量名 = new 类名称([参数]); //类的实例化.
访问类成员:
$变量名 ->成员属性 = 值;
构造方法和析构方法
构造方法是对象创建完成后第一个呗对象自动调用的方法.它存在每个类的声明当中,是一个特殊的成员方法,一般用来完成一些初始化操作.如果类中没有构造方法,系统会默认自动生成一个没有参数的构造方法.
格式:
复制代码代码如下:
function _construct(形参列表){
//方法体
};
析构方法则如构造方法相反,它是在对象被销毁前最后一个调用的方法.它将完成一个特定的操作,如关闭文件和释放内存.
格式:
复制代码代码如下:
function _destruct(){
//方法体
};
面向对象特点:封装性,抽象性,多态性.
封装:
将类中的成员属性和方法结合成一个独立的相同单位,并且尽可能的隐藏对象的内容细节.其目的是确保类以外的部分不能随意存取类的内部数据(成员属性和成员方法),从而避免外部错误对内部数据的影响.
类的封装是通过关键字public,private,protected,static和final实现的.各关键字的作用请查看php相关文档.
继承性:
使一个类继承并拥有另一个已存在的类的成员属性和成员方法,其中被继承的类成为父类,继承的类成为子类.通过继承能够提高代码的重用性和可维护性.类的继承用 extends 关键字.
格式:
复制代码代码如下:
class 子类名称 extends 父类名称{
//子类方法体.
}
通过parent::关键字也可以在子类方法中调用父类的成员方法,格式如下:
parent::父类的成员方法(参数);
覆盖父类的方法:
所谓的覆盖父类的方法,也就是使用子类中的方法替换从父类中继承的方法,也叫方法的重写.重写的关键就在与子类中创建与父类中相同的方法,g包括方法名称,参数和返回类型.
多态性:
多态性是指一段程序能够处理多种类型对象的能力.php多态有两种实现方法,即通过继承实现多态和通过接口实现多态.
通过继承实现多态,即通过重写继承的成员方法来达到多态的效果.
复制代码代码如下:
abstract class ParentClass{
abstract function printMessage();
}
class SubClassA extends ParentClass{
function printMessage(){
echo “i am message from class A”;
}
}
class SubClassB extends ParentClass{
function printMessage(){
echo “i am message from class B”;
}
}
function printMSG($object){
if( $object instanceof ParentClass){
$object->printMessage();
}else{
echo “error!”;
}
}
$objectA=new SubClassA();
printMSG($objectA);
$objectB=new SubClassB();
printMSG($objectB);
?>
通过接口实现多态,通过定义接口,与空方法.然后类继承接口.
复制代码代码如下:
interface interfaceInfo{
function printMessage();
}
class ClassA implements interfaceInfo{
function printMessage(){
echo “message form class A”;
}
}
class ClassB implements interfaceInfo{
function printMessage(){
echo “message form class B”;
}
}
function printMSG($object){
if($object instanceof interfaceInfo){
$object ->printMessage();
}else{
echo “error !”;
}
}
$objectA =new ClassA();
printMSG($objectA);
$objectB =new ClassB();
printMSG($objectB);
?>
ps. 抽象类和接口.
抽象类和接口都是不能被实例化的特殊类.他们都是能够配合面向对象多态性一起使用.
抽象类:
抽象类是一种不能实例化的类,只能作为其他类的父类来使用.抽象类使用abstract 关键字来声明,其格式如下:
复制代码代码如下:
abstract class 抽象类名{
abstract function 成员方法(参数);//
}
抽象类和普通类相似,包含成员变量,成员方法.两者区别在于抽象类至少要包含一个抽象方法.抽象方法没有方法体,其功能的实现只能在子类中完成.抽象方法也使用关键字 abstract 来修饰.
接口:
继承特性简化了对象和类的创建,增强了代码的可重用性.但php只支持单继承,如果想实现多重继承,就要使用接口.
接口的声明:通过interface 关键字来实现,接口中声明的方法必须是抽象方法,接口中不能声明变量,只能使用const 关键字声明为常量的成员属性,并且接口中所有成员都必须具备puclic 的访问权限.ainterface 声明接口格式如下:
复制代码代码如下:
inerface 接口名称{
//常量成员;//成员只能是常量.
//抽象方法;
}
由于接口不能实现实例化操作,因此只能借助子类继承接口的形式来实现.实现的格式是:
复制代码代码如下:
Class 子类名 implements 接口名1[,接口名2,接口名3,.....]{
//子类方法体.
}
常用关键字:
1) final:final之意为最终的,最后的.这就以为着通过final 关键字修饰的类和方法都为最终版本.不能被继承,也不能有子类.不能重写,也不能被覆盖.
2) static: 通过static 关键字修饰的成员属性和成员方法称为静态属性和静态方法.静态成员属性和方法不需要被实例化就能直接使用.
静态属性:它属于类本身,而不属于类的任何实例.它相当于存储在类中的全局变量,可以在任何位置通过类来访问.访问格式为:
类名称::$静态属性名称;
如果你要在类内部的成员方法中访问静态属性,那么在静态属性的名称前加上操作符: “self::” 即可.
静态方法:由于其不受任何对象限制,因此可以不通过类的实例化而直接引用类中的静态方法.引用格式如下:
类名称::静态方法名(参数);
如果你要在类内部的成员方法中调用静态方法,那么在静态方法的名称前加上操作符: “self::” 即可.在静态方法中只能调用静态变量,而不能调用普通变量;而普通方法中则可以调用静态变量.
使用静态成员除了不需要实例化外,另一个作用是在对象被销毁后,仍然保留呗修改的静态数据,以便下次调用.
3) clone.对象的克隆可以通过关键字来实现.使用clone对象与原对象没有任何关系,即克隆对象会重新申请一份存储空间来存放原对象内容.格式如下:
$克隆对象 = clone $原克隆对象名称;
克隆成功后,他们的n成员方法,属性以及值完全相等.如果要对副本重新初始化,就要用到 _clone().
魔术方法_clone()可以对克隆后的副本对象重新初始化.它不需要任何参数,其中自动包含$this (副本对象)和 $that (原对象) 对象的引用.
对象的比较:
“==” 表示比较两个对象的内容,“===”表示比较两个对象的引用地址相等.
对象类型的检测: instanceof 操作符可以检测当前对象属于那个对象.
面向对象---常用魔术方法:
以上我们已经了解的常用魔术方法有:_construct(),_destruct(),_clone.下面我们再接着介绍几个常用魔术方法.
_get(),_set();
以上两个方法用于对私有成员精细复制或者获取值的操作.
_set()在程序运行中为私有的成员属性设置值,它不需要任何返回值._set()方法包括两个不可省略的参数:变量名和变量值.这个方法不需要主动调用,可在方法钱加上prive关键字.
_get():在程序运行中,在对象的外部获取私有成员的属性的值.他有一个参数:私有成员属性名称.他返回一个允许对象在外部使用的值.此方法同样不许主动调用.
_isset(),_unset():
isset()函数用于检测变量是否存在.而在面向对象中可以通过isset()函数对公有的成员属性进行检测,但对私有成员属性,此函数则不起作用.因此,_isset()函数正是为了起到此作用而创建.格式如下:
bool _isset(string name);
_unset()则同样为了删除制定的变量和对象的私有成员属性.格式如下:
void _unset(string name);//
_call():
_call()方法的作用是当程序试图调用不存在或不可见的成员方法时,php会先调用_call()方法来存储方法名及其参数(方法名和方法参数).其中方法参数是以数组的形式存在.
_toString()方法:
其作用是当使用echo 或者print输出对象时,将对象转化为字符串.
如果没有_toString()方法,直接输出对象时将会发生致命错误.
输出对象时应注意的是,echo 或print 语句后面直接跟要输出的对象,中间不要加多余的字符,否则_toSting()将不会被执行.
_autoload()方法:
将一个独立的,完整的类保存到一个php页中,并且文件名和类名保持一致,这是每个开发人员都需要养成的良好习惯.这样下次在使用的时候就能够轻松的找到它.但有一种情况:如果要在一个页面中引进很多的类,就需要使用include_once()函数或者require_once()函数一个个地引入.php5中引入_autoload()方法可以自动实例化需要使用的类.当一个类还没实例化时,_autoload()会自动到指定的路径下面自动查找和类名相同的文件.找到则继续执行,否则报错.
复制代码代码如下:
function _autoload($class_name){
$class_path = $class_name.'.class.php';
if(file_exists($class_path)){
include_once($class_path);
}else{
echo '类不存在或者类路径错误';
}
}
$class = new Class(); //将会自动加载.
echo $class; //输出类内容.如自定义了_toString()方法;则会输出_toString()中定义的内容.
?>
[php面向对象面试题]
篇6:笔试题面向对象
操作系统
1请解释下列10个shell命令的用途
top、ps、mv、find、df、cat、chmod、chgrp、grep、wc
2、写出下列服务的用途和默认端口
ftp、ssh、http、telnet、https
面向对象
1、写出php的public、protected、private三种访问控制模式的区别
2、写出下列程序的输出结果
class a{
protected $c;
public function
a(){
$this ->c=10;
}
}
class b extends a
{
public function print_data(){
return
★ 软件开题报告
★ 图形的变换课件
★ Expression Blend实例中文教程 控件快速入门ControlTempla
【Silverlight游戏设计:(五)面向对象的思想塑造游戏对象(共6篇)】相关文章:
帝国时代作文2022-04-29
如何屏蔽弹出的广告窗口2022-10-19
ntlm验证机制学习札记2022-12-12
WEB开发工程师个人简历2022-07-09
程序员年终总结怎么写2022-11-08
有关游戏项目策划与开发实习心得2022-07-22
Silverlight 2中多语言支持实现(下)2022-08-28
游戏项目策划与开发实习心得2023-07-27
年终总结程序员2024-03-09
程序员年终总结2022-11-28