原文请猛戳:
http://galoisplusplus.coding.me/blog/2016/01/16/tips-in-cocos2d-x-game/

这次分享一个简单的小功能,用cocos2d-x实现tips效果,作为之前一篇博文的后续。tips的行为很简单:点击某个node(我们不妨称它为target_node)触发,当点击区域在target_node范围时出现tips,否则隐藏tips(有些情况需要指定有效点击范围不在某些node中,我们把这些node称为exclude_nodes);当target_node位于屏幕左半边时,tips出现在target_node右侧;否则tips就出现在target_node左侧,tipstarget_node有一个固定的水平间距(我们不妨定义为DEFAULT_TIPS_disT);tipstarget_node底部对齐,但tips不能超过屏幕范围。

不废话,先上代码:

function setupTips(params)
    local targetNode = params.target_node
    local tips = params.tips
    local excludeNodes = params.exclude_nodes or {}

    local DEFAULT_TIPS_disT = 10
    local TIPS_ZORDER = 1000

    if tolua.isnull(targetNode) or tolua.isnull(tips) then
        return
    end

    tips:setVisible(false)
    targetNode:setTouchEnabled(false)
    display.getRunningScene():addChild(tips,TIPS_ZORDER)

    targetNode:addNodeEventListener(cc.NODE_EVENT,function(event)
        if event.name == "exit" then
            local scene = display.getRunningScene()
            scene:performWithDelay(MyPackage.callbackWrapper({scene},function()
                if not tolua.isnull(tips) then
                    tips:setVisible(false)
                end
            end),0)

            local eventdispatcher = display.getRunningScene():getEventdispatcher()
            eventdispatcher:removeEventListenersForTarget(targetNode)
        end
    end)
    ------------------------------------------------------------
    local function setTipsPosition()
        local leftBottomPos = MyPackage.getPositionOfNode(targetNode,display.LEFT_BottOM)
        local targetNodePos = display.getRunningScene():convertToNodeSpace(targetNode:getParent():convertToWorldspace(leftBottomPos))
        local targetNodeAnchorPoint = targetNode:getAnchorPoint()
        local tipsPos = targetNodePos
        local tipsAnchorPoint = cc.p(0,0)
        local director = cc.Director:getInstance()
        local glView = director:getopenGLView()
        local frameSize = glView:getFrameSize()
        local viewSize = director:getVisibleSize()

        if targetNodePos.x <= frameSize.width * 0.5 / glView:getScaleX() then
            -- show tips on the right of the targetNode if the targetNode is on the left screen
            tipsPos.x = tipsPos.x + targetNode:getContentSize().width + DEFAULT_TIPS_disT
        else
            -- show tips on the left of the targetNode otherwises
            tipsPos.x = tipsPos.x - DEFAULT_TIPS_disT
            tipsAnchorPoint.x = 1
        end

        if targetNodePos.y + tips:getContentSize().height > viewSize.height then
            tipsPos.y = viewSize.height
            tipsAnchorPoint.y = 1
        end
        if targetNodePos.y < 0 then
            targetNodePos.y = 0
        end

        tips:ignoreAnchorPointForPosition(false)
        tips:setAnchorPoint(tipsAnchorPoint)
        tips:setPosition(tipsPos)
    end
    ------------------------------------------------------------
    local function activeFunc()
        local scene = display.getRunningScene()
        -- NOTE: delay util the next frame in order to get the correct Worldspace position
        scene:performWithDelay(MyPackage.callbackWrapper({scene,tips},function()
            setTipsPosition()
            tips:setVisible(true)
        end),0)
    end

    local function inactiveFunc()
        if not tolua.isnull(tips) then
            tips:setVisible(false)
        end
    end

    local function isTouchInNode(touch,node)
        if tolua.isnull(node) or tolua.isnull(touch) then
            return false
        end

        local localLocation = node:convertToNodeSpace(touch:getLocation())
        local width = node:getContentSize().width
        local height = node:getContentSize().height
        local rect = cc.rect(0,width,height)
        return getCascadeVisibility(node) and node:isRunning() and cc.rectContainsPoint(rect,localLocation)
    end

    local function isActive(touch)
        local isExcluded = false
        for _,excludeNode in ipairs(excludeNodes) do
            isExcluded = isExcluded or isTouchInNode(touch,excludeNode)
        end
        return isTouchInNode(touch,targetNode) and not isExcluded
    end

    local function onTouchBegan(touch,event)
        if isActive(touch) then
            activeFunc()
            return true
        else
            return false
        end
    end

    local function onTouchMoved(touch,event)
        local scene = display.getRunningScene()
        scene:performWithDelay(MyPackage.callbackWrapper({scene},function()
            if isActive(touch) then
                activeFunc()
            else
                inactiveFunc()
            end
        end),0)
    end

    local function onTouchEnded(touch,function()
            inactiveFunc()
        end),0)
    end

    local listener = cc.EventListenerTouchOneByOne:create()
    listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN)
    listener:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCH_MOVED)
    listener:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED)
    listener:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_CANCELLED)
    local eventdispatcher = display.getRunningScene():getEventdispatcher()
    eventdispatcher:removeEventListenersForTarget(targetNode)
    eventdispatcher:addEventListenerWithSceneGraPHPriority(listener,targetNode)
end

关于MyPackage.getPositionOfNodeMyPackage.callbackWrapper等helper functions请参见之前某篇博文。

上面的代码基本是很简单的,除了有几点需要额外说明一下:

1.几处调用到performWithDelay的地方。这是因为我们用target_node的Worldspace坐标来确定tips的位置,当target_node位于某个可滚动的node(如ScrollView)中时,需要延迟到下一帧才能拿到它正确的Worldspace坐标,所以我们用了quickx定义的Node:performWithDelay来做延时。之所以用这个函数而不用scheduler,是因为它在Node的生命周期中,我们不需要担心如何去安全销毁scheduler所产生的handler。事实上我们只要看一下quickx定义在NodeEx.lua中的Node:performWithDelay就一目了然了:

function Node:performWithDelay(callback,delay)
    local action = transition.sequence({
        cc.DelayTime:create(delay),cc.CallFunc:create(callback),})
    self:runAction(action)
    return action
end

2.我们指定target_node在收到exit事件时隐藏tips,这是因为target_node可能在某些ClippingNode(如ScrollView)中,当它超出区域不再显示时,tips也不应该被显示。

3.当同一个位置有多个具有tips行为的target_node时,需要判断当前的target_node是否有显示,这需要回溯看父节点的visibilitygetCascadeVisibility定义如下:

function getCascadeVisibility(node)
    if tolua.isnull(node) then
        return true
    end
    local visibility = node:isVisible()
    if visibility then
        local parent = node:getParent()
        visibility = visibility and getCascadeVisibility(parent)
    end
    return visibility
end

