`
wgcode
  • 浏览: 593872 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

即时战略游戏开发—Rectangle对象应用实战+Array对象中被你忽略的方法

阅读更多

上一次发了一篇Rectangle对象在游戏开发中的应用的文章,下面还是围绕Rectangle对象介绍一下在即时战略游戏中的实际应用。同时还将会用到数组对象中平时用的不多的几个方法。

      玩过《红警》或者《帝国时代》的朋友应该都知道,这类游戏有一个框选功能。鼠标在屏幕上拉一个框,处在方框之内的都被选中。如图:


 

 

 

 

 

 

      我们这个例子的原型是这样的:

      1、坦克的选择有框选和点击选择两种方式。
      2、坦克被选中后会显示自己被选中
      3、鼠标在屏幕上点击时,如果有坦克被选中,坦克将移动到鼠标点击位置附近(是附近不是鼠标点击位置),同时选择状态自动取消。
      4、如果有新的选择,则之前选择的坦克的选择状态将取消。

      先看一下做好的效果,点击这里

讲解:

      1、坦克的被选择和非选择状态的实现
      在我们的坦克类里面设置一个属性select,通过set方法来实现。当select=true时,让坦克的帧跳转到第2帧。当select=false时,让坦克的帧跳转到第1帧。

      在坦克类Tank中设定一个私有变量_select,然后设置getter/setter

      public function get select():Boolean
      {
           return _select;
      }
      public function set select(s:Boolean)
      {
           _select=s;
           this.gotoAndStop(_select==true? 2:1)
      }

      2、坦克点击选择的实现
      我们没有必要给每一辆坦克都注册鼠标事件,只要给放置坦克的容器注册一个鼠标事件就能知道用户点击的是哪一辆坦克。
      MouseEvent有target和currentTarget两个属性。这两个属性有区别,target返回的是最先接收到点击的交互物体,而currentTarget返回的是你addEventListener注册的这个对象。见下图:
     

 

 

      3、坦克框选的实现
      基本上我们会需要做这几个步骤:
      A、通过鼠标的MOUSE_MOVE事件实现拉框效果。
      B、通过画的这个框和物体的边界框比较判断那些物体被选择了
      C、让这些物体变为选择的状态
      D、当鼠标再一次被点击时,如果有坦克在选择状态下并且点击的位置是空地,则所有坦克向目标点附近移动,同时取消所有选择状态。

      实现思路是——准备两个数组一个记录所有坦克的引用tankList,一个记录任何时候被选择的坦克的引用selectList。

       这里我们会用到平时使用不多的两个数组里的方法forEach()和filter(),这两个方法将在这里发挥重要的作用。数组对象共有5个你可能没怎么关注的新的方法。如下图:\





 
 
 

      来看一下我们在这个例子里面是怎么用的:

      selectList=tankList.filter(selectTank); //找出被框选的坦克
      selectList.forEach(moveTank); //让所有被选中的坦克移动

      function selectTank(element:*, index:int, arr:Array)
      {
           //如果坦克边界与选框相交,则让坦克显示为选择状态
           if(element.getBounds(this).intersects(rec)==true)
           {
                element.select=true;
                return true;
          }
           return false;
      }

      function moveTank(element:*, index:int, arr:Array)
      {
         element.select=false; //移动时取消坦克的选择状态
          var randomX=targetPoint.x+Math.random()*150-75;
          var randomY=targetPoint.y+Math.random()*150-75;
          element.moveTo(randomX,randomY); //让坦克移动
       }

 

完整代码如下:
==================================================================================
主程序:
import Tank;

var map:Sprite=new Sprite(); //定义一个地图容器
var tankList:Array=new Array(); //定义一个记录所有坦克的列表
var selectList:Array=new Array(); //定义一个记录当前选择的坦克的列表
var targetPoint:Point; //目标点
var rec:Rectangle; //选择框的矩形对象
var shape:Shape=new Shape(); //用于显示选择框的Shape对象
var isMove:Boolean; //选择坦克还是移动坦克
addChild(map); //把地图放入显示列表
addChild(shape); //选择框

//产生20辆坦克
for (var i=0;i<20;i++)
{
    var tank=new Tank();
    map.addChild(tank);
    tankList.push(tank); //把坦克的引用记录下来
}

addEventListener(MouseEvent.MOUSE_DOWN,mouseDownHandler)
addEventListener(MouseEvent.MOUSE_UP,mouseUpHandler)

function mouseDownHandler(evt:MouseEvent)
{
    targetPoint=new Point(evt.currentTarget.mouseX,evt.currentTarget.mouseY);
    //如果点击在坦克上,则此坦克被选中。否则注册一个鼠标移动事件
    if((evt.target is Tank)==true)
    {
        selectList.forEach(unSelect); //将已选择链表中所有坦克变为非选择状态
        clearArray(selectList); //清空selectList数组
        evt.target.select=true
        selectList.push(evt.target)
       isMove=false; 
    }
    else
    {
        addEventListener(MouseEvent.MOUSE_MOVE,mouseMoveHandler)
       isMove=true;
   }
}
function mouseMoveHandler(evt:MouseEvent)
{
    var recWidth=evt.currentTarget.mouseX-targetPoint.x;
    var recHeight=evt.currentTarget.mouseY-targetPoint.y;
    shape.graphics.clear();
    shape.graphics.beginFill(0x99ccff,0.2);
    shape.graphics.lineStyle(2, 0x000000,0.8);            
    shape.graphics.drawRect(targetPoint.x,targetPoint.y, recWidth, recHeight)
    shape.graphics.endFill(); 
}
function mouseUpHandler(evt:MouseEvent)
{
    removeEventListener(MouseEvent.MOUSE_MOVE,mouseMoveHandler)
    rec=shape.getBounds(this);
    shape.graphics.clear();
    if(rec.width>0&&rec.height>0)//重新框选
   {
        selectList.forEach(unSelect);
       clearArray(selectList);
        selectList=tankList.filter(selectTank);
       rec.width=rec.height=0;
   }
    else if(selectList.length>0&&isMove==true)
    {
        selectList.forEach(moveTank)
        clearArray(selectList);
    }
}
//用来筛选哪些坦克被选中的过滤方法
function selectTank(element:*, index:int, arr:Array)
{
    if(element.getBounds(this).intersects(rec)==true)
   {
        element.select=true;
       return true;
    }
    return false;
}
//取消坦克的选择状态的方法
function unSelect(element:*, index:int, arr:Array)
{
      element.select=false;
}
//移动坦克的方法
function moveTank(element:*, index:int, arr:Array)
{
    element.select=false;
    var randomX=targetPoint.x+Math.random()*150-75;
    var randomY=targetPoint.y+Math.random()*150-75;
    element.moveTo(randomX,randomY);
}
function clearArray(arr:Array)
{
    while(arr.length>0)
   {
       arr.shift();
    }
}

==================================================================================
坦克类

package
{
/**
* 一个简单的坦克类的模型
* 作者:闪刀浪子
* blog:http://hi.baidu.com/mr_ziqiang
*/
import flash.display.MovieClip
import flash.geom.Point
import flash.events.Event;

public class Tank extends MovieClip
{
   private var speed:int; //坦克的速度
   private var targetPoint:Point; //目标点
   private var _select:Boolean; //此坦克是否被选中,选中则显示被选中状态
   /**
   * Tank类构造函数
   * 初始化的时候随机产生一个坐标
   */
   public function Tank()
   {
    this.mouseChildren=false; //这里记得禁用子对象的鼠标点击
    this.x=300*Math.random()+10; //设置坦克出现的时候在左上角100*100大小范围类随机
    this.y=300*Math.random()+10;
    this.scaleX=this.scaleY=1+Math.random(); //体积大的就是红警中最牛的猛犸坦克了
    speed=(3-scaleX)*4; //呵呵,体积越大速度当然要越慢了
   }
   public function moveTo(tx:Number,ty:Number)
   {
    this.removeEventListener(Event.ENTER_FRAME,onMove);
    targetPoint=new Point(tx,ty);
    this.addEventListener(Event.ENTER_FRAME,onMove);
   }
   private function onMove(evt:Event)
   {
    var dx = targetPoint.x - this.x;
    var dy = targetPoint.y - this.y;
    var radian = Math.atan2(dy, dx);//求新角度  
    body.rotation=radian*180/Math.PI; //我的坦克类里有一个body的mc,方便转向的时候绿框不随着转
    if (dx * dx + dy * dy <= speed * speed)
    {
     this.x=targetPoint.x;
     this.y=targetPoint.y;
     this.removeEventListener(Event.ENTER_FRAME,onMove);
    }
    else
    {
     var vx = Math.cos(radian) * speed;//求增量
     var vy = Math.sin(radian) * speed;
    
     this.x += vx;
     this.y += vy;
    }   
   }
   public function get select():Boolean
   {
    return _select;
   }
   public function set select(isSelect:Boolean)
   {
    _select=isSelect;
    if(_select==true)
    {
     this.gotoAndStop(2);
    }
    else
    {
     this.gotoAndStop(1);
    }
   }  
}
}

  • 大小: 77 KB
  • 大小: 159.9 KB
  • 大小: 60.7 KB
分享到:
评论

相关推荐

    flash游戏长见程序教程

    即时战略游戏开发:Rectangle应用实战+Array中被你忽略的方法 类似弹弓的小游戏 由浅入深学习Flash制作高射炮游戏 由浅入深学习Flash制作物体弹跳游戏 游戏的任务事件处理解决方案 游戏基本操作:上下左右的移动(AS...

    面向对象设计模式应用+绘制类图+Java语言实现任务中的模式设计。

    )一个软件团队开发绘图系统,设计了圆对象(Circle)、矩形对象(Rectangle)、线对象(Line)都支持Draw()函数,即可以通过Draw()函数绘制图形。为了加快项目进度,将角度对象(Angle)绘制功能交给了合作团队...

    as3开发中的Rectangle类用法

    ### as3开发中的Rectangle类用法详解 #### 一、概览 在Adobe Flash平台的ActionScript 3.0(简称AS3)编程语言中,`Rectangle`类扮演着非常重要的角色,尤其是在处理图形和图像时。乍看之下,`Rectangle`类似乎...

    Rectangle 类的VC++程序源码

    在编程世界中,VC++是Microsoft开发的一个集成开发环境(IDE),主要用于编写使用C++语言的应用程序。这个“Rectangle 类的VC++程序源码”是一个基础的编程练习,旨在帮助初学者理解面向对象编程(OOP)的核心概念,...

    C# Rectangle基本用法和图片切割源码

    在C#编程语言中,`Rectangle`类是用于表示二维矩形区域的重要工具,它广泛应用于图形绘制、图像处理和游戏开发等领域。本教程将深入探讨`Rectangle`的基本用法,以及如何使用C#进行图片切割操作。我们将通过实例代码...

    qt quick实战开发

    在《Qt Quick实战开发》这本书中,你可以期待学习到以下关键知识点: 1. **QML基础**:了解QML的基本语法,包括变量、对象、属性、方法、信号和槽等概念。学习如何定义和使用QML元素,如Rectangle、Image、Text等,...

    Qt Qml 可拖动设置Rectangle大小Demo

    在本文中,我们将深入探讨如何在Qt Qml中创建一个可拖动调整大小的Rectangle示例。Qt是一个跨平台的应用程序开发框架,广泛用于桌面、移动和嵌入式设备。Qml是Qt的一个组成部分,它提供了一种声明式语言来构建用户...

    实验三:Java类与对象

    在本实验“Java类与对象”中,我们深入学习了Java面向对象编程的基本概念和实践。面向对象编程(OOP)是一种程序设计思想,它强调数据和操作数据的方法结合在一起,形成一个独立的对象,以此来组织和管理代码。与...

    MFC应用GDI+实现时钟

    5. **绘制时钟背景**:使用`SolidBrush`和`Rectangle`方法绘制时钟的背景,可以是圆形或矩形,取决于你的设计。 6. **绘制刻度和数字**:利用`Pen`和`LineTo`绘制时钟的刻度,`TextOut`或`DrawString`绘制数字。...

    Rectangle 矩形求面积 c++

    在实际的软件开发中,这种模式被广泛应用于各种复杂的问题,例如图形界面设计、游戏开发、数据结构等。 在北邮的C++实验课程中,类似的编程练习可以帮助学生巩固基本的C++语法,如变量声明、函数定义、输入/输出...

    面向对象实验通过编程和上机实验理解 Java 语言是如何体现面向对象

    在`Exercise7_1`中,我们创建了两个`Rectangle`对象,并通过`toString()`方法显示了它们的属性。而在`Exercise7_7`中,我们创建了两个`Time`对象,一个表示当前时间,另一个指定特定的毫秒数,然后通过`toString()`...

    C++ 对象 例题 rectangle clock

    ### C++ 对象 例题 rectangle clock #### 知识点概述 本示例通过两个C++类`rectangle`和`clock`的实现,展示了如何在C++中定义类、创建对象以及调用成员函数来操作这些对象。下面将详细分析这两个类的设计思路及其...

    面向对象核心技术.pdf

    面向对象编程(OOP)是目前软件开发中广泛使用的一种编程范式,它具有封装、继承和多态三个核心特性。在OOP中,类是创建对象的模板,继承则是实现类之间关系的一种机制。多态则提供了使用相同方法名调用不同方法的...

    Qt及Qt Quick开发实战精解(超清PDF)

    《Qt及Qt Quick开发实战精解》是一本深入讲解Qt Quick技术的专业书籍,特别适合对QML初学者和希望提升Qt应用开发技能的开发者。Qt是一个跨平台的应用程序开发框架,广泛应用于桌面、移动和嵌入式设备。Qt Quick则是...

    Ubuntu应用开发

    在Ubuntu应用开发中,QML被广泛应用于构建动态且响应式的用户界面。 ##### 3.1 QML结构 QML使用一种声明式的语法,通过定义对象及其属性来描述用户界面。例如,下面的代码展示了如何使用QML定义一个矩形: ```qml...

    Qt及Qt+Quick开发实战精解

    《Qt及Qt+Quick开发实战精解》这本书深入探讨了使用Qt框架进行应用程序开发的各种技术和策略,特别是结合Qt Quick技术的高效应用。Qt Quick是Qt框架的一个重要组成部分,它允许开发者快速创建美观、动态且响应迅速的...

    初学java之接口的一个小程序 Circle Rectangle

    根据给定的信息,我们可以总结出以下关于Java编程语言中的接口应用和类实现的相关知识点: ### 一、接口(Interface)的基础概念 在Java中,接口是一种完全抽象的类,它只包含方法签名(即方法名、参数列表以及...

    《Qt及Qt Quick开发实战精解》代码

    在《Qt及Qt Quick开发实战精解》的代码库中,你可能会发现以下类型的示例: 1. 基础控件:这些示例展示了如何使用QML创建基本的UI元素,如Rectangle、Text、Image等,以及如何设置它们的属性和样式。 2. 组件组合...

    Java面向对象程序设计(苏健版)

    public class Rectangle { //声明矩形类 int xTopLeft; //左上角横坐标 int yTopLeft; //左上角纵坐标 int xBottomRight; //右下角横坐标 int yBottomRight; //右下角纵坐标 int id; //唯一编号 static int ...

Global site tag (gtag.js) - Google Analytics