存档

‘cocos2d’ 分类的存档

What is the meaning of std::function<void(Ref*)> in C++

2015年3月5日 没有评论

I got into trouble of this function, and I don’t know what is the meaning of that:

menuItem1->setCallback([&](cocos2d::Ref *sender)

Enter the function, the param is ccMenuCallback&:

    /** set the callback to the menu item
    * @code
    * In js,can contain two params,the second param is jsptr
    * @endcode
    * @lua NA
    */
    void setCallback(const ccMenuCallback& callback);

And

typedef std::function<void(Ref*)> ccMenuCallback;

That’s a C++11 lambda.

Basically setCallback accepts as an argument a std::function that takes a cocos2d::Ref* and returns void. That’s a type which is able to hold a callable function.

A lambda is an anonymous function which in that situation is stored inside a std::function<void(cocos2d::Ref*)> variable and passed to the function.

Indeed it’s something like:

auto lambda = [&](cocos2d::Ref* sender) {
  /* implementation */
};
// ^ store the anonymous function in a variable

menuItem1->setCallBack(lambda);

std::function can hold function pointer, method binding, lambda expression and any object with overloaded operator()

void someFunc(cocos2d::Ref *sender)
{
    //some code
}

std::function<void(Ref*)> f1 = someFunc;
std::function<void(Ref*)> f2 = [&](cocos2d::Ref *sender) {
    //some code
}

Probably void setCallback(const ccMenuCallback& callback); takes a callback which is called when a menu item is clicked or something like this.

This expression is a lambda:

[&](cocos2d::Ref *sender)
分类: cocos2d, stackoverflow精选 标签:

Cocos2d-x Version 2.2 CCRenderTexture not rendering image properly on Samsung Tab 4 (model no. SMT231)

2015年1月7日 没有评论

I have been trying to draw on touches moved using Render Texture. This is my code:

void GameplayLayer::visitSpriteContinuously()
{
   CCRenderTexture*    canvas = CCRenderTexture::create(screenSize.width,screenSize.height,kCCTexture2DPixelFormat_RGBA4444);

   canvas->setPosition(ccp(screenSize.width/2,screenSize.height/2));
   this->addChild(canvas);

   GameSprite* drawSprite=GameSprite::gameSpriteWithFile(“circle.png");
   this->addChild(drawSprite);

   CCPoint start = starttouchPosition->getLocationInView();
   start = CCDirector::sharedDirector()->convertToGL(start);

CCPoint end = starttouchPosition -> getPreviousLocationInView();
end = CCDirector::sharedDirector()->convertToGL(end);

float distance = ccpDistance(start, end);
canvas->begin();
for (int i = distance; i > 0; i--)
{
    float difx = end.x - start.x;
    float dify = end.y - start.y;
    float delta = (float)i / distance;
    drawSprite->setPosition(ccp(start.x + (difx * delta), start.y + (dify * delta)));
    drawSprite->visit();
}
canvas->end();

}

I am getting the desired result in almost all the android devices that I have tested except Samsung Tab 4. On Tab 4 the sprite drawn is having a dotted sort of pattern even if the base png image used is single solid colour. I have searched a lot, but I didn’t find anything useful. If anyone has seen similar issues and has a solution please let me know. Following are the screenshots:

‘A’ rendered on Other Devices:
Cocos2d-x Version 2.2 CCRenderTexture not rendering image properly on Samsung Tab 4 (model no. SMT231)

‘A’ rendered on Samsung Tab 4:
Cocos2d-x Version 2.2 CCRenderTexture not rendering image properly on Samsung Tab 4 (model no. SMT231)

In some device,RGBA4444 format not supported correctly, so in that case , you have to use RGBA8888 format.
So, Just change this line in your code

CCRenderTexture*    canvas = CCRenderTexture::create(screenSize.width,screenSize.height,kCCTexture2DPixelFormat_RGBA4444);

with

CCRenderTexture*    canvas = CCRenderTexture::create(screenSize.width,screenSize.height,kCCTexture2DPixelFormat_RGBA8888);
分类: cocos2d, stackoverflow精选 标签:

How to property hold a reference to the children nodes with ARC in Cocos2d

2014年10月30日 没有评论

I have a custom CCNode class that has a bunch of children nodes, and I want to keep references to the children in order to make some custom transitions.

For instance for the child background the custom class would look like this:

@interface MyNode : CCNode
@property (nonatomic, strong) CCNode *background;
@end

@implementation
- (void)setBackground:(CCNode *)background {
    if (_background) {
        [self removeChild:_background];
    }
    if (background) {
        [self addChild:background];
    }
    _background = background;
}
- (void)runTransition {
    if (_background)
        [_background runAction:[…]];
}
@end

The problem is that this causes a retain cycle on ARC with the node background never being freed from memory.

There are no hard rules for memory management. You need to look at your code and decide the best method to use.

In your case though as you only ever have one background you could just make that property weak. Cocos2d holds a strong reference to all nodes that are in the scene graph so it will hold onto it for you.

This doesn’t mean that every node should be stored as weak, sometimes you want the node to hang around if its not in the scene graph.

Change your interface to use a zeroing weak reference:

@interface MyNode : CCNode
@property (nonatomic, weak) CCNode *background;
@end

If the background node deallocates, the _background ivar will become nil automatically. That way you won’t have a retain cycle anymore. This is generally good practice if you store a node reference in a node that is a child or grandchild of the node because those situations will always cause a retain cycle.

Your code as is should work fine with a weak reference.

Note however that you need to be careful when creating and assigning to a weak reference, for instance this will fail with a nil node being added as child:

_background = [CCNode node];
[self addChild:_background];

The problem here is that after the assignment, there is nothing strongly holding on to the background node, so it deallocates and is set to nil before the addChild: line.

There’s a simple workaround:

CCNode* bg = [CCNode node];
[self addChild:bg];
_background = bg;

After the node has been added as child, the children array will hold a strong reference to the node. So after the addChild: line you can assign the temporary bg node to the _background ivar.

分类: cocos2d, stackoverflow精选 标签:

Problems limiting object rotation with Mathf.Clamp()

2014年9月13日 没有评论

I am working on a game that rotates an object on the z axis. I need to limit the total rotation to 80 degrees. I tried the following code, but it doesn’t work. minAngle = -40.0f and maxAngle = 40.0f

Vector3 pos = transform.position;
pos.z = Mathf.Clamp(pos.z, minAngle, maxAngle);
transform.position = pos;

The code you posted clamps the z position. What you want is to use transform.rotation

void ClampRotation(float minAngle, float maxAngle, float clampAroundAngle = 0)
{
    //clampAroundAngle is the angle you want the clamp to originate from
    //For example a value of 90, with a min=-45 and max=45, will let the angle go 45 degrees away from 90

    //Adjust to make 0 be right side up
    clampAroundAngle += 180;

    //Get the angle of the z axis and rotate it up side down
    float z = transform.rotation.eulerAngles.z - clampAroundAngle;

    z = WrapAngle(z);

    //Move range to [-180, 180]
    z -= 180;

    //Clamp to desired range
    z = Mathf.Clamp(z, minAngle, maxAngle);

    //Move range back to [0, 360]
    z += 180;

    //Set the angle back to the transform and rotate it back to right side up
    transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y, z + clampAroundAngle);
}

//Make sure angle is within 0,360 range
float WrapAngle(float angle)
{
    //If its negative rotate until its positive
    while (angle < 0)
        angle += 360;

    //If its to positive rotate until within range
    return Mathf.Repeat(angle, 360);
}

Here’s a static version of the nice solution by Imapler that, instead of changing the angle itself, it returns the campled angle, so it can be used with any axis.

public static float ClampAngle(
    float currentValue,
    float minAngle,
    float maxAngle,
    float clampAroundAngle = 0
) {
    return Mathf.Clamp(
        WrapAngle(currentValue - (clampAroundAngle + 180)) - 180,
        minAngle,
        maxAngle
    ) + 360 + clampAroundAngle;
}

public static float WrapAngle(float angle)
{
    while (angle < 0) {
        angle += 360;
    }
    return Mathf.Repeat(angle, 360);
}

Or if you don’t expect to use the WrapAngle method, here’s an all-in-one version:

public static float ClampAngle(
    float currentValue,
    float minAngle,
    float maxAngle,
    float clampAroundAngle = 0
) {
    float angle = currentValue - (clampAroundAngle + 180);

    while (angle < 0) {
        angle += 360;
    }

    angle = Mathf.Repeat(angle, 360);

    return Mathf.Clamp(
        angle - 180,
        minAngle,
        maxAngle
    ) + 360 + clampAroundAngle;
}

So now you can do:

transform.localEulerAngles.x = YourMathf.ClampAngle(
    transform.localEulerAngles.x,
    minX,
    maxX
);
分类: cocos2d, stackoverflow精选 标签:

Unable to parse plist in Cocos2dx 3.0

2014年8月22日 没有评论

Unable to parse plist in Cocos2dx 3.0

I want to parse this plist structure…Please help

What I am using right now is

mainDictionary = __Dictionary::createWithContentsOfFile(plistPath.c_str());
__Dictionary *exit = (__Dictionary*)__Dictionary::createWithDictionary(
            (__Dictionary*)mainDictionary->objectForKey(std::string("otherButton")));

But there are keys missing exit dictioanry…

In 3.0+ version the data structure like CCDictionary CCArray are deprecated. You have to use ValueMap or ValueVector etc
You can find the data structure under the folder ValueVector > CCValue.h

Here’s the code for reading this plist:

cocos2d::ValueMap gameData;
gameData = FileUtils::getInstance()->getValueMapFromFile("data.plist");

In case you want to read the values:

//1
std::string backgroundValue = gameData.at("background");

//2
ValueMap otherButtonsMap = gameData.at("otherButton").asValueMap();
std::string tagValue = otherButtonsMap.at("Tag");

//3
ValueVector buttonsVector = gameData.at("Buttons").asValueVector();
ValueMap item0 = buttonsVector.at(0).asValueMap();

Where the gameData is ValueMap (or in other words Dictionary or Map or HashMap)

Edit:

The answer by “Wez Sie Tato” is correct but in your case you should read the plist in ValueMap instead of ValueVector, because your plist is actually the Dictionary(ValueMap) and not the Array(ValueVector).

There is simply no key named “ExitButton” in the root of the plist (and thus in mainDictionary).

The mainDictionary keys will be “background”, “otherButton” and “Buttons”, each returning another Dictionary or Array instance.

If the “ExitButton” key is somewhere in the Buttons array, you have to enumerate the Buttons array and find the “ExitButton” key in one of the array items.

Try use ValueMap and FileUtils to load PList file. The way you try to load dictionary is from cocos2d-x v2.x. In cocos2d-x you should do something like this:

ValueMap mainDictionary = FileUtils::getInstance()->getValueMapFromFile(plistPath.c_str());

ValueMap exit = mainDictionary["otherButton"].asValueMap();
分类: cocos2d, stackoverflow精选 标签:

How to include Cocos2dx UI library in Android project

2014年6月8日 没有评论

I’m trying to include one of the UI classes in my cocos2dx project.

In my scene class I have:

 #include "CocosGUI.h"

It compiles fine for iOS, but when I try to use the command line to compile for Android I get the following error:

fatal error: CocosGUI.h: No such file or directory

I understand it’s because it can’t find the library. I’ve been trying to find the right one to add but haven’t had any luck.

I’ve added:

LOCAL_WHOLE_STATIC_LIBRARIES += cocos_extension_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_ui_static

and

$(call import-module,extensions)
$(call import-module,ui)

But that doesn’t seem to help.

I’m using cocos2dx v3.0

I solved the problem by getting the right libraries to compile in the make file.

Here is what I added:

LOCAL_C_INCLUDES := ... /
$(LOCAL_PATH)/../../cocos2d/cocos/ui /

AND ADDING THESE LINES IN THE RIGHT SECTIONS

LOCAL_WHOLE_STATIC_LIBRARIES += cocostudio_static
$(call import-module,editor-support/cocostudio)

Change your import to “ui/CocosGUI.h”. I am using 3.3.

You don’t need to edit your Android.mk’s import-module or import-add-path lines, or your build-cfg.json, all you need to do is change the specific headers to this generic one.

分类: cocos2d, stackoverflow精选 标签:

What is Mono Behaviour?

2014年6月6日 没有评论

I’m getting this message multiple times when I try to run my game:

The referenced script on this Behaviour is missing

For some reason, all my prefabs are missing a script that dictates something called their ‘Mono Behaviour':

What is Mono Behaviour?

What is the Mono Behaviour component, and what does it do?

How can I fix this error? I can click the little target circle to bring up all my scripts, but that just gives me all of the scripts that I’ve written:

What is Mono Behaviour?

So I don’t really know how to replace my missing Mono Behaviour script… Maybe if I knew what it was I could have a clue how to fix it.

I probably moved something. But how can I select the Mono Behaviour script (whatever it is) if the target just shows me my scripts?

Update

I’ve moved some assets in the project window, but not via the OS (Finder/Explorer) so why is this happening?

Also I am told that Mono Behaviour is a script I’ve applied…

Don’t really get this…isn’t the script component a reference to a script?

What is Mono Behaviour?

This happens when you have a script attached to a component, but then the script has been deleted (or its reference has lost in another way, such as the meta file being modified).

If you don’t know which script used to be there, just delete those Mono Behaviour components.

MonoBehaviour is the Base Class of all scripts that you want to attach to a GameObject. I am not sure how you managed to create a MonoBehaviour Component with a script missing. What you normally do is write your script and then just drag it from the project view onto the GameObject you want it attached to.

分类: cocos2d, stackoverflow精选 标签:

Can Android Studio be used to create Unity-plugin compatible JARs out of Library projects?

2014年5月5日 没有评论

Context: I am an experienced programmer, but not with Java nor associated tools like Ant or Gradle. It’s possible I’m missing something that should be obvious.

When using Unity3d, “native” (pure-java) Android functionality can be accessed via Plugin. As described in the documentation,

There are several ways to create a Java plugin but the result in each case is that you end up with a .jar file containing the .class files for your plugin

When I create an Android Application Project in eclipse, and set it is a library, it automatically generates a .jar file in the bin folder. I understand that this is a temporary file in the context of the Android toolchain, but this is the file that Unity needs in order to see the classes and build up it’s own internal JNI magic. (The entire process is outlined very well here in case more clarity is needed on that process.)

Unfortunately, as near as I can tell, Android Studio does not generate this file. Is there a way I can tell it to give me this file, or perhaps some other way to generate code that Unity will be able to use?

You can create a jar file using Android Studio.
Just add these tasks in your app’s build.gradle file.

//task to delete the old jar
task deleteOldJar(type: Delete) {
    delete 'build/libs/AndroidPlugin.jar'
}

//task to export contents as jar
task exportJar(type: Copy) {
    from('build/intermediates/bundles/release/')
    into('release/')
    include('classes.jar')
    ///Give whatever name you want to give
    rename('classes.jar', 'AndroidPlugin.jar')
}

exportJar.dependsOn(deleteOldJar, build)

Once you add the above lines you can export the jar using the task of the same name.
You can go through this post on TGC here on how to create an Android Plugin For Unity using Android Studio

I’m not really sure about Android Studio but in ADT I use the export functionality by right-clicking on the project. With this you can create your .jar and place it wherever you want. Unity needs it to be on a specific folder to see it when running on a device (unfortunately I don’t remember it well, but it should be something like Assets/Plugins/Android).

Yes, you can use Android Studio to generate your jars from a Library.
In my case the jar file was located very well hidden in the app build folder, under

<ProjectRootDir>/<AppModuleName>/build/exploded-aar/<ProjectName>/<LibraryModuleName>/unspecified/classes.jar

My example setup for this:

  • A app module containing nothing but a minimal Android App (Including a MainActivity)
  • A library module that contains the library code
  • Add a dependency from your app to your library e.g. add: compile project(‘:library’)

If you build your app now it will also build the library and your apps build folder will contain the jar file under the location I explained above (in my case: PROJECT_ROOT/app/build/exploded-aar/SampleLibrary/library/unspecified/classes.jar).

分类: cocos2d, stackoverflow精选 标签:

Multiple screen resolution support in cocos2d v3?

2014年3月9日 没有评论

I am little confused with cocos2d v3’s support for multiple screen resolutions. If I use CCSetupScreenMode: CCScreenModeFlexible, what should be the default resolution of the image that I provide?

Currently, I have provided assets for all the iOS device resolutions along with suffixes and the correct images are loaded on iPhone “3.5inch” and iPad. However, the “-568h@2x” suffix for iPhone “4 inch” is not working fine. Am i using the wrong suffix?

I would like to avoid the need to use macros to determine which device the game is running on and load the images accordingly.

Thank you for your time!

The ScreenMode only defines if the screen scales up with the device size or not.

The fixed screen mode provides you with a stage that has a safe area and an unsafe area but the complete stage always has the same size.

In the flexible screen mode the root node of your scene will resize with the actual screen size, so you have to deal with dynamic sizing.

You can read more about the screen modes, image sizes and how to design a game for multiple screen resolutions in our tutorial.

In Cocos2D the suffixes are different from the ones UIKit uses. The suffixes are:

  • -ipad
  • -ipadhd
  • -hd
  • -iphone5hd
分类: cocos2d, stackoverflow精选 标签:

How to change the image of a CCSprite in cocos2d v3.x

2014年3月1日 没有评论

In cocos2d 2.x we change the image of a CCSprite using CCTexture. But in cocos2d 3.x CCTextureCache seems to be deprecated as Xcode warns me : “undeclared identifier ‘CCTextureCache’“. Or may be am I miss something as I’m new to cocos.

So how can we change the image of a CCSprite in v3 ??

Thank you.

I think I know how to do.

  1. We have to use a spriteSheet built with TexturePacker [note : may be it’s wrong to speak about external resources like it on SO] for example (let’s say we have 2 images : monster_01.png and monster_02.png).
  2. We add the .plist and the .png into xCode
  3. We put the spritesheet in cache
  4. and then we can create a CCSprite with a frame using a item of the spritesheet.
  5. This image can be changed.

Some code :

 // 3) We put in cache
 [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"monsterSpriteSheet.plist"];

 // 4) We create the sprite
 CCSprite * mySprite = [CCSprite initWithSpriteFrame: [CCSpriteFrame frameWithImageNamed: @"monster_01.png"]];

 // 5) To change image : 
 [mySprite setSpriteFrame:[CCSpriteFrame frameWithImageNamed: @"monster_02.png"]];

This works perfectly with cocos2d v3.

I spent 6 hours to have this process. Sometimes I feel stupid.

You can do it by using this

CCSpriteFrameCache and after that you can change you sprite by using function setSpriteFrame of ccsprite.

分类: cocos2d, stackoverflow精选 标签: