2018-11-07 15:59:28 n_moling 阅读数 212

首先,UI布置是这样的:

  

        点击右面按钮进行显示隐藏,开始的设想是这样的,显示的时候坐标为零,隐藏的话为-width,这样做的话,当UI自适应时,比如4:3的屏状态下,可能出现按钮也移动到了屏幕外的情况。

pnlLeft.DOMoveX(isDisplay ? 0 : -pnlLeft.GetComponent<RectTransform>().sizeDelta.x, 1f);

        然后就想到了修改pivot的想法,但是当代码实现时,发现,会出现瞬移,后测试发现,代码控制并不同于editor状态下的修改pivot,在代码中修改,坐标是不会随之改变的。

        所以直接采用了DOPivotX的方法:

pnlLeft.GetComponent<RectTransform>().DOPivotX (isDisplay ? 0 : 1, 1f);

 

2019-02-21 13:44:46 qinxinger 阅读数 299

导读

先总结一下这个阶段的工作,也是这篇博客要写的内容:

  1. 对于上一篇中的避障程序进行了改进;
  2. 实现的一种简单的地图实时显示方式;
  3. 写了一个的匹配程序。

接下来就这三点进行相对详细的介绍。

1.避障程序的改进

上一篇中的避障程序的思路简单说来就是:前方若有障碍就向左或者向右找到没有障碍的最近方向然后继续前进。在运行的过程中我发现这样会导致机器人会贴边走,如下图所示。
避障程序的改进
改进的策略就是在对正前方的距离进行限制的基础上,对左侧和右侧也加以约束。
在这里插入图片描述
脚本代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class avoidance : MonoBehaviour {

    public laser laser;
    public int delta_r_a = 0;
    public int delta_l_a = 0;
    public float security_distance;
    float security_distance_b;

    public GameObject symbol_B;
    
    //计算运动方差(?)现在还没有用到,我自己的思路也没有理清,可以忽略---2019.02.21
    public float COV_X ;
    public float COV_Z ;
    public float COV_A ;

    public float v = 0.5f;

    //public Slider v_slider;

    // Use this for initialization
    void Start () {
        COV_A = 0;
        COV_X = 0.00001f;
        COV_Z = 0.00001f;
        security_distance = 25;
        security_distance_b = 0;
        symbol_B = GameObject.Find("symbol_Text_B");
        //v_slider = GameObject.FindObjectOfType<Slider>();
        
    }
	
	// Update is called once per frame
	void Update () {

        if (laser.distance[0] >= security_distance && laser.distance[90] >= security_distance_b && laser.distance[270] >= security_distance_b)
        {
            transform.Translate(Random.Range(v - 0.3f, v + 0.3f), 0, 0);

            //transform.Translate(v * Mathf.Cos(-transform.rotation.eulerAngles.y), 0, v * Mathf.Sin(-transform.rotation.eulerAngles.y),Space.World);

            COV_X = COV_X + COV_A * Mathf.Sin(-transform.rotation.eulerAngles.y) * Mathf.Sin(-transform.rotation.eulerAngles.y);
            COV_Z = COV_Z + COV_A * Mathf.Cos(-transform.rotation.eulerAngles.y) * Mathf.Cos(-transform.rotation.eulerAngles.y);
        }
        else
        //if (laser.distance[0] < security_distance)
        {
            for (int i = 1; i <= 179; i++)
            {
                if (i <= 89)
                {
                    if (laser.distance[i] >= security_distance && laser.distance[i + 90] >= security_distance_b && laser.distance[i + 270] >= security_distance_b )
                    {
                        delta_l_a = i;
                        break;
                    }
                }
                else
                {
                    if (laser.distance[i] >= security_distance && laser.distance[i - 90] >= security_distance_b && laser.distance[i + 90] >= security_distance_b )
                    {
                        delta_l_a = i;
                        break;
                    }
                }

            }

            for (int i = 359; i > 180; i--)
            {
                if (i >= 270)
                {
                    if (laser.distance[i] >= security_distance && laser.distance[i - 90] >= security_distance_b  && laser.distance[i - 270] >= security_distance_b )
                    {
                        delta_r_a = 360 - i;
                        break;
                    }
                }
                else
                {
                    if (laser.distance[i] >= security_distance && laser.distance[i - 90] >= security_distance_b  && laser.distance[i + 90] >= security_distance_b )
                    {
                        delta_r_a = 360 - i;
                        break;
                    }
                }
            }

            if (delta_l_a * delta_r_a != 0)
            {
                if (delta_l_a < delta_r_a)
                {
                    transform.Rotate(0, -1.0f + Random.Range(-0.5f, 0.5f), 0);
                    COV_A = COV_A + 0.05f;
                }
                if (delta_l_a >= delta_r_a)
                {
                    transform.Rotate(0, 1.0f + Random.Range(-0.5f, 0.5f), 0);//这样轨迹更平滑,且此数值应与laser精度相同
                    COV_A = COV_A + 0.05f;
                }
                //if (delta_l_a < delta_r_a)
                //    transform.Rotate(0, -delta_l_a, 0);
                //if (delta_l_a >= delta_r_a)
                //    transform.Rotate(0, delta_r_a, 0);

            }
            else
            {
                if (delta_l_a != 0)
                    transform.Rotate(0, -1.0f + Random.Range(-0.5f, 0.5f), 0);
                if (delta_r_a != 0)
                    transform.Rotate(0, 1.0f + Random.Range(-0.5f, 0.5f), 0);

                //if (delta_l_a != 0)
                //    transform.Rotate(0, -delta_l_a, 0);
                //if (delta_r_a != 0)
                //    transform.Rotate(0, delta_r_a, 0);

            }

        }     
    }
}

