存档

2015年7月 的存档

[置顶] 即将推出最新的Cocos2d-x 课程博客,敬请关注~

2015年7月30日 没有评论

      许久不见,小伙伴们,你们还好么,本博即将推出最新的Cocos2d-x 课程博客,包括3D部分,敬请关注~[置顶]        即将推出最新的Cocos2d-x 课程博客,敬请关注~

版权声明:本文为博主原创文章,未经博主允许不得转载。

分类: 未分类 标签:

Error while changing player animation

2015年7月23日 没有评论

First of all , I’m using cocos2d 3.6
Everything works well until I press right arrow key on keyboard which execute the startRunning() function from keypress event listener,actions stopped successfully but on the next line ,this->runAction(Animate::create( runAnimation));, I get error.
runAnimation is OK.I guess the problem is in running new Action but I dont know what is it.

here’s the code:

#pragma once

#include "cocos2d.h"

using namespace cocos2d;

const int DIR_RIGHT = 1;
const int DIR_LEFT = -1;




class CPlayer: public Sprite
{

private:
    Animation* idleAnimation;
    Animation* runAnimation;
    Animation* bowAnimation;
    Animation* climbAnimation;
    SpriteFrame* jumpFrame;
    SpriteFrame* fallFrame;
    SpriteFrame* wallJumpFrame;

    boolean onGround = true;
    boolean running = false;
    int dir = DIR_RIGHT;
    float movementSpeed = 50; //50 unit in world space 
    float stateTime=0;
public:

    Animation* createAnimation(const char* format, float delay, bool loop){

        Animation* animation = Animation::create();
        char str[100] = { 0 };
        int frameIndex = 1;
        do
        {
            sprintf(str, format, frameIndex);

            auto frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(str);
            if (frame == NULL)
                break;
            animation->addSpriteFrame(frame);
            Texture2D::TexParams texParams = { GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE };
            frame->getTexture()->setTexParameters(texParams);
            frameIndex++;
        } while (true);
        int loops = 1;
        if (loop)
            loops = -1;
        animation->setDelayPerUnit(delay);
        animation->setLoops(loops);


        return animation;

    }

    CPlayer(){

        idleAnimation = createAnimation("Idle/player_idle_%d.png", .2f, -1);
        runAnimation = createAnimation("Run/player_run_%d.png", .5f, -1);
        bowAnimation = createAnimation("Bow/bow_%d.png", .2f, -1);
        climbAnimation = createAnimation("Climb/player_climb_%d.png", .2f, -1);
        jumpFrame = SpriteFrameCache::getInstance()->getSpriteFrameByName("Fall-Jump-WallJ/player_climb_jump.png");
        fallFrame = SpriteFrameCache::getInstance()->getSpriteFrameByName("Fall-Jump-WallJ/player_climb_fall.png");
        wallJumpFrame = SpriteFrameCache::getInstance()->getSpriteFrameByName("Fall-Jump-WallJ/player_climb_wall_jump.png");

        this->runAction(Animate::create(idleAnimation));
    }

    CREATE_FUNC(CPlayer);

    void startRunning(){
        running = true;

        if (onGround){
            this->stopAllActions();
            this->runAction(Animate::create( runAnimation));
        }
    }

    void endRunning(){
        running = false;
        if (onGround){
            this->stopAllActions();
            this->runAction(Animate::create(idleAnimation));
        }

    }

    void update(float delta){
        stateTime += delta;
        if (onGround && running){
            this->setPositionX(this->getPositionX() + delta*  movementSpeed*dir);

        }
    }

    void headToRight(){
        this->setFlipX(false);
        dir = DIR_RIGHT;
    }

    void headToLeft(){
        this->setFlippedX(true);
        dir = DIR_LEFT;
    }



};

Your createAnimation method returns an autoreleased animation object, which is released before you use it.

To fix this issue you need to retain your autoreleased objects after you create them, and release them in destructor or when you don’t need them no more:

CPlayer(){
    idleAnimation = createAnimation("Idle/player_idle_%d.png", .2f, -1);
    runAnimation = createAnimation("Run/player_run_%d.png", .5f, -1);
    bowAnimation = createAnimation("Bow/bow_%d.png", .2f, -1);
    climbAnimation = createAnimation("Climb/player_climb_%d.png", .2f, -1);
    idleAnimation->retain();
    runAnimation->retain();
    bowAnimation->retain();
    climbAnimation->retain();
    jumpFrame = SpriteFrameCache::getInstance()->getSpriteFrameByName("Fall-Jump-WallJ/player_climb_jump.png");
    fallFrame = SpriteFrameCache::getInstance()->getSpriteFrameByName("Fall-Jump-WallJ/player_climb_fall.png");
    wallJumpFrame = SpriteFrameCache::getInstance()->getSpriteFrameByName("Fall-Jump-WallJ/player_climb_wall_jump.png");

    this->runAction(Animate::create(idleAnimation));
}

virtual ~CPlayer() {
    idleAnimation->release();
    runAnimation->release();
    bowAnimation->release();
    climbAnimation->release();
}
分类: stackoverflow精选, unity3d 标签:

Sprite tracking touch

2015年7月14日 没有评论

I want to implement tracking (following) touch by a sprite with rotation in cocos2d-x. You can see this effect here: https://www.youtube.com/watch?v=RZouMyyNGG8 (2:10).

Here’s my code in touchMove:

_destinationX = touchPoint.x;
_destinationY = touchPoint.y;

_dx = _destinationX - draggedItem->getPositionX();
_dy = _destinationY - draggedItem->getPositionY();

_vx = _dx;
_vy = _dy;

float d = sqrtf((_dx*_dx)+(_dy*_dy));

//nice easing when near destination
if (d < 50 && d > 3){
    _vx *= d / 50.0f;
    _vy *= d / 50.0f;
}
else if(d <= 3){
    _vx = _vy = 0;
}

draggedItem->setPosition(draggedItem->getPosition() + Point(_vx, _vy));

float rad = atan2(_dy, _dx);
float rotateTo = CC_RADIANS_TO_DEGREES(-rad);
if (rotateTo > draggedItem->getRotation() + 180) rotateTo -= 360;
if (rotateTo < draggedItem->getRotation() - 180) rotateTo += 360;

draggedItem->setRotation(rotateTo);

It works, but sprite destination point is on it’s center, so if I on touchBegin won’t start from it’s center it’s not looking too well.

So I’m calculating offset in touch begin as well as initial rotation:

offsetPoint = Point(touchPoint.x - draggedItem->getPositionX(), touchPoint.y - draggedItem->getPositionY());
offsetRotation = atan2(offsetPoint.y, offsetPoint.x);

I also added these lines in touch move (on the top):

float alfa = offsetRotation;
float beta = CC_DEGREES_TO_RADIANS(draggedItem->getRotation());
float gamma = alfa + beta;

float radius = offsetPoint.length();
float ax = cosf(gamma) * radius;
float ay = sinf(gamma) * radius;

so destination would be:

_destinationX = touchPoint.x + ax;
_destinationY = touchPoint.y + ay;

But it doesn’t work, where’s an issue? Sprite is jumping all around.

As I’m not familiar at all with Obj-C or C++, I’m gonna give you the answer in Swift. Then, you’ll be able to either insert it into your project or ‘translate’ to Obj-C/C++. Anyway:

Inside the file that represents your gameplay scene, declare a variable that keeps track of whether the user is currently touching the screen or not. I’ll also assume the sprite you want to follow the touch is represented by some variable (named ‘sprite’ here):

var touchingScreen:Bool = false // needs 'false' as initial value.
weak var sprite:CCSprite!; // represents a connection to the sprite.

Then, you’ll also want a variable that represents the difference between the value of the point currently being touched and the point your sprite is located in the x and y axises:

var diffTouchSpriteX:CGFloat!; // not necessary to initialize it with any default value.
var diffTouchSpriteY:CGFloat!; // same.

The next step is to update these two variables’ values when necessary. Lets create a method for that:

func updateDiff(touchX: CGFloat, touchY: CGFloat) {
  self.diffTouchSpriteX = touchX - self.sprite.position.x;
  self.diffTouchSpriteY = touchY - self.sprite.position.y;
}

Now it’s time to make use of the touch methods provided for handling the touch input at specific moments. Let’s assign a value to diffTouchSpriteX and diffTouchSpriteY variables and set touchingScreen to true when the user touches the screen, update diffTouchSpriteX and diffTouchSpriteY values when the user moves its finger on the screen and finally set touchingScreen to false once the touch is interrupted:

override func touchBegan(touch: CCTouch!, withEvent event: CCTouchEvent!) {
  self.updateDiff(touch.locationInWorld().x, touch.locationInWorld().y);
  self.touchingScreen = true;
}

override func touchMoved(touch: CCTouch!, withEvent event: CCTouchEvent!) {
  self.updateDiff(touch.locationInWorld().x, touch.locationInWorld().y);
}