在cocos2d-x游戏中实现tips功能的更多相关文章

  1. 利用Node实现HTML5离线存储的方法

    这篇文章主要介绍了利用Node实现HTML5离线存储的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  2. Html5 滚动穿透的方法

    这篇文章主要介绍了Html5 滚动穿透的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  3. HTML5 拖放(Drag 和 Drop)详解与实例代码

    本篇文章主要介绍了HTML5 拖放(Drag 和 Drop)详解与实例代码,具有一定的参考价值,有兴趣的可以了解一下

  4. 跨域修改iframe页面内容详解

    这篇文章主要介绍了跨域修改iframe页面内容详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  5. ios – Xcode找不到Alamofire,错误:没有这样的模块’Alamofire’

    我正在尝试按照github(https://github.com/Alamofire/Alamofire#cocoapods)指令将Alamofire包含在我的Swift项目中.我创建了一个新项目,导航到项目目录并运行此命令sudogeminstallcocoapods.然后我面临以下错误:搜索后我设法通过运行此命令安装cocoapodssudogeminstall-n/usr/local/bin

  6. ios – 使用带有NodeJs HTTPS的certificates.cer

    我为IOS推送通知生成了一个.cer文件,我希望将它与NodeJSHTTPS模块一起使用.我发现HTTPS模块的唯一例子是使用.pem和.sfx文件,而不是.cer:有解决方案吗解决方法.cer文件可以使用两种不同的格式进行编码:PEM和DER.如果您的文件使用PEM格式编码,您可以像使用任何其他.pem文件一样使用它(有关详细信息,请参见Node.jsdocumentation):如果您的文件使

  7. ios – 暂停调度队列是否会暂停其目标队列?

    我想创建两个串行队列A&B.队列B是队列A的目标.我想在B上排队一些块,并暂停它直到我准备执行它们,但是我想继续在队列A上执行块.如果我暂停B,这还会暂停它的目标队列(队列A)吗?我的想法是,我想安排这些特定的块在稍后日期执行但是我不希望它们同时运行而我不这样做想要处理信号量.但我希望队列A继续处理它的块,而B则被暂停如果不清楚这里是一些示例代码解决方法queueB被挂起,但queueA未被挂起.queueA和queueB被挂起.

  8. ios – 使用CocoaPods post install hook将自定义路径添加到HEADER_SEARCH_PATHS

    解决方法在Podfile中定义一个方法:然后在post_install中调用该方法:

  9. ios – 来自UIAlertController的self.navigationController?.popViewControllerAnimated

    我是新手,但我想我已经掌握了它.这让我的进步很难过.我想要做的是当我们无法找到他的查询的相关数据时向用户抛出错误消息,然后继续将他带回到之前的ViewController.但是,我在这方面遇到了麻烦.在我添加操作的行上,我收到以下错误:’UIViewController?’不是Void的子类型我该怎么做呢?

  10. ios – 在Swift中删除WKWebView Accesory栏

    我现在正试着将this转换成Swift而没有真正的背景.这是我到目前为止所得到的…而且我一直在寻找谷歌并不知道要搜索什么才能更具体.你能否详细说明我做错了什么?

随机推荐

  1. 【cocos2d-x 3.x 学习笔记】对象内存管理

    Cocos2d-x的内存管理cocos2d-x中使用的是上面的引用计数来管理内存,但是又增加了一些自己的特色。cocos2d-x中通过Ref类来实现引用计数,所有需要实现内存自动回收的类都应该继承自Ref类。下面是Ref类的定义:在cocos2d-x中创建对象通常有两种方式:这两中方式的差异可以参见我另一篇博文“对象创建方式讨论”。在cocos2d-x中提倡使用第二种方式,为了避免误用第一种方式,一般将构造函数设为protected或private。参考资料:[1]cocos2d-x高级开发教程2.3节[

  2. 利用cocos2dx 3.2开发消灭星星六如何在cocos2dx中显示中文

    由于编码的不同,在cocos2dx中的Label控件中如果放入中文字,往往会出现乱码。为了方便使用,我把这个从文档中获取中文字的方法放在一个头文件里面Chinese.h这里的tex_vec是cocos2dx提供的一个保存文档内容的一个容器。这里给出ChineseWords,xml的格式再看看ChineseWord的实现Chinese.cpp就这样,以后在需要用到中文字的地方,就先include这个头文件然后调用ChineseWord函数,获取一串中文字符串。

  3. 利用cocos2dx 3.2开发消灭星星七关于星星的算法

    在前面,我们已经在GameLayer中利用随机数初始化了一个StarMatrix,如果还不知道怎么创建星星矩阵请回去看看而且我们也讲了整个游戏的触摸事件的派发了。

  4. cocos2dx3.x 新手打包APK注意事项!

    这个在编译的时候就可以发现了比较好弄这只是我遇到的,其他的以后遇到再补充吧。。。以前被这两个问题坑了好久

  5. 利用cocos2dx 3.2开发消灭星星八游戏的结束判断与数据控制

    如果你看完之前的,那么你基本已经拥有一个消灭星星游戏的雏形。开始把剩下的两两互不相连的星星消去。那么如何判断是GameOver还是进入下一关呢。。其实游戏数据贯穿整个游戏,包括星星消除的时候要加到获得分数上,消去剩下两两不相连的星星的时候的加分政策等,因此如果前面没有做这一块的,最好回去搞一搞。

  6. 利用cocos2dx 3.2开发消灭星星九为游戏添加一些特效

    needClear是一个flag,当游戏判断不能再继续后,这个flag变为true,开始消除剩下的星星clearSumTime是一个累加器ONE_CLEAR_TIME就是每颗星星消除的时间2.连击加分信息一般消除一次星星都会有连击信息和加多少分的信息。其实这些combo标签就是一张图片,也是通过控制其属性或者runAction来实现。源码ComboEffect.hComboEffect.cpp4.消除星星粒子效果消除星星时,为了实现星星爆裂散落的效果,使用了cocos2d提供的粒子特效引擎对于粒子特效不了

  7. 02 Cocos2D-x引擎win7环境搭建及创建项目

    官网有搭建的文章,直接转载记录。环境搭建:本文介绍如何搭建Cocos2d-x3.2版本的开发环境。项目创建:一、通过命令创建项目前面搭建好环境后,怎样创建自己的Cocos2d-x项目呢?先来看看Cocos2d-x3.2的目录吧这就是Cocos2d-x3.2的目录。输入cocosnew项目名–p包名–lcpp–d路径回车就创建成功了例如:成功后,找到这个项目打开proj.win32目录下的Hello.slnF5成功了。

  8. 利用cocos2dx 3.2开发消灭星星十为游戏添加音效项目源码分享

    一个游戏,声音也是非常的重要,其实cocos2dx里面的简单音效引擎的使用是非常简单的。我这里只不过是用一个类对所有的音效进行管理罢了。Audio.hAudio.cpp好了,本系列教程到此结束,第一次写教程如有不对请见谅或指教,谢谢大家。最后附上整个项目的源代码点击打开链接

  9. 03 Helloworld

    程序都有一个入口点,在C++就是main函数了,打开main.cpp,代码如下:123456789101112131415161718#include"main.h"#include"AppDelegate.h"#include"cocos2d.h"USING_NS_CC;intAPIENTRY_tWinMain{UNREFERENCED_ParaMETER;UNREFERENCED_ParaMETER;//createtheapplicationinstanceAppDelegateapp;return

  10. MenuItemImage*图标菜单创建注意事项

    学习cocos2dx,看的是cocos2d-x3.x手游开发实例详解,这本书错误一大把,本着探索求知勇于发现错误改正错误的精神,我跟着书上的例子一起调试,当学习到场景切换这个小节的时候,出了个错误,卡了我好几个小时。

返回
顶部