Cocos2dx 3.3 tilemap scales and slides and accurately clicks an object. cocos2dxtilemap

Source: Internet
Author: User

Cocos2dx 3.3 tilemap scales and slides and accurately clicks an object. cocos2dxtilemap

There was already a more basic tilemap note. In the past two days, I used tilemap of 3.3 to find that some things were useless. So I wrote another note, and I suddenly felt cute.

For more information, see the basics.


Main objectives:

1. tiledMap can be scaled by three times.

2. Sliding tiledMap with the mouse

3. When zooming and sliding, click a tile to determine the actual grid coordinates.


Here we will not go into detail about scaling and sliding. There are many examples, with the complete code at the end. This section describes the implementation of article 3.

As you can see, I created a points object group and created two objects: startPos and endPos.

StartPos covers about four tiled [] [] [] [] []

In addition, a custom attribute id is set for startPos. All I need is to get the id value of this object when I click the above four tileds.






First, I wrote a function to read the map object.

void HelloWorld::parseTileMap(){    CCLOG("parseTileMap");    if(_tiledMap == NULL)        return;        _objectsGroup = _tiledMap->getObjectGroup("points");    //tileX 0  tileY 24    ValueMap startPos = _objectsGroup->getObject("startPos");    std::string name = startPos["name"].asString();    float pointX = startPos["x"].asFloat();    float pointY = startPos["y"].asFloat();;    float PointWidth = startPos["width"].asFloat();    float PointHeight = startPos["height"].asFloat();    Size winSize = Director::getInstance()->getWinSize();    Point mapPoint = _tiledMap->getPosition();    Point centerPos = covertTiledPointToCenterPoint(Point(0,24));    Point tilePos = covertPointToTiledPoint(Point(pointX,pointY));    Point tilePos2 = covertPointToTiledPoint(centerPos);}

The pointX and pointY of the startPos object are obtained smoothly, but the value is (0,296). It is not expected (1,768) to be suddenly messy -_-!! .

It wasn't until you looked at the getPositionAt of the source code TMXLayer that this (0,296) had already undergone "Resolution conversion.

Vec2 TMXLayer::getPositionAt(const Vec2& pos){    Vec2 ret = Vec2::ZERO;    switch (_layerOrientation)    {    case TMXOrientationOrtho:        ret = getPositionForOrthoAt(pos);        break;    case TMXOrientationIso:        ret = getPositionForIsoAt(pos);        break;    case TMXOrientationHex:        ret = getPositionForHexAt(pos);        break;    case TMXOrientationStaggered:        ret = getPositionForStaggeredAt(pos);        break;    }    CCLOG("%f,%f,%f",ret.x,ret.y,CC_CONTENT_SCALE_FACTOR());        ret = <span style="color:#ff0000;">CC_POINT_PIXELS_TO_POINTS</span>( ret );    return ret;}


Let's take a look at the macro definition:

/** @def CC_POINT_PIXELS_TO_POINTS Converts a rect in pixels to points */#define CC_POINT_PIXELS_TO_POINTS(__pixels__)                                    \Vec2( (__pixels__).x / CC_CONTENT_SCALE_FACTOR(), (__pixels__).y / CC_CONTENT_SCALE_FACTOR())/** @def CC_CONTENT_SCALE_FACTOROn Mac it returns 1;On iPhone it returns 2 if RetinaDisplay is On. Otherwise it returns 1*/#define CC_CONTENT_SCALE_FACTOR() Director::getInstance()->getContentScaleFactor()


We can see from the source code:

1. We can determine that the ratio of pixel: point on tilemap is 1: 1, but not necessarily on the device.

On a mac device, pixel: point = 1: 1 and the iphone Retina is 2: 1. The low resolution is larger. Let's take this ratio to pixel size factor.

2. CC_POINT_PIXELS_TO_POINTS can be used to convert the coordinate value above tilemap to the coordinate value above the device.

3. This setScale getScale is similar, but must be separated for computing.


In addition, because our tilemap can slide and click, two additional points are required when converting the absolute tilemap coordinate from the touch point:

1. Use the coordinates of tilemapLayer as the offset.

bool HelloWorld::onTouchBegan(Touch *touch, Event  *event){    CCLOG("HelloWorld::onTouchBegan");    Point touchPoint = touch->getLocation();    Point mapPoint = _tiledMap->getPosition();  <span style="color:#ff0000;">  Point realPoint = touchPoint - mapPoint;</span>    Point tilePoint = covertPointToTiledPoint(realPoint);    CCLOG("tilePoint x:%f y:%f",tilePoint.x,tilePoint.y);        tryGetObjectPropertyByPosition(realPoint);    return true;}


2. Multiply by the scaling factor
// Parameter: Touch coordinate string HelloWorld: tryGetObjectPropertyByPosition (Point position) {float scale = _ tiledMap-> getScale (); float factor = CC_CONTENT_SCALE_FACTOR (); <span style = "color: # ff0000;"> float realPointX = position. x/scale; float realPointY = position. y/scale; </span> for (auto item: _ objectsGroup-> getObjects () {ValueMap curObject = item. asValueMap (); float pointX = curObject ["x"]. asFloat (); float pointY = curObject ["y"]. asFloat (); float PointWidth = curObject ["width"]. asFloat (); float PointHeight = curObject ["height"]. asFloat (); if (realPointX> = pointX and realPointX <= pointX + PointWidth and realPointY> = pointY and realPointY <= pointY + PointHeight) {string objectId = curObject ["id"]. asString (); CCLOG ("HelloWorld: tryGetObjectPropertyByPosition: % s", objectId. c_str (); return objectId;} return "";}


Next, it's very easy to reverse push from the touch point to the tilemapPoint method.

Point HelloWorld::covertTiledPointToCenterPoint(Point p){    float scale = _tiledMap->getScale();    float factor = CC_CONTENT_SCALE_FACTOR();        CCLOG("HelloWorld::covertTiledPointToCenterPoint scale:%f factor:%f",scale,factor);        int offsetX = _tiledMap->getTileSize().width / (2 * factor);    int offsetY = _tiledMap->getTileSize().height / (2 * factor);    TMXLayer* layer = _tiledMap->layerNamed("background");    Point point = layer->getPositionAt(p);        point = Point(point.x  + offsetX,point.y - offsetY);    point = Point(point.x * scale, point.y * scale);    return point;}

Source code







Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.