override func touchEnded(touch: CCTouch!, withEvent event: CCTouchEvent!) {
  self.touchingScreen = false;
}

override func touchCancelled(touch: CCTouch!, withEvent event: CCTouchEvent!) {
  self.touchingScreen = false;
}

Finally, the last step. Inside the Cocos2d method fixedUpdate(), add a conditional to move the character if the screen is being currently touched:

override func fixedUpdate(delta: CCTime) {
  if (self.touchingScreen) {
    self.sprite.runAction(CCActionMoveBy(duration: 1/ 60, position: CGPoint(x: self.diffTouchSpriteX / 60, y: self.diffTouchSpriteY / 60)));
  }
}

The fixedUpdate() cocos2d method runs at a constant rate (1 time each second, if I remember well). The runAction() method here will update the sprite position by adding ‘x’ to its ‘x’ value of its current position and ‘y’ to its ‘y’ value of its current position. So, at this rate it would take one second for the sprite to reach the current touch location, but this of course is something you can easily manipulate.

分类: stackoverflow精选, unity3d 标签:

EXC_BAD_ACCESS at lauch for EAGLContext renderbufferStorage: fromDrawable: in Cocos2d app whie debugging

2015年7月14日 没有评论

Using default cocos2d-swift app I’m receiving the error EXC_BAD_ACCESS on my iPad Mini 2 at the line:

BOOL rb_status = [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer];

But if I try to launch the app without debug all works fine. If I use debug on any virtual device I receive no error too.
Why it doesn’t work? How to remove this error?

Looks like this is an issue on certain devices on iOS 8.3+. It works for me on almost all devices but the iPad mini 2 fails for me as well. The short of it is that there’s nothing wrong with the call itself. Seems to be an Xcode bug with those devices for some reason. You can get around it (until Apple fixes it) by:

In Xcode, go to Product -> Scheme -> Edit Scheme …
And for the Run Debug configuration (on left side) choose “Options” (on right side) and configure “GPU Frame Capture” as Disabled.

For more information, check out this thread:
https://github.com/BradLarson/GPUImage/issues/2022#issuecomment-118943746

I found the device hadn’t got the last iOS version. When I updated the iOS version of the devices the error has removed.

分类: stackoverflow精选, unity3d 标签:

自动生成材质Material(Unity3D开发之十九)

2015年7月12日 没有评论

猴子原创,欢迎转载。转载请注明: 转载自Cocos2Der-CSDN,谢谢!
原文地址: http://blog.csdn.net/cocos2der/article/details/46854411

项目中,有时候导入一些资源时候,需要对应创建材质球,如果每次自己动手创建,还是挺麻烦的,下面是如何导入资源时候自动创建材质球。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using System.IO;

public class BuildMaterial : UnityEditor.AssetModificationProcessor
{

    //生成出的Material的路径
    private static string MaterialsPath = "Assets/Resources/Skin/";

    // 创建菜单按钮,手工调用创建材质
    [MenuItem ("HETools/BuildMaterials")]
    static void CreateMateral ()
    {
        Object[] selectObject = Selection.objects;

        List<string> path = new List<string> ();
        foreach (Object obj in selectObject) {
            path.Add (AssetDatabase.GetAssetPath (obj));
        }

        foreach (string p in path) {
            CreateOneMateral (p);
        }
        System.GC.Collect ();
    }

    // 监控assets资源添加,发现指定目录ThemeTile有新增加的texture,就自动生成材质
    public static void OnWillCreateAsset (string path)
    {
        int index = path.LastIndexOf (".");
        string file = path.Substring (index);
        string[] pathArr = path.Split ('/');
        if (pathArr [pathArr.Length - 3] != "ThemeTile")
            return;

        CreateOneMateral (path);
        System.GC.Collect ();
    }

    // 创建材质球
    static void CreateOneMateral (string p)
    {
        p = p.Replace (".meta", "");
        Debug.Log ("CreateOneMateral from path: " + p);

        int pos = p.LastIndexOf ('/');
        if (pos == -1)
            return;

        string[] strArr = p.Split ('/');

        string themeIDStr = strArr [strArr.Length - 2];

        Texture textur = (Texture)AssetDatabase.LoadAssetAtPath (p, typeof(Texture)) as Texture;

        string name = strArr [strArr.Length - 1];

        int y = name.IndexOf ('.');
        name = name.Substring (0, y);
        Material mater = new Material (Shader.Find ("Mobile/VertexLit"));
        mater.mainTexture = textur;

        AssetDatabase.CreateAsset (mater, MaterialsPath + themeIDStr + "/" + name + ".mat");
    }
}

