spudworks

  • 28 de Jan de 2015
  • Entrou em 18 de Jun de 2013
  • BigRed escreveu

    you wouldn't happen to know how to 'ccGLBindTexture2D()' bind the skeleton texture, or each attachment, if it is possible?

    The 'ccGLBindTexture2D()' call happens when the 'textureAtlas->drawQuads()' call happens in CCSkeleton.cpp. Essentially, the 'draw()' function updates where each section of the atlas should be drawn then all the 'draws' happen at once.

    Not sure what you're looking to do here or how this helps but... there you go.

    Are you thinking about applying different shader programs to the draws? Because, if so, I'd be curious to see what you come up with.

  • I think the problem with setting each attachment as a fixture is that you can't set positions on fixtures like you can on bodies. I was just playing with the code and wasn't finding an immediate way to manipulate a fixture in this way.

    As to your previous post, yeah, I think that's still the best tutorial. When Spine (and the development community around it) grows a bit more, hopefully we'll get something a little clearer and without all the Java specific stuff. Personally, I find it easier to see something in C and turn it into Java than the other way around.

  • Hey-o Esoteric,

    You have done awesome work and it's clear it's being picked up by the community. I was wondering, if for sheer search results sake, you might not want to start dividing up the forums into "Application" and "Coding" sections so people know clearly where to post and where to read.

    At some point, it may make sense to divide coding up by platform but, right now, most of the stuff is translatable and doesn't need to be separated. But I know I'm interested in the coding side and a lot of app specific stuff comes up when I search. So... maybe differentiating between the two would make these forums even more useful?

    Loving the work that's been done and the reach outs to the various communities. Spine is awesome and it's been sooooo easy to drop into my project. We have two licenses. Just trying to throw a suggestion out there that might help lower your workload.

  • The thing with Cocos2d-x, if you're developing in XCode, is to add the images directories under Resources as actual directories and not groups. Once that's done, in your AppDelegate.cpp, you can switch based upon screen size to different directories based on resolutions. As per the example:

    vector<string> searchPath;
    CCSize frameSize = view->getFrameSize();
    if (frameSize.height > 640) {
       searchPath.push_back("hd);
    }
    

    This will effectively ignore asests of the wrong size and only load asets of the correct size.

    If you're not developing in XCode, then you need to alter you build file depending upon the resolution the target is aimed at.

  • From what I've seen is you need to make each variation an attachment to the skeleton but not part of the default skin. Then, in the runtime, you assign the specific attachments to the specific bones (as defined in the exported JSON), and that will give you the variation you're looking for.

    For instance, my animator designed a skeleton with a fist, a knife, and a gun. The default skin has the fist being used but, programmatically, I can assign the knife or the gun. You can do the same thing with all the body parts or define skins that use different variations by default.

    I can't give you specific Java code but in C++, it looks like:

    this->setAttachment("FistLeft", "knife");

    Where "FistLeft" is the bone and "knife" is the attachment. (I don't want to go crazy, but I assume the API is pretty much the same but with dot notation.)

    So long as all the images are part of the same sprite sheet, it should work without any problems and without any increase in memory usage. Again, my knowledge of Java in this instance is limited but in C++ it would be rendered as a batch node and, thus, a single draw command.

    There's not really any penalty for defining a hundred skins that use a hundred variations of the same attachments because it's really only a JSON file being loaded. So, you can either define them as skins or just a bunch of attachments available to the skins (that you assign in your code) and it would all be pretty much the same.

    I'd be curious in performance tests between assigning attachments via code versus skins but I'm willing to bet it would pretty much be a wash unless the JSON parser was really slow on your platform.

  • Tetheta escreveu

    Just came back from a few days absence, thanks for putting up the code! I definitely appreciate it 🙂

    No worries. Just one thing I found when device testing, ignore the stupid CC_CONTENT_SCALE_FACTOR() stuff. All it did was screw things up.

    I hope if you make any discoveries you'll share too. We'll all be better off for it.

  • Just an update with better code, in case anyone's interested. For my sprite, this fixture perfectly matches the general outline of my hero and all the coordinates match correctly.

    void Hero::setBody(b2World *world) {
    	float definedHeight = (100 * CC_CONTENT_SCALE_FACTOR()) / PTM_RATIO;
    	b2PolygonShape boxPoly;
    	boxPoly.SetAsBox((40 * CC_CONTENT_SCALE_FACTOR()) / PTM_RATIO,
    					 definedHeight,
    					 b2Vec2(0.0, definedHeight),
    					 0.0f);
    	
    
    b2BodyDef boxBodyDef;
    boxBodyDef.userData = this;
    boxBodyDef.type = b2_dynamicBody;
    boxBodyDef.fixedRotation = true;
    boxBodyDef.allowSleep = true;
    float tmpX = this->getPositionX() / PTM_RATIO;
    float tmpY = this->getPositionY() / PTM_RATIO;
    
    boxBodyDef.position.Set(tmpX, tmpY);
    this->body = world->CreateBody(&boxBodyDef);
    
    b2Fixture *mainBody = this->body->CreateFixture(&boxPoly, HERO_DENSITY);
    mainBody->SetRestitution(0.0f);
    CCLog("Estimated sprite size: W: %f, H: %f", width, height);
    
    
    float leftRightBoxSize = (10 * CC_CONTENT_SCALE_FACTOR()) / PTM_RATIO;
    b2PolygonShape rightSensorShape;
    rightSensorShape.SetAsBox(leftRightBoxSize, leftRightBoxSize, b2Vec2(1.9, 0.8 + definedHeight), 0);
    
    b2FixtureDef rightSensorDef;
    rightSensorDef.isSensor = true;
    rightSensorDef.shape = &rightSensorShape;
    rightSensorDef.density = 0.0f;
    
    b2Fixture *rightSensor = this->body->CreateFixture(&rightSensorDef);
    
    b2PolygonShape leftSensorShape;
    leftSensorShape.SetAsBox(leftRightBoxSize, leftRightBoxSize, b2Vec2(-1.9, 0.8 + definedHeight), 0);
    
    b2FixtureDef leftSensorDef;
    leftSensorDef.isSensor = true;
    leftSensorDef.shape = &leftSensorShape;
    leftSensorDef.density = 0.0f;
    
    b2Fixture *leftSensor = this->body->CreateFixture(&leftSensorDef);
    }
    
  • Sure thing. It's not perfect yet, but this is basically how I put together the body and fixtures. Basically, I subclassed CCSKeletonAnimation and added the method setBody(). The left and right sensors match up with where his fists are when punching and, if his "punching" boolean is false, then I just ignore contacts there. Or... at least that's the idea.

    void Hero::setBody(b2World *world) {
            b2PolygonShape boxPoly;
    	boxPoly.SetAsBox((40 * CC_CONTENT_SCALE_FACTOR()) / PTM_RATIO, (100 * CC_CONTENT_SCALE_FACTOR()) / PTM_RATIO);
    	
    
    b2BodyDef boxBodyDef;
    boxBodyDef.userData = this;
    boxBodyDef.type = b2_dynamicBody;
    boxBodyDef.fixedRotation = true;
    boxBodyDef.allowSleep = true;
    float tmpX = this->getPositionX() / PTM_RATIO;
    float tmpY = this->getPositionY() / PTM_RATIO;
    
    boxBodyDef.position.Set(tmpX, tmpY);
    b2Body *box = world->CreateBody(&boxBodyDef);
    
    box->CreateFixture(&boxPoly, 1);
    
    float leftRightBoxSize = (10 * CC_CONTENT_SCALE_FACTOR()) / PTM_RATIO;
    b2PolygonShape rightSensorShape;
    rightSensorShape.SetAsBox(leftRightBoxSize, leftRightBoxSize, b2Vec2(1.9, 0.8), 0);
    
    b2FixtureDef rightSensorDef;
    rightSensorDef.isSensor = true;
    rightSensorDef.shape = &rightSensorShape;
    
    b2Fixture *rightSensor = box->CreateFixture(&rightSensorDef);
    
    b2PolygonShape leftSensorShape;
    leftSensorShape.SetAsBox(leftRightBoxSize, leftRightBoxSize, b2Vec2(-1.9, 0.8), 0);
    
    b2FixtureDef leftSensorDef;
    leftSensorDef.isSensor = true;
    leftSensorDef.shape = &leftSensorShape;
    
    b2Fixture *leftSensor = box->CreateFixture(&leftSensorDef);
    }
    

    The only problem with this code at the moment is that when I feed it's position data to the sprite, it's currently giving me the Y coord in the center of the box. I'm working on it and will post an update when I have it down.

  • Thanks for your replies, guys. I've actually decided to go a much simpler route for physics because, honestly, I don't need every attachment to be a a physical structure.

    If you look at the screenshot below, you can see how I've built the new body and added a couple of sensors (for punching collisions).

    Essentially, I subclassed CCSkeletonAnimation and added a weak reference to the b2Body (among other things) and a method which sets up the body for being added to the world.

    If anyone's interested, I can post the code. But the result is what's below.

  • I've seen that problem when loading the wrong sprite sheet and atlas combo. All the coordinates are wrong, thus the problem.

  • Hey everyone,

    I'm having a problem properly creating Box2d bodies on my animation. I've followed the Java tutorial but, and this is probably me, but I'm clearly losing something in translation.

    As you can see from the screenshot I've attached above, the bodies aren't in the right spot and don't reflect the shape of the animation. Below is the code I'm using to set up the bodies.

    for (int i = 0; i < this->skeleton->slotCount; i++) {
    		Slot* slot = this->skeleton->slots[i];
    		if (!slot->attachment || slot->attachment->type != ATTACHMENT_REGION) continue;
    		
    	RegionAttachment* attachment = (RegionAttachment*)slot->attachment;
    	
    	CCLog("Adding body shape: %s, width: %f, height: %f", attachment->super.name, attachment->width * attachment->scaleX, attachment->height * attachment->scaleY);
    	
    	b2PolygonShape boxPoly;
    	boxPoly.SetAsBox(attachment->regionWidth / PTM_RATIO,
    					 attachment->regionHeight / PTM_RATIO,
    					 b2Vec2((attachment->x + attachment->regionOffsetX) / PTM_RATIO, (attachment->y + attachment->regionOffsetY) / PTM_RATIO),
    					 attachment->rotation*3.14159265/180);
    	
    	
    	b2BodyDef boxBodyDef;
    	b2Body *box = world->CreateBody(&boxBodyDef);
    	box->CreateFixture(&boxPoly, 1);
    }
    

    The screen shot below shows the actual attachments with debugSlots set to true.

    Can anyone help with this? I've been beating my head against this for a couple of days now and this is the closest I've gotten to having anything. Any help would be extremely appreciated.

  • It looks really great and the art is super original. The animation is super smooth and the camera handling is really nice.

    Really interested to see new updates.

  • Your game looks awesome!

    Since you're doing dev for Android, are you using cocos2d-x? If so, would you be willing to share how you set up your physics on your character animation? I'm trying to follow the Java code but I'm clearly missing something in the translation.

  • I took everything from spine-c and spine-cocos2dx and dumped them into the same folder for my project. It's maybe not the best as far as updating the runtimes go in the future but it's the easiest way for me without maintaining a bunch of different folders.