zoukankan      html  css  js  c++  java
  • cocos lua 地图拖动及缩放

    吐血写了这个地图拖动及缩放 
    单指拖动 双指缩放 防出界

    self._map_node  --大地图
    self._map_size = {x, y} --大地图大小
    self._map_scale --大地图缩放
    self._map_min_scale --大地图最小缩放
    self._map_max_scale --大地图最大缩放
    -- 点击监听
    local listener = cc.EventListenerTouchOneByOne:create()
    listener:setSwallowTouches(false)
    -- 点击列表
    local touchPoint = {}
    -- 第一个点击初始位置
    local pos_s
    local function onTouchBegan(touch, event)
        -- 最多处理两指
        table.insert(touchPoint, {id=touch:getId(), pos=touch:getLocation()})
        if #touchPoint > 2 then
            table.remove(touchPoint, #touchPoint)
            return false
        end
        pos_s = touch:getLocation()
        return true
    end
    
    local function onTouchMoved(touch, event)
        if #touchPoint == 1 then
            local pos = touch:getLocation()
            -- 移动的位置
            local moveX = pos_s.x-pos.x
            local moveY = pos_s.y-pos.y
            -- 移动到的位置
            local toX = self._map_node:getPositionX()-moveX
            local toY = self._map_node:getPositionY()-moveY
            -- 变化之后的四角坐标
            local posLeft = self._map_size.x/2*self._map_scale-toX --左坐标
            local posBottom = self._map_size.y/2*self._map_scale-toY -- 下坐标
            local posRight = self._map_size.x/2*self._map_scale+g_visibleSize.width-toX -- 右坐标
            local posTop = self._map_size.y/2*self._map_scale+g_visibleSize.height-toY -- 上坐标
            -- 调整位置 防止出框
            if posLeft < 0 then toX = self._map_size.x/2*self._map_scale end --
            if posBottom < 0 then toY = self._map_size.y/2*self._map_scale end --
            if posRight > self._map_size.x*self._map_scale then toX = g_visibleSize.width-self._map_size.x/2*self._map_scale end --
            if posTop > self._map_size.y*self._map_scale then toY = g_visibleSize.height-self._map_size.y/2*self._map_scale end --
            -- 跳到位置
            self._map_node:setPosition(toX, toY)
            pos_s = pos
        else
            -- 两个原始坐标
            local touch1 = touchPoint[1]
            local touch2 = touchPoint[2]
            -- 放入新坐标
            if touch:getId() == touch1.id then
                touchPoint[1] = {id=touch:getId(), pos=touch:getLocation()} 
            else
                touchPoint[2] = {id=touch:getId(), pos=touch:getLocation()}
            end
            -- 两个坐标相对位移
            local posX1 = touchPoint[1].pos.x - touch1.pos.x
            local posY1 = touchPoint[1].pos.y - touch1.pos.y
            local posX2 = touchPoint[2].pos.x - touch2.pos.x
            local posY2 = touchPoint[2].pos.y - touch2.pos.y
            -- 距离变化
            local distance_before = (touch1.pos.x-touch2.pos.x)*(touch1.pos.x-touch2.pos.x)+(touch1.pos.y-touch2.pos.y)*(touch1.pos.y-touch2.pos.y)
            local distance_after = (touchPoint[1].pos.x-touchPoint[2].pos.x)*(touchPoint[1].pos.x-touchPoint[2].pos.x)+(touchPoint[1].pos.y-touchPoint[2].pos.y)*(touchPoint[1].pos.y-touchPoint[2].pos.y)
            local distance_diff = distance_after - distance_before
            -- 原来的锚点
            local anchorPoint_before = self._map_node:getAnchorPoint()
            -- 距离左下角距离
            local dis_left = self._map_size.x*anchorPoint_before.x*self._map_scale-self._map_node:getPositionX()+(touchPoint[1].pos.x+touchPoint[2].pos.x)/2
            local dis_bottom = self._map_size.y*anchorPoint_before.y*self._map_scale-self._map_node:getPositionY()+touch1.pos.y+(touchPoint[1].pos.y+touchPoint[2].pos.y)/2
            -- 以两点中心为新的锚点
            local anchorPoint_after = cc.p(dis_left/self._map_scale/self._map_size.x, dis_bottom/self._map_scale/self._map_size.y)
            self._map_node:setAnchorPoint(anchorPoint_after)
            -- 距离差
            local dis_X = self._map_size.x*(anchorPoint_before.x-anchorPoint_after.x)*self._map_scale
            local dis_Y = self._map_size.y*(anchorPoint_before.y-anchorPoint_after.y)*self._map_scale
            -- 位置纠正
            self._map_node:setPosition(self._map_node:getPositionX()-dis_X, self._map_node:getPositionY()-dis_Y)
            -- 缩放
            self._map_scale = self._map_scale + distance_diff/1000000
            -- 限制
            if self._map_scale < self._map_min_scale then self._map_scale = self._map_min_scale end
            if self._map_scale > self._map_max_scale then self._map_scale = self._map_max_scale end
            self._map_node:setScale(self._map_scale)
            -- 防止出界 移动补位
            -- 左侧空白距离
            local posX_left = self._map_size.x*anchorPoint_after.x*self._map_scale-self._map_node:getPositionX() 
            if posX_left < 0 then
                self._map_node:setPositionX(self._map_size.x*anchorPoint_after.x*self._map_scale)
            end
            -- 下侧空白距离
            local posX_bottom = self._map_size.y*anchorPoint_after.y*self._map_scale-self._map_node:getPositionY() 
            if posX_bottom < 0 then
                self._map_node:setPositionY(self._map_size.y*anchorPoint_after.y*self._map_scale)
            end
            -- 右侧空白距离
            local posX_right = self._map_size.x*(1-anchorPoint_after.x)*self._map_scale+self._map_node:getPositionX()-g_visibleSize.width 
            if posX_right < 0 then
                self._map_node:setPositionX(g_visibleSize.width-self._map_size.x*(1-anchorPoint_after.x)*self._map_scale)
            end
            -- 上侧空白距离
            local posX_top = self._map_size.y*(1-anchorPoint_after.y)*self._map_scale+self._map_node:getPositionY()-g_visibleSize.height 
            if posX_top < 0 then
                self._map_node:setPositionY(g_visibleSize.height-self._map_size.y*(1-anchorPoint_after.y)*self._map_scale)
            end
        end
    end
    
    local function onTouchEnded(touch, event)
        -- 清除松开的点击
        if touchPoint[1].id == touch:getId() then
            table.remove(touchPoint, 1)
        elseif touchPoint[2].id == touch:getId() then
            table.remove(touchPoint, 2)
        end
        -- 将剩下的点击设置为第一个点击位置
        if #touchPoint == 1 then
            -- 恢复锚点
            local anchorPoint_before = self._map_node:getAnchorPoint()
            local anchorPoint_after = cc.p(0.5, 0.5)
            self._map_node:setAnchorPoint(anchorPoint_after)
            local dis_X = self._map_size.x*(anchorPoint_before.x-anchorPoint_after.x)*self._map_scale
            local dis_Y = self._map_size.y*(anchorPoint_before.y-anchorPoint_after.y)*self._map_scale
            self._map_node:setPosition(self._map_node:getPositionX()-dis_X, self._map_node:getPositionY()-dis_Y)
            pos_s = touchPoint[1].pos
        end
    end
    
    listener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN)
    listener:registerScriptHandler(onTouchMoved, cc.Handler.EVENT_TOUCH_MOVED)
    listener:registerScriptHandler(onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED)    
    self:getEventDispatcher():addEventListenerWithSceneGraphPriority(listener, self._map_node)

    介于PC的话不能多点触控 所以特意写了一个键盘监听来模拟多点触控的行为 
    不过对于cc.Touch这个C++类 在存在table中之后会使getId()方法失效 不知道是什么原因 所以干脆就把具体数据存在了表里 
    cc.Touch在使用setTouchInfo()方法的时候 posY的值莫名会变 不知道什么原因 准备在C++中下断点看看- -

    local posX = 300
    local posY = 500
    local pos_move = 1
    
    -- 按键监听
    local listener_key = cc.EventListenerKeyboard:create()
    
    local key_Q = 140
    local key_F = 129
    local ket_E = 128
    local key_W = 146
    local key_S = 142
    local key_A = 124
    local key_D = 127
    local key_R = 141
    local key_T = 143
    
    local function keyToMove(index)
        local touch = cc.Touch:new()
        touch:setTouchInfo(1, posX, posY)
        local event = cc.EventTouch:new()
        event:setEventCode(index)
        if index == 0 then
            onTouchBegan(touch, event)
        elseif index == 1 then
            onTouchMoved(touch, event)
        elseif index == 2 then
            onTouchEnded(touch, event)
        end
    end
    
    local function onKeyReleased(keyCode, event)
        print("键盘操作 keyCode="..keyCode)
        if key_Q == keyCode then
            print("初始化")
            posX = 500
            posY = 500
        elseif key_F == keyCode then
            print("按下另一个鼠标")
            keyToMove(0)
        elseif ket_E == keyCode then
            print("松开另一个鼠标")
            keyToMove(2)
        elseif key_W == keyCode then
            print("向上移动")
            posY = posY - pos_move
            keyToMove(1)
        elseif key_S == keyCode then
            print("向下移动")
            posY = posY + pos_move
            keyToMove(1)
        elseif key_A == keyCode then
            print("向左移动")
            posX = posX - pos_move
            keyToMove(1)
        elseif key_D == keyCode then
            print("向右移动")
            posX = posX + pos_move
            keyToMove(1)
        end
    end
    
    listener_key:registerScriptHandler(onKeyReleased, cc.Handler.EVENT_KEYBOARD_RELEASED )
    self:getEventDispatcher():addEventListenerWithSceneGraphPriority(listener_key, self)
  • 相关阅读:
    JS 表单submit() 提交无效的问题
    thinkphp中连接oracle时封装的方法无法用
    Struts2 开发流程(转)
    oracle wm_concat(column)函数的使用(转)
    js点击按钮后显示时间自动减少提示
    Windows Server 2008 R2安装过程
    Spring学习之旅(1) 第一个Controller
    Groovy系列 Groovy集合
    Groovy系列 安装Groovy
    VMWare实现共享目录
  • 原文地址:https://www.cnblogs.com/PandaQ/p/9234745.html
Copyright © 2011-2022 走看看