2.地图的显示

这是一个unity3d的技术问题,我之前想用Particle System实现,然而随着采集到的点的增加Particle System会占用大量的计算资源,导致运行画面的卡顿。显然,这是由我对unity3d不够熟悉造成的。受占用栅格地图的启发,加上查到的资料我发现可以用sprite和image实现。效果图如下:

地图的显示
详细操作:

  1. 新建一个image,这里我命名为bitmap
    地图的显示
  2. 新建脚本,将脚本拖拽到bitmap上,代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class bitmap : MonoBehaviour {

    public GameObject distance_Dect;

    public laser laser;
    private Image image;

    int width = 501;
    int height = 501;

    public int[,] map=new int[501,501];

    Texture2D texture2D;

    int u, v;

    Vector3 temp_pos;
    
	// Use this for initialization
	void Start () {
	
        distance_Dect = GameObject.Find("distance_Dect");
        laser = distance_Dect.GetComponent<laser>();
        image = GetComponent<Image>();

        texture2D = new Texture2D(width, height);

        for (int i = 0; i < 501; i++)
        {
            for (int j = 0; j < 501; j++)
            {
                texture2D.SetPixel(i, j, Color.black);
                map[i, j] = 0;
            }
        }

        texture2D.Apply();

        Sprite sprite = Sprite.Create(texture2D, new Rect(0, 0, texture2D.width, texture2D.height), new Vector2(500.0f, 500.0f));

        image.sprite = sprite;
    }
	
	// Update is called once per frame
	void Update () {

        for (int i = 0; i < 360; i++)
        {
            if (laser.distance[i] != laser.maxDistance)
            {
                u = (int)laser.hitPoints[i].x;
                v = (int)laser.hitPoints[i].z;
                texture2D.SetPixel(u, v, Color.white);

                map[u, v] = 1;
            }
        }
        texture2D.Apply();

        Sprite sprite = Sprite.Create(texture2D, new Rect(0, 0, texture2D.width, texture2D.height), new Vector2(0.5f, 0.5f));

        image.sprite = sprite;
    }
}

地图的显示

3.匹配程序

匹配程序很不成熟,为了验证处理的速度所以写了出来,还没有后端处理能力贴出来暂时放在这。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

//匹配是由触发条件的
public class icp_matching : MonoBehaviour {

    public GameObject distan_Dect;
    
    public laser laser;

    int[,] map=new int[501,501];
    

    int[,] submap=new int[201,201];

    public int match_range;

    public Text text;

    Vector3 result;//score,u,v

    float tmp = 0;

    int count;

    // Use this for initialization
    void Start () {
        match_range = 3;

        distan_Dect = GameObject.Find("distance_Dect");
        laser = distan_Dect.GetComponent<laser>();

        
        //全局地图初始化
        for (int i = 0; i < 501; i++)
        {
            for (int j = 0; j < 501; j++)
            {
                map[i, j] = 0;
            }
        }

    }
    void Update()
    {
        text.text = result.ToString()+count.ToString()+"  "+(result.x/count).ToString();
        

        tmp = tmp + Time.deltaTime;

        if (tmp > 1)
        {
            tmp = 0;
            match();
        }

        //更新全局地图
        for (int i = 0; i < 360; i++)
        {
            if (laser.distance[i] != laser.maxDistance)
            {
                map[(int)laser.hitPoints[i].x, (int)laser.hitPoints[i].z] = 1;
            }
        }

    }



    void match()
    {
         count = 0;

        //子地图初始化
        for (int i = 0; i < 200; i++)
            for (int j = 0; j < 200; j++)
                submap[i, j] = 0;


        //载入当前测得的子地图
        for (int i = 0; i < 360; i++)
        {
            if (laser.distance[i] < laser.maxDistance)
            {
                //Debug.Log((int)(laser.hitPoints[i].x));
                //Debug.Log((int)(laser.hitPoints[i].z));
                submap[(int)(laser.hitPoints[i].x - distan_Dect.transform.position.x + 100), (int)(laser.hitPoints[i].z - distan_Dect.transform.position.z + 100)] = 1;
                count++;
            }
        }

        //计算

        result = new Vector3Int(0, 0, 0);//score,u,v

        for (int m = -match_range; m <= match_range; m++)
        {
            for (int n = -match_range; n <= match_range; n++)
            {
                int score = 0;
                int u = (int)distan_Dect.transform.position.x - 100 + m;
                int v = (int)distan_Dect.transform.position.z - 100 + n;

                if (u + 200 <= 500 && u >= 0 && v + 200 <= 500 && v >= 0)
                {
                    for (int i = 0; i < 201; i++)
                    {
                        for (int j = 0; j < 201; j++)
                        {
                            if (submap[i, j] * map[u + i, v + j] != 0)
                            {
                                score++;
                            }
                        }
                    }

                    if (score > result.x)
                    {
                        result.x = score;
                        result.y = u + 100;
                        result.z = v + 100;
                    }
                }

            }
        }
        
    }
}

2018-12-25 11:25:32 lk1822791193 阅读数 222

思路

拿向上贴边隐藏举例:

通过判断窗体上边框的坐标,来判断窗体是否贴边,然后通过窗体的向上移动,实现隐藏!

 

窗体坐标的机制:

当窗体向上贴边的时候,它的Top坐标就为0,再向上走,就是负数,其他坐标也是这样的。

 

代码

两行代码实现隐藏:

//窗体隐藏的方法
//鼠标移出事件
private void from_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
    //三个条件判断
    // 1. 窗体Top坐标小于2时候(隐藏触发的条件)
    // 2. Top的坐标>-Height+3(隐藏停止的条件,+3是为了露出3像素的据类,方便用户找到隐藏的窗体)
    // 3. IsMouseOver 鼠标不在窗体上的时候
    while (Top <= 2 && Top > -Height + 3 && !IsMouseOver)
    {
        //窗体Top不断-1
        Top -= 1;
    }
            
}

 

//窗体显示方法
//鼠标进入窗体事件
private void from_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
{
    //如果窗体的上坐标小于-1
    // 解释:当窗体的Top坐标 =-1 的时候,窗体就不向下移动了
    //      这样就解决了,窗体上下跳的问题
    while (this.Top < -1 )
    //窗体的上坐标不断 +1
    this.Top += 1;
}

 

别看这几句代码,够你研究一会,但是研究完了,思路清晰了,其实也就很简单了!嘿嘿!

感谢大家阅读,如有不足,欢迎指出!感觉有所收获,点个赞鼓励一下!

 

2019-08-03 20:01:55 wing_summer 阅读数 25

大家好,最近我想用VB.net实现贴边隐藏,结果网上只有思路,没有明确的源码,故本人总结并给出相应的代码示例下载。

相关代码使用:

一、My.Computer.Screen.Bounds

该代码可获取屏幕的边界数据,比如屏幕的宽和高。
获取屏幕宽度: My.Computer.Screen.Bounds.Width
获取屏幕高度: My.Computer.Screen.Bounds.Height

二、 System.Windows.Forms.Cursor.Position

该代码可获取鼠标的位置(X,Y)
获取鼠标X坐标: System.Windows.Forms.Cursor.Position.X
获取鼠标Y坐标: System.Windows.Forms.Cursor.Position.Y

三、添加Timer控件增加收缩效果

四、鼠标是否进入窗体判断

If Me.Top<= 0 Then FrmLocaction=FrmTop 'Top贴边优先

移动至

If Me.Top >= My.Computer.Screen.Bounds.Height - Me.Height Then FrmLocaction = FrmBottom 

后面,否则是Left贴边优先(程序员们都懂滴)

2012-04-11 09:01:35 chenlycly 阅读数 1728

        由于现有的系统中加入了即时通讯的功能,所以需要实现类似于QQ的一些常用的功能,这其中就包括QQ的贴边掩藏功能。于是查看了网上很多相关的话题,结合现有系统的实际需求,实现了类似QQ的贴边掩藏功能。

       首先要仔细研究一下QQ的贴边掩藏时的一些细节:贴边掩藏实在何时触发的?如何自动实现掩藏的?将光标移到掩藏边界时窗口又是如何自动伸展出来的?于是带着这些想知道的问题,在操作QQ窗口过程中,仔细观察了贴边掩藏的方式和界面效果。研究对象是最新版的QQ2011,经观察发现:

       1、贴边掩藏有三种方式:向上掩藏、向左掩藏和向右掩藏。当然向下掩藏也可以实现,结合用户的使用习惯,估计没有太大的实用价值,所以就没实现了。

       2、贴边掩藏的触发条件:通过检测拖动QQ窗口时的光标与桌面边界的距离来决定是否需要掩藏窗口,当小于指定的值后才会触发窗口掩藏。具体的,向上掩藏就是检测拖动QQ窗口时的光标距离桌面上边界的距离;向左掩藏则是检测与桌面左边界的距离;向右掩藏则是检测与桌面右边界的距离。

       3、主窗体贴边掩藏后,在对应的桌面边界上会有一个boarder,而且这部分窗体属于主窗体的非客户区域。当我们将光标移到该boarder上,主窗体则会自动显示出来;在显示后,当我们将光标从主窗体中移走后,主窗体则会自动掩藏起来。

       4、向上掩藏,掩藏前后窗体的大小没有改变。向左或右掩藏,窗体的宽度没有改变,窗体的高度则发生了改变:从桌面的高度方向看,掩藏后的窗口充满整个桌面客户区。要退出掩藏状态,只要将窗口拖到客户区以内就可以了。对于向左或右掩藏,在退出掩藏状态后会恢复之前的窗口高度。

        事实上,这里说的掩藏不是真正地将窗口Hide起来,而是将窗口移动到桌面外的区域,给人一种窗口被掩藏的感觉。界面操作细节和效果已经有结果了,那么接下来就是研究怎么通过具体的代码来实现了。

div贴边运动代码

阅读数 626

没有更多推荐了,返回首页