自动生成材质Material(Unity3D开发之十九)
注意,上面代码中我是规定了只有指定的目录添加texture才会自动生成材质,所以使用时候,请自行修改下。

这里发现了个问题:
导入贴图时候,自动创建出来的材质球丢失了纹理图,而采用菜单按钮点击创建出来的正常。问题还没有解决,有哪位朋友知道解决办法可以告诉我下。

版权声明:本文为博主原创文章,未经博主允许不得转载。

分类: 未分类 标签:

Unity3d 使用 Node Canvas

2015年7月10日 没有评论

Node Canvas

Node Canvas是一个行为树的插件,它是图形化的操作模式,可以简化开发逻辑,官方文档在这 .

基本元素

流程上的原则是,一旦返回值为False则向上返回。一般在BehaviourTreeOwner组件上,要勾选Repeat循环监测。通常这些监测指的是各子树的条件判断。常用的元素如下:

元素名称 对应逻辑 备注
Action 操作 各种操作,用过都说好
Condition 条件判断 各种判断,没它真不成
Selector 选择器 逻辑|| 如果有返回为真的子树,则停止执行,返回真
Sequencer 顺序器 逻辑&&与Selector相反,有返回假的,则返回假
Parallel 并行器 “同时”执行子树,返回值根据Policy取舍
Conditional 条件节点 如果不合条件,直接返回False,不执行子节点
Filter 过滤器 限制性访问,比如初始化时只进一次
Iterate 迭代器 做循环用
OverrideAgent 复写变量 对于子节点,不使用行为树挂载的Agent

快捷键

Here are the node/canvas controls and shortcuts:

  • Right Click on the canvas to add a new node.
  • Click & Drag to pan the node.
  • Middle Click & Drag in the canvas to pan the canvas.
  • Shift + Click & Drag a node to pan it and all of it’s children together; panning a branch.
  • Click & Drag from a port over a target node to connect. Right click a connected port to disconnect.
  • Click & Drag from a port into empty canvas space, will show context menu to automaticaly create and connect a new node.
  • Click a connected port or connection itself to select the connection.
  • Delete the selected node or connection with Delete Key, or through the right click context menu.
  • Duplicate a node with Control+D or through the right click context menu.
  • Double Clicking a node will open it’s script in the IDE, unless it’s a Nested Node in which case it will open the nested tree.
  • Relink a connection by click and dragging it over a new node.
  • Hit “F” will focus the canvas on the center of all your nodes within it.
  • Mouse Scroll Wheel will Zoom In/Out the canvas.
  • Left Click and Drag in the canvas, will allow you to create a selection rectangle.
  • Holding Control while making a rectangle selection will create a Canvas Group.

On right click on a node or connection, a context menu will show up. Depending on the node or connection type there might be different extra options. Following are the common operations:

  • Delete: Deletes the Node or Connection. (available in multiselection as well).
  • Copy Node: Copies the Node possible to Paste later. (available in multiselection as well)
  • Copy Assigned Task: Will copy the task that has been assigned to the Node or Connection.
  • Paste Assigned Task: Will paste the currently copied Task to the Node or Connection and assign it.

版权声明:本文为博主原创文章,未经博主允许不得转载。

分类: 未分类 标签:

iOS8 UILocalNotification 增加启动授权

2015年7月8日 没有评论

猴子原创,欢迎转载。转载请注明: 转载自Cocos2Der-CSDN,谢谢!
原文地址: http://blog.csdn.net/cocos2der/article/details/46810357

好久没接入UILocalNotification了,今天接入时发现没有权限启动通知。
错误如下:

Attempting to schedule a local notification <UIConcreteLocalNotification: 
0x174178540>{fire date = (null), time zone = (null), repeat interval =
0, repeat count = UILocalNotificationInfiniteRepeatCount, next fire
a badge number but haven't received permission from the user to badge
the application

看了下API,原来iOS8增加了启动授权,需要用户同意下才能注册通知。

添加如下代码:

- (void)RegistNotificationSettings
{
    float sysVersion=[[UIDevice currentDevice]systemVersion].floatValue;
    if (sysVersion>=8.0) {
        UIUserNotificationType type = UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound;
        UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:type categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:setting];
    }
}

你可以在注册通知之前调用,也可以在app启动时候调用

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
    // todo ...

    [self RegistNotificationSettings];
    return YES;
}

注意:只要用户对app授权过了,以后即使删除再次安装,也默认为授权了。

版权声明:本文为博主原创文章,未经博主允许不得转载。

分类: 未分类 标签: