游戏摇杆

using System;
using UnityEngine;
using UnityEngine.EventSystems;

public class JoyStick : MonoBehaviour
{
    enum JoyStickState
    {
        None,
        OnEnter,
        OnStay,
        OnLeave,
    }

    public Transform m_background;
    public Transform m_foreground;
    public Transform m_arrow;

    public float m_radius;

    public Action onEnter;
    public Action<Vector2> onMove;
    public Action onLeave;

    private JoyStickState _js_state;
    private JoyStickState js_state
    {
        get
        {
            return _js_state;
        }
        set
        {
            if (_js_state != value)
            {
                switch (value)
                {
                    case JoyStickState.OnEnter:
                        m_timer = Time.time;
                        break;
                    case JoyStickState.OnStay:
                        SetActive(true, point_pre);
                        break;
                    case JoyStickState.OnLeave:
                        SetActive(false, Vector3.zero);
                        break;
                    default:
                        break;
                }
                _js_state = value;
            }
        }
    }

    private Touch m_touch;
    private int m_touch_ID;

    private float m_timer;
    private Vector3 m_position;

    private Vector2 point_pre;
    private Vector2 point_now;

    public bool m_force = true;

    private void Awake()
    {
        SetActive(false, Vector3.zero);
    }

    private void Update()
    {
#if UNITY_IPHONE || UNITY_ANDROID && !UNITY_EDITOR
        if (Input.touchCount > 0)
        {
            for (int i = 0; i < Input.touchCount; i++)
            {
                m_touch = Input.GetTouch(i);

                switch (m_touch.phase)
                {
                    case TouchPhase.Began:
                        if (!EventSystem.current.IsPointerOverGameObject(m_touch.fingerId))
                        {
                            if (m_touch.position.x <= Content.screen_width_half)
                            {
                                if (PlayerController.instance.canMove)
                                {
                                    m_touch_ID = m_touch.fingerId;
                                    if (onEnter != null)
                                    {
                                        onEnter();
                                    }
                                    js_state = JoyStickState.OnEnter;
                                }
                            }
                        }
                        break;
                    case TouchPhase.Stationary:
                        if (m_touch.fingerId == m_touch_ID)
                        {
                            if (js_state == JoyStickState.OnEnter)
                            {
                                if (Time.time - m_timer > Time.deltaTime)
                                {
                                    point_pre = m_touch.position;
                                    js_state = JoyStickState.OnStay;
                                }
                            }
                            else if (js_state == JoyStickState.OnStay)
                            {
                                point_now = m_touch.position;
                                Vector2 vector = Get_Postion(point_now, point_pre);
                                Vector3 rotation = Get_Rotation(vector);
                                m_foreground.localEulerAngles = rotation;
                                m_arrow.localPosition = vector;

                                if (m_force && onMove != null)
                                {
                                    onMove(vector / m_radius);
                                }
                            }
                        }
                        break;
                    case TouchPhase.Moved:
                        goto case TouchPhase.Stationary;
                    case TouchPhase.Canceled:
                        if (m_touch.fingerId == m_touch_ID)
                        {
                            if (js_state != JoyStickState.OnLeave)
                            {
                                if (onLeave != null)
                                {
                                    onLeave();
                                }
                                js_state = JoyStickState.OnLeave;
                            }
                        }
                        break;
                    case TouchPhase.Ended:
                        goto case TouchPhase.Canceled;
                    default:
                        break;
                }
            }
        }
#else
        if (Input.GetMouseButtonDown(0))
        {
            if (!EventSystem.current.IsPointerOverGameObject())
            {
                //实现左半屏触发
                if (Input.mousePosition.x <= Content.screen_width_half)
                {
                    if (PlayerController.instance.canMove)
                    {
                        if (onEnter != null)
                        {
                            onEnter();
                        }
                        js_state = JoyStickState.OnEnter;
                    }
                }
            }
        }
        if (Input.GetMouseButton(0))
        {
            if (js_state == JoyStickState.OnEnter)
            {
                //等待一帧,区别射线的触发
                if (Time.time - m_timer > Time.deltaTime)
                {
                    point_pre = Input.mousePosition;
                    js_state = JoyStickState.OnStay;
                }
            }
            else if (js_state == JoyStickState.OnStay)
            {
                point_now = Input.mousePosition;
                Vector2 vector = Get_Postion(point_now, point_pre);
                Vector3 rotation = Get_Rotation(vector);
                m_foreground.localEulerAngles = rotation;
                m_arrow.localPosition = vector;

                if (m_force && onMove != null)
                {
                    onMove(vector / m_radius);
                }
            }
        }
        if (Input.GetMouseButtonUp(0))
        {
            if (js_state != JoyStickState.OnLeave)
            {
                if (onLeave != null)
                {
                    onLeave();
                }
                js_state = JoyStickState.OnLeave;
            }
        }
#endif
    }

    /// <summary>
    ///强制中断操纵杆[优先级小于攻击]
    /// </summary>
    public void BreakeJoyStick()
    {
        if (js_state != JoyStickState.OnLeave)
        {
            if (onLeave != null)
            {
                onLeave();
            }
            js_state = JoyStickState.OnLeave;
        }
    }

    private void SetActive(bool state, Vector3 pos)
    {
        if (state)
        {
            pos.x -= Content.screen_width_half;
            pos.y -= Content.screen_height_half;
            pos.x *= Content.screen_width_ratio;
            pos.y *= Content.screen_height_ratio;
            m_background.localPosition = pos;
        }

        GameObject go = m_background.gameObject;
        if (go.activeSelf != state)
        {
            go.SetActive(state);
        }
    }

    private Vector3 Get_Postion(Vector3 point_now, Vector3 point_pre)
    {
        Vector3 vector = point_now - point_pre;

        float ratio = 1;
        float distance = Vector3.Distance(point_now, point_pre);
        if (distance >= m_radius)
        {
            ratio = m_radius / distance;
        }

        return vector * ratio;
    }

    private Vector3 Get_Rotation(Vector2 position)
    {
        Vector3 dir = new Vector3(position.x, 0, position.y);
        Vector3 angle = Quaternion.LookRotation(dir, Vector3.up).eulerAngles;
        return Vector3.forward * angle.y * -1f;
    }
}
View Code

 

转载于:https://www.cnblogs.com/Joke-crazy/p/9947196.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Vue 中实现游戏摇杆,可以考虑以下步骤: 1. 创建一个组件,用于显示游戏摇杆和响应用户操作。 2. 在组件中,可以使用 `canvas` 元素绘制游戏摇杆的外框和摇杆。 3. 在 `mounted` 钩子函数中,监听 `canvas` 元素的 `touchstart`、`touchmove`、`touchend` 事件,根据用户手指的操作,计算出摇杆的位置和偏移量。 4. 在 `touchmove` 事件中,需要不断重新绘制摇杆的位置,以及根据位置计算出摇杆的偏移量。 5. 在组件内定义一个 `joystick` 对象,用于保存当前摇杆的位置和偏移量,可以通过 `props` 属性将其传递给父组件。 6. 在 `touchend` 事件中,需要重置 `joystick` 对象的位置和偏移量。 下面是一个简单的 Vue 游戏摇杆组件示例代码: ```html <template> <div> <canvas ref="canvas" /> </div> </template> <script> export default { props: { radius: { type: Number, default: 50 }, bgColor: { type: String, default: '#eee' }, fgColor: { type: String, default: '#999' } }, data() { return { joystick: { x: 0, y: 0, dx: 0, dy: 0 } } }, mounted() { this.canvas = this.$refs.canvas this.ctx = this.canvas.getContext('2d') this.canvas.width = this.radius * 2 this.canvas.height = this.radius * 2 this.canvas.addEventListener('touchstart', this.touchStart) this.canvas.addEventListener('touchmove', this.touchMove) this.canvas.addEventListener('touchend', this.touchEnd) this.draw() }, methods: { draw() { this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height) // 绘制背景圆 this.ctx.beginPath() this.ctx.arc(this.radius, this.radius, this.radius, 0, 2 * Math.PI) this.ctx.fillStyle = this.bgColor this.ctx.fill() // 绘制摇杆圆 this.ctx.beginPath() this.ctx.arc( this.radius + this.joystick.dx, this.radius + this.joystick.dy, this.radius / 2, 0, 2 * Math.PI ) this.ctx.fillStyle = this.fgColor this.ctx.fill() requestAnimationFrame(this.draw) }, touchStart(e) { e.preventDefault() const rect = this.canvas.getBoundingClientRect() const touch = e.touches[0] this.joystick.x = touch.clientX - rect.left this.joystick.y = touch.clientY - rect.top }, touchMove(e) { e.preventDefault() const rect = this.canvas.getBoundingClientRect() const touch = e.touches[0] const x = touch.clientX - rect.left const y = touch.clientY - rect.top const dx = x - this.joystick.x const dy = y - this.joystick.y const maxDist = this.radius / 2 if (Math.sqrt(dx * dx + dy * dy) > maxDist) { const angle = Math.atan2(dy, dx) this.joystick.dx = maxDist * Math.cos(angle) this.joystick.dy = maxDist * Math.sin(angle) } else { this.joystick.dx = dx this.joystick.dy = dy } }, touchEnd(e) { e.preventDefault() this.joystick.dx = 0 this.joystick.dy = 0 } } } </script> ``` 在父组件中,可以使用 `<game-joystick>` 标签引入游戏摇杆组件,并通过 `props` 属性设置游戏摇杆的半径、背景色和前景色。 ```html <template> <div> <game-joystick :radius="50" bgColor="#eee" fgColor="#999" @joystickmove="onJoystickMove" /> </div> </template> <script> import GameJoystick from './GameJoystick.vue' export default { components: { GameJoystick }, methods: { onJoystickMove(joystick) { // 处理游戏摇杆移动事件 } } } </script> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值