`
amuropikin
  • 浏览: 41639 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Cocos2d实现类似Clash of clans的缩放拖拽效果

阅读更多
最近开始跳入做游戏的坑了,而且想做一款独立游戏,虽然随时有烂尾的危险,但无妨一试~敬请期待~

目前正在准备游戏的原型,由于需要设计像COC的缩放场景,作为cocos2d的菜鸟兼ios开发新手,实在search遍了也没有像样的cocos2d代码,即使有效果也未如人意。stackoverflow上有老外关于pinch缩放手势的例子,但放到cocos2d环境,需要控制一个sprite或者tilemap的边界,就变得有点复杂了。这个问题实在卡了我好久好久,但通过参考了一些pinch示例以及不断调试anchor point和map position等值,最终解决,实在泪牛满面!

这个例子我使用了tilemap作为缩放的对象,当然需要的话也可以用sprite或其他代替。在使用了cocos2d的模版生成文件后,可以在hellolayer中的构造器里先添加本次需要的变量

@implementation HelloWorldLayer{
    CCTMXTiledMap *map;
    CGSize winSize;
    CGFloat mapWidth;
    CGFloat mapHeight;
}


map是我们的tilemap对象,我们用它来初始化tile map;winSize包含了屏幕的大小参数;mapWidth和mapHeight是实际制作的tilemap的高宽值。同时在init方法中添加代码:

-(id) init
{
    if( (self=[super init]) ) {
        winSize=[CCDirector sharedDirector].winSize;

        //加载地图
        map=[[CCTMXTiledMap alloc] initWithTMXFile:@"square_tile.tmx"];
        map.anchorPoint=CGPointZero;
        map.position=CGPointZero;
        map.scale=2;
        [self addChild:map];
         
        //除以2是考虑retina,实际中应该对此判断
        mapWidth= map.tileSize.width*map.mapSize.width/2.0f;
        mapHeight= map.tileSize.height*map.mapSize.height/2.0f;
         
        //缩放处理
        UIPinchGestureRecognizer *pinchRecognizer = [[[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchFrom:)] autorelease];
        [[[CCDirector sharedDirector] view] addGestureRecognizer:pinchRecognizer];
  
        //滑动
        [[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
    }
    return self;
}


这段代码分三步来分解:

1.加载tilemap地图文件,anchor point和position属性值均为CGPointZero,这里为了方便retina显示,初始化scale是2,retina的解决方案暂时不在这里考虑,为了方便,相关的参数是用实际数字代替,实际开发可以对各种参数重构。地图的资源文件在本文最后的demo里找到~

2.pinch手势的缩放,交由本类的handlePinchFrom方法处理

3.最后是滑动处理,由多触点的方法接口实现,下面将引入ccTouchBegan和ccTouchMoved来控制视图的滑动和边界限制等

NOW LET'S KICK OFF!

我们来编写核心功能缩放zoom的处理代码,需要实现的基本需求有:pinch手势(两指滑动)能对当前视图进行相应的放大缩小;缩放的焦点须要为两指初始位置的中点上;同时视图必须以该焦点作为中心

添加handlePinchFrom方法的具体代码:

-(void) handlePinchFrom:(UIPinchGestureRecognizer *)gestureRecognizer
{
    if ([gestureRecognizer state] == UIGestureRecognizerStateBegan){
        
        UIView *piece = gestureRecognizer.view;
        
        CGPoint location = [gestureRecognizer locationInView:piece];
        
        location=[[CCDirector sharedDirector] convertToGL:location];
        
        CGPoint locationInView=[map convertToNodeSpace:location];
        
        //ax-新的anchor point中x的值,ay同理
        CGFloat ax=locationInView.x / mapWidth;
        CGFloat ay=locationInView.y / mapHeight;
        
        CGPoint prevAnchor=map.anchorPoint;
        
        map.anchorPoint = ccp(ax,ay);
        
        //调整后的地图位置
        map.position=ccp(mapWidth*ax*map.scale+map.position.x-map.boundingBox.size.width*prevAnchor.x,mapHeight*ay*map.scale+map.position.y -map.boundingBox.size.height*prevAnchor.y);
        
        
        gestureRecognizer.scale=map.scale;
    }
    
    map.scale=gestureRecognizer.scale;
    
    [self adjustViewBoundingPosition:self.position];
}



实际中调试还必须加入以下方法:

-(void)adjustViewBoundingPosition:(CGPoint)newPos{
}

-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
	return YES;
}

-(void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
}


现在可以build后看看效果了!能够看到地图已经能根据两点焦点进行缩放,基本上这就是本例的核心功能!但还不能移动,我们后面再解决,先看下handlePinchFrom的方法:)

CGPoint location = [gestureRecognizer locationInView:piece];


这句是根据获取当前pinch手势的焦点,获取该点后,通过[map convertToNodespace:location]将它转换成地图上相对的坐标位置,然后计算出焦点相对地图x轴和y轴的比例,从而获得了地图新的anchor point,我们的地图将以此新的焦点进行缩放。但设置了anchor point,必然需要对position位置值进行相应移动才能保证地图是平滑放大!所以position的计算值才是最难的一点,为此需要记录缩放前的anchor point(prevAnchor)作为参考值计算

map.position=ccp(mapWidth*ax*map.scale+map.position.x-map.boundingBox.size.width*prevAnchor.x,mapHeight*ay*map.scale+map.position.y -map.boundingBox.size.height*prevAnchor.y);


以上就是地图位置的调整公式,通过反复调试得出,数学好的可以想一下哈哈 
map.scale=gestureRecognizer.scale;

按当前手势的比例设置地图比例,非常简单,就不用多解释了。如果需要优化的话,可以加入最大比例和最小比例的参数来限制缩放的比例。

最后的adjustViewBoundingPosition方法是为了让地图的上下左右边界不超出界限,即不会划出屏幕以外,下面我们来填充剩下的adjustViewBoundingPosition和CCTouchMoved方法来实现移动!

-(void)adjustViewBoundingPosition:(CGPoint)newPos
{
    CGFloat adjustWidth=map.boundingBox.size.width*map.anchorPoint.x-map.position.x;
    CGFloat adjustHeight=map.boundingBox.size.height*map.anchorPoint.y-map.position.y;
    
    newPos.x=  MIN(newPos.x, adjustWidth);
    newPos.x = MAX(newPos.x, winSize.width-[map boundingBox].size.width+adjustWidth);
    newPos.y = MIN(newPos.y,adjustHeight);
    newPos.y = MAX(newPos.y, winSize.height-[map boundingBox].size.height+adjustHeight);
    self.position=newPos;
}

-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
	return YES;
}

-(void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
    CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
    
    CGPoint oldTouchLocation = [touch previousLocationInView:touch.view];
    oldTouchLocation = [[CCDirector sharedDirector] convertToGL:oldTouchLocation];
    oldTouchLocation = [self convertToNodeSpace:oldTouchLocation];
    
    CGPoint translation = ccpSub(touchLocation, oldTouchLocation);
    CGPoint newPos= ccpAdd(self.position, translation);
    
    [self adjustViewBoundingPosition:newPos];
}


CCTouchMoved的方法通过获得手势滑动前后的位置差来设置新视图的位置,并使用了adjustViewBoundingPosition来限制移动边界。如果需要做到COC效果滑动时带有惯性,则又必须添加几项控制参数(如是否为拖动状态)同时设置一个schedule来添加惯性的动画,本例没有做这个效果,可以另行添加

adjustViewBoundingPosition和常规的控制边界代码没有什么不同,主要是多了adjustHeight和adjustWidth的值,这两个值是根据当前map的anchor point和position决定的。另外MIN和MAX的相关值与缩放的实际需求相关,譬如本人不需要考虑scale<2即地图小于屏幕的情况,所以MIN和MAX是定死了,可根据是否小于屏幕来对调MIN和MAX的值

以上就是基本的代码,由于只考虑实现,所以实际项目中还是需要按自己需求去调整,譬如添加惯性,控制缩放比例,缩放达到界限后用动画过渡等效果,在本demo中都没有提供,但这些处理并不复杂~so~

本例的代码已经放到github上,需要的时候可以下来看看 :)

Check this out: https://github.com/yijiancen/pinch-and-scroll-like-clash-of-clans
分享到:
评论

相关推荐

    cocos2d-x 双指缩放,单指拖动,双击自动放大地图

    在Cocos2d-x游戏开发中,实现"双指缩放,单指拖动,双击自动放大地图"的功能是一项常见的交互设计,它为玩家提供了更直观、更友好的操作体验。下面将详细讲解如何利用Cocos2d-x库来实现这些功能。 一、双指缩放 ...

    cocos2d制作类似雷电游戏中飞机的激光子弹效果源码

    本篇将详细讲解如何利用cocos2d来制作类似雷电游戏中飞机的激光子弹效果,并且这种效果能够呈现出动态的弯曲轨迹。 首先,我们要理解cocos2d的核心概念。cocos2d基于场景(Scene)、节点(Node)和动作(Action)的...

    cocos2d-x 地图的缩放和拖动

    cocos2d-x提供了丰富的API和工具来实现这些动态效果,使得玩家可以自由地查看游戏场景的各个角落。下面将详细介绍如何在cocos2d-x中实现地图的缩放和拖动功能。 首先,我们来讨论地图的缩放。在cocos2d-x中,缩放...

    cocos2d实现button(按钮)效果

    感觉4个人开发游戏真的很累,游戏为了脱颖出更加真实的效果还使用了物理引擎,在老大的同意的情况下,我共享cocos2d自己写的一些大家比较常用的,因为cocos2d有些控件不怎么好用或者没有,反正我觉得是这样的。...

    cocos2d-x3.10 翻页、翻牌效果的实现

    在Cocos2d-x 3.10这个流行的2D游戏开发框架中,实现翻页和翻牌效果是一项常见的需求,特别是在制作卡片游戏或者互动UI时。这些效果为游戏增添了生动性和趣味性,使得用户体验更加丰富。下面我们将深入探讨如何在...

    cocos2d实现progress(进度条效果)

    感觉4个人开发游戏真的很累,游戏为了脱颖出更加真实的效果还使用了物理引擎,在老大的同意的情况下,我共享cocos2d自己写的一些大家比较常用的,因为cocos2d有些控件不怎么好用或者没有,反正我觉得是这样的。...

    Cocos2d-x实现战争迷雾效果 项目源码下载

    Cocos2d-x实现战争迷雾效果 项目源码下载

    cocos2d3D扑克翻牌特效

    《cocos2d 3D扑克翻牌特效详解——基于OpenGL的实现》 在游戏开发领域,视觉效果的呈现往往能极大地提升玩家的沉浸感。其中,扑克翻牌特效就是一个常见的交互元素,它能为游戏增添趣味性和神秘感。本文将深入探讨...

    cocos2d实现RollNunber(数字滚动效果)

    感觉4个人开发游戏真的很累,游戏为了脱颖出更加真实的效果还使用了物理引擎,在老大的同意的情况下,我共享cocos2d自己写的一些大家比较常用的,因为cocos2d有些控件不怎么好用或者没有,反正我觉得是这样的。...

    cocos2d实现液体流动效果

    本篇我们将深入探讨如何利用cocos2d来实现液体流动效果,这是一个既有趣又挑战性的任务。 首先,液体流动效果的核心在于模拟物理现象,尤其是流体动力学。在cocos2d中,这通常通过编程算法来实现,而不是依赖于预...

    cocos2d_lua 3D搓牌效果

    本文将深入探讨如何利用cocos2d_lua实现3D搓牌效果,以及如何将其流畅地整合到项目中。 首先,搓牌效果是许多扑克类游戏中的关键元素,它不仅要求视觉效果逼真,还需要运行流畅,以提供优秀的用户体验。在cocos2d_...

    Cocos2d-x实战:JS卷——Cocos2d-JS开发

    资源名称:Cocos2d-x实战:JS卷——Cocos2d-JS开发内容简介:本书是介绍Cocos2d-x游戏编程和开发技术书籍,介绍了使用Cocos2d-JS中核心类、瓦片地图、物理引擎、音乐音效、数据持久化、网络通信、性能优化、多平台...

    cocos2d-x-cocos2d-x-2.2.2.zip

    这个压缩包“cocos2d-x-cocos2d-x-2.2.2.zip”包含了cocos2d-x 的2.2.2版本,该版本是cocos2d-x发展中的一个重要里程碑,它提供了许多改进和优化,使得开发者能够更加高效地创建2D游戏和应用。 在cocos2d-x 2.2.2中...

    Cocos2d-x 闪电特效

    总的来说,"Cocos2d-x 闪电特效"涵盖了游戏开发中的图形编程、OpenGL图形渲染、着色器编程以及动态效果的实现等多个知识点。对于想要提升游戏视觉效果的开发者来说,深入理解和掌握这些技术是非常有价值的。通过实践...

    COCOS2D 弹球效果

    《COCOS2D 弹球效果实现详解》 Cocos2D是一个广泛使用的开源2D游戏开发框架,尤其在iOS和Android平台上受到开发者们的喜爱。它的强大功能和易用性使得开发各种类型的游戏变得简单,包括我们今天要讨论的主题——...

    Cocos2d-x 地图行走的实现2

    在这个主题“Cocos2d-x 地图行走的实现2”中,我们将深入探讨如何在Cocos2d-x环境中创建动态的游戏地图并让角色在地图上自由行走。首先,我们需要了解Cocos2d-x的基本概念和组件。 Cocos2d-x 是基于C++的,它提供了...

    cocos2d-x 初级粒子爆炸特效

    在本文中,我们将深入探讨如何使用Cocos2d-x框架创建初级粒子爆炸特效。Cocos2d-x是一款广泛应用于移动游戏开发的开源2D游戏引擎,支持多种平台,包括iOS、Android、Windows等。粒子系统是游戏开发中常用的一种技术...

    经典版本 方便下载 源码 旧版本 3.8 官网找不到了 cocos2d-x-3.8.zip

    4. **Action系统**:cocos2d-x的动作系统允许开发者轻松实现物体的移动、旋转、缩放等效果,极大地简化了动画制作。 5. **Scene和Layer**:通过Scene和Layer的概念,可以组织游戏的场景和层次结构,方便管理游戏...

    cocos2d-x 3.0

    《cocos2d-x 3.0:游戏开发中的角色移动技术详解》 ...总之,cocos2d-x 3.0提供了强大的工具和框架,帮助开发者实现生动有趣的游戏角色行走效果。通过深入理解和实践,你可以创建出具有高度交互性和沉浸感的2D游戏。

    cocos2d-X水果忍者效果demo

    本篇将深入探讨如何利用cocos2d-X来实现一款类似《水果忍者》的游戏效果,旨在为游戏开发爱好者提供宝贵的实践经验和理论指导。 首先,我们要理解《水果忍者》的核心玩法:玩家通过滑动屏幕切割飞行中的水果,同时...

Global site tag (gtag.js) - Google Analytics