原理:

1、确保拖动对象在鼠标点上,如果不确定会出现瞬间移动的感觉

2、确保触碰到非通行区域,跳回到没触碰的点

源码:

import flash.events.MouseEvent;
import flash.events.Event; car.buttonMode = true;
car.addEventListener(MouseEvent.MOUSE_DOWN,downH); var diffX:Number, diffY:Number;
var canMove:Boolean = false; function downH(e){
diffX = car.x - mouseX;
diffY = car.y - mouseY;
canMove = true;
stage.addEventListener(MouseEvent.MOUSE_MOVE,moveH);
stage.addEventListener(MouseEvent.MOUSE_UP,upH);
addEventListener(Event.ENTER_FRAME, onEnter);
} function upH(E){
stage.removeEventListener(MouseEvent.MOUSE_UP,upH);
stage.removeEventListener(MouseEvent.MOUSE_MOVE,moveH);
removeEventListener(Event.ENTER_FRAME, onEnter);
} //确保在非通行区域可以拖动
function moveH(E){
var xx = car.x;
var yy = car.y;
if (canMove){
car.x = mouseX + diffX;
car.y = mouseY + diffY;
}
if (HitTest.complexHitTestObject(car,bg)){
car.x = xx;
car.y = yy;
}
} //确保车在鼠标点上
function onEnter(e:Event):void {
if (car.hitTestPoint(mouseX,mouseY)) {
if (!canMove) {
canMove = true;
diffX = car.x - mouseX;
diffY = car.y - mouseY;
}
}
else {
canMove = false;
}
}

  

触碰类网上提供的:

package
{
//像素级精确碰撞算法优化
//代码:Aone
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.DisplayObject;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
public class HitTest
{
public static var tileSize:int = 20;
public static function complexHitTestObject(target1:DisplayObject, target2:DisplayObject):Boolean
{
//横向缩小到tileSize尺寸需要的倍数,也就是期望检测的时候缩小到的尺寸。
var scaleX:Number = (target1.width < target2.width ? target1.width : target2.width) / tileSize
//纵向缩小到tileSize尺寸需要的倍
var scaleY:Number = (target1.height < target2.height ? target1.height : target2.height) / tileSize
//
//如果倍数小于1则按原始倍率也就是原始尺寸
scaleX = scaleX < 1 ? 1 : scaleX
scaleY = scaleY < 1 ? 1 : scaleY
//draw用point
var pt:Point=new Point()
//做2次draw时使用的颜色
var ct:ColorTransform=new ColorTransform()
ct.color=0xFF00000F
//原始尺寸下的重叠矩形
var oldHitRectangle:Rectangle=intersectionRectangle(target1, target2)
//用于存放缩放的重叠矩形
var hitRectangle:Rectangle= new Rectangle()
return complexIntersectionRectangle(target1, target2 , scaleX , scaleY , pt , ct , oldHitRectangle,hitRectangle,tileSize,tileSize).width != 0;
}
public static function intersectionRectangle(target1:DisplayObject, target2:DisplayObject):Rectangle
{
// If either of the items don't have a reference to stage, then they are not in a display list
// or if a simple hitTestObject is false, they cannot be intersecting.
if (!target1.root || !target2.root || !target1.hitTestObject(target2))
return new Rectangle();
// Get the bounds of each DisplayObject.
var bounds1:Rectangle = target1.getBounds(target1.root);
var bounds2:Rectangle= target2.getBounds(target2.root);
return bounds1.intersection(bounds2);
// // Determine test area boundaries.
// var intersection:Rectangle = new Rectangle();
// intersection.x = Math.max(bounds1.x, bounds2.x);
// intersection.y = Math.max(bounds1.y, bounds2.y);
// intersection.width = Math.min((bounds1.x + bounds1.width) - intersection.x, (bounds2.x + bounds2.width) - intersection.x);
// intersection.height = Math.min((bounds1.y + bounds1.height) - intersection.y, (bounds2.y + bounds2.height) - intersection.y);
// return intersection;
}
private static function complexIntersectionRectangle(target1:DisplayObject, target2:DisplayObject, scaleX:Number , scaleY:Number , pt:Point , ct:ColorTransform ,oldhitRectangle:Rectangle,hitRectangle:Rectangle,nowW:int,nowH:int):Rectangle
{
if (!target1.hitTestObject(target2))
return new Rectangle();
//根据纵横的缩小倍数来计算缩小的重叠矩形尺寸
hitRectangle.x = oldhitRectangle.x
hitRectangle.y = oldhitRectangle.y
hitRectangle.width = oldhitRectangle.width / scaleX
hitRectangle.height = oldhitRectangle.height / scaleY
//建立一个用来draw的临时BitmapData对象,尺寸为期望宽nowW,期望高nowH
var bitmapData:BitmapData=new BitmapData(nowW,nowH, true, 0);
//绘制对象1其缩放比例和位移量由getDrawMatrix()函数计算,并且把不透明处绘制为ct的颜色
bitmapData.draw(target1, getDrawMatrix(target1, hitRectangle , scaleX , scaleY ),ct);
//当纵横缩小比例不为1的时候把任何有色像素重新替换成ct的颜色0xFF00000F,原因为缩小的对象在进行纯色绘制的时候会有半透明像素产生,如果不加以重新替换会影响后面对象2的滤镜效果。
if(scaleX!=1&&scaleY!=1)
bitmapData.threshold(bitmapData,bitmapData.rect,pt,">",0,0xFF00000F)
//绘制对象2其缩放比例和位移量由getDrawMatrix()函数计算,并且把不透明处绘制为ct的颜色,并且模式为叠加。如此一来两个对象重叠的部分颜色值必定大于0xFF00000F。
bitmapData.draw(target2, getDrawMatrix(target2, hitRectangle , scaleX , scaleY ),ct, BlendMode.ADD);
//把所有颜色值大于0xFF00000F的部分(也就是重叠部分)重新替换为不透明红色方便后面getColorBoundsRect()方法计算尺寸。这里替换的原因是getColorBoundsRect()不支持范围取色而只支持单色计算。
//对象1缩放后可以重新替换掉透明色,但是对象2则无法使用同一方法,但是对象2由于也是经过缩放绘制也会有半透明像素,那么重叠部分虽然全部大于0xFF00000F,但未必是统一的。
var hits:int=bitmapData.threshold(bitmapData,bitmapData.rect,pt,">",0xFF00000F,0xFFFF0000)
//判断红色区域尺寸
var intersection:Rectangle=bitmapData.getColorBoundsRect(0xFFFFFFFF, 0xFFFF0000);
bitmapData.dispose();
//如果红色区域宽度不为0,即bitmapData中含有红色像素。此时说明对象1和对象2在此次判定中有重叠有碰撞
//如果纵横缩放比例有任意一个不是原始尺寸
//并且红色像素的数量比较少,对象1和对象2的碰撞面积比较小的话
if (intersection.width != 0 && (scaleX > 1 || scaleY > 1) && hits <= (scaleX+scaleY) * 1.5)
{
//由于bitmapData的宽高坐标都是以整数表示,那么经过缩放后取整的区域势必回又可能在取整的时候把真正可能产生碰撞的区域忽略。
//所以要进行下一次检测时候适当的把检测区域扩大xadd和yadd就是这个扩大的系数
var xadd:int = 0.5;
var yadd:int = 0.5;
//下次检测时候bitmapData的期望大小
//如果此次判定发现碰撞区域和bitmapData尺寸相同,那么在计算下次需要判断区域时候会和此次的区域相同,那么判断结果可能会和此次结果相同。这样则会引起堆栈上溢的情况,为了避免该情况发生,将缩小判断的尺寸扩大一倍进行再次检测。
var nextW:int = (intersection.width != nowW) ? tileSize : nowW * 2;
var nextH:int = (intersection.height != nowH) ? tileSize : nowH * 2;
//根据检测出来的缩的碰撞区域来计算未缩小的碰撞区域大小以方便下一次计算的时候缩小检测范围。
oldhitRectangle.x += (intersection.x - xadd) * scaleX;
oldhitRectangle.y += (intersection.y - yadd) * scaleY;
oldhitRectangle.width = (intersection.width + xadd*2) * scaleX;
oldhitRectangle.height = (intersection.height + yadd*2) * scaleY;
//根据检测期望缩小到的尺寸重新计算缩小倍率
scaleX = (oldhitRectangle.width / nextW)
scaleY = (oldhitRectangle.height / nextH)
//如果倍率小于2则直接按原始尺寸
scaleX = scaleX < 2 ? 1 : scaleX
scaleY = scaleY < 2 ? 1 : scaleY
//进行下一次判定
intersection = complexIntersectionRectangle(target1,target2, scaleX , scaleY ,pt,ct,oldhitRectangle,hitRectangle,nextW,nextH)
}
return intersection;
}
protected static function getDrawMatrix(target:DisplayObject, hitRectangle:Rectangle , scaleX:Number , scaleY:Number ):Matrix
{
var localToGlobal:Point;
var matrix:Matrix;
var rootConcatenatedMatrix:Matrix=target.root.transform.concatenatedMatrix;
localToGlobal=target.localToGlobal(new Point());
matrix=target.transform.concatenatedMatrix;
matrix.tx=(localToGlobal.x - hitRectangle.x) / scaleX;
matrix.ty=(localToGlobal.y - hitRectangle.y) / scaleY;
matrix.a=matrix.a / rootConcatenatedMatrix.a / scaleX ;
matrix.d=matrix.d / rootConcatenatedMatrix.d / scaleY;
return matrix;
}
}
}

  

AS3 在不规则区域内拖动的更多相关文章

  1. 【GIS新探索】算法实现在不规则区域内均匀分布点

    1 概要 在不规则区域内均匀分布点,这个需求初看可能不好理解.如果设想一下需求场景就比较简单了. 场景1:在某个地区范围内,例如A市区有100W人口,需要将这100W人口在地图上面相对均匀的标识出来. ...

  2. 【原】ios的hitTest方法以及不规则区域内触摸事件处理方法

    概述 在正常的使用场景中,我们处理了比较多的矩形区域内触摸事件,比如UIButton.UIControl.一般来说,这些控件的图形以及触摸区域都是矩形或者圆角矩形的.但是在一些特殊应用场景中我们有时不 ...

  3. ios的hitTest方法以及不规则区域内触摸事件处理方法

    概述 在正常的使用场景中,我们处理了比较多的矩形区域内触摸事件,比如UIButton.UIControl.一般来说,这些控件的图形以及触摸区域都是矩形或者圆角矩形的.但是在一些特殊应用场景中我们有时不 ...

  4. 【Unity游戏开发】UGUI不规则区域点击的实现

    一.简介 马三从上一家公司离职了,最近一直在出去面试,忙得很,所以这一篇博客拖到现在才写出来.马三在上家公司工作的时候,曾处理了一个UGUI不规则区域点击的问题,制作过程中也有一些收获和需要注意坑,因 ...

  5. UGUI实现不规则区域点击响应

    UGUI实现不规则区域点击响应 前言 大家吼啊!最近工作上事情特别多,没怎么打理博客.今天无意打开cnblog才想起该写点东西了.今天给大家讲一个Unity中不规则区域点击响应的实现方法,使用UGUI ...

  6. [OpenGL] 不规则区域的填充算法

    不规则区域的填充算法 一.简单递归 利用Dfs实现简单递归填充. 核心代码: // 简单深度搜索填充 (四连通) void DfsFill(int x, int y) { || y < || x ...

  7. OSPF --- 不规则区域实验

    OSPF不规则区域实验: 一.知识点整理: OSPF中路由器的角色(看图): 骨干路由器:路由器所有接口属于area 0  -->R3 非骨干路由器:路由器所有接口属于非area 0  --&g ...

  8. java/c# 判断点是否在多边形区域内

    java/c# 判断点是否在多边形区域内 年06月29日 ⁄ 综合 ⁄ 共 1547字 ⁄ 字号 小 中 大 ⁄ 评论关闭 最近帮别人解决了一个问题,如何判断一个坐标点,是否在多边形区域内(二维). ...

  9. 验证坐标在某片坐标区域内 php 代码

    之前碰到的这样一个需求,要将公司的服务范围在地图中显示出来,并将用户每天的访问坐标进行统计看有多少用户是在所能达到的服务范围半径内. 以下是PHP代码的实现 (仅验证坐标在某片坐标区域内) <? ...

随机推荐

  1. 产品思维&技术思维&工程思维

    产品思维 产品思维的起源是用户(或客户)价值.用户价值是通过技术手段以产品或服务的形态去解决用户的痛点,或带去爽点.毫无疑问,工程师在日常工作中应时刻关注并理清自己的工作与用户(或客户)价值的联系,并 ...

  2. tomcat源码阅读之单点登录

    一.SSO概念: 单点登录,Single Sign-On,简写为 SSO,是一个用户认证的过程,允许用户一次性进行认证后,就可访问系统中不同的应用:而无需要访问每个应用时,都重新输入用户和密码. 实现 ...

  3. php比较全的友好时间显示

    分享一个php友好的比较完成的时间格式化函数,包括‘刚刚’,'几秒之前',‘几分钟前’,'几小时前',几天前,几周前,几个月前等.调用方式很简单,是从ThinkSNS 里面拿出来的. /** * 友好 ...

  4. chrome 45以上flash被拦截的一种可能解决方案

    chrome 45以上不自动播放"非必要"flash的一种可能解决方案chrome 45以上flash被拦截的一种可能解决方案 问题 1.chrome 45以上(包含45)版本默认 ...

  5. php curl curl_getinfo()返回参数详解

    php curl请求在curl_exec()函数执行之后,可以使用curl_getinfo()函数获取CURL请求输出的相关信息,示例代码如下: curl_exec($ch);$info = curl ...

  6. POJ2127 LICS模板

    题目:http://poj.org/problem?id=2127 十分费劲地终于记录好了路径……用一个前驱. 这是 n^2 的LICS方法.其实就是 n ^ 2 log n 把“找之前的d [ j ...

  7. Hyper-V 虚拟机连网

    参考:http://www.cnblogs.com/chenxizhang/p/3188005.html(个人推荐) 参考:http://blog.csdn.net/elvis_0123/articl ...

  8. 启动servlet报错:The servlets named [DemoServlet] and [main.java.com.wlf.demo.servlet.DemoServlet] are both mapped to the url-pattern [/hello] which is not permitted

    先看具体错误日志: [2019-04-26 09:29:25,484] Artifact demo-servlet:war: Artifact is being deployed, please wa ...

  9. java web中获取各种路径

    一.获取项目路径: 1) String path = request.getContextPath() :// /TestMyEclipseString basePath = request.getS ...

  10. Excel 公式CORREL算出相关系数

    当对 N 个主体中的每一个变量进行观测时,CORREL 工作表函数可计算两个测量变量之间的相关系数.(缺少任何主体的观测值将导致该主体在分析中被忽略.)当 N 个主体中的每一个均具备两个以上的测量变量 ...