How to use CCGrid3DActions?

Topics: Actions and Control Logic
Apr 12, 2014 at 8:27 PM
I'm using Cocos2d-XNA OpenGL along with Monogame to write a game.

I want to add a CCLiquid action to my player shield in my game.

In my Player class:
public Player()
    // code snippet when creating new Player
    CCSprite shield = new CCSprite("Graphics\\shield");
    CCLiquid liq = new CCLiquid(3, new CCGridSize(20, 20), 10, 10);
    shield.Position = new CCPoint(ConvertToNodeSpace(this.BoundingBox.Center));
    ActionManager.AddAction(liq, shield, false);
This causes the action to run, but makes my game background turn black. I looked around online and this is a common problem when using these types of actions. People said the solution is to set the pixel format in CCDirector to RGBA8 (details for this here)

However, Cocos2d-XNA doesn't have this setPixelFormat function in CCDirector and from reading the source code, I haven't found a good way of doing so. I'm stumped!
Apr 14, 2014 at 2:28 AM
There's no reason for the background to be affected by the grid effect. The CCLiquid effect only changes the vertex location of the sprite's draw frame. If you have a picture to post that would help.
Apr 14, 2014 at 2:29 AM
Also, Effect test #5 shows how the CCLiquid action is used.
Apr 14, 2014 at 4:48 AM
You could also just do:

Apr 14, 2014 at 5:07 AM
The problem here is that the grid is not drawing using the alpha channel.
Apr 15, 2014 at 12:38 AM
Hi totallyevil,

Thanks so much for getting back so quick.

From reading about CCLiquid online, what you said makes sense (that it only changes the vertex).

I did take a look at the test suite before to see if that would help me. If you look at Effect test #5 (I'm assuming you mean LiquidDemo?) - you'll see the test runs the effect on the whole layer. Shown below:
var node = new CCNode();
CCActionInterval effect = getAction(); // this is the CCLiquid action
AddChild(node, 0, EffectTestScene.kTagBackground);

var bg = new CCSprite(TestResource.s_back3);
node.AddChild(bg, 0);
bg.AnchorPoint = new CCPoint(0.5f, 0.5f);
bg.Position = CCVisibleRect.Center;
So the effect is run on the node, which contains the background (bg) as the child. That's why i think it works. What I'm doing instead is running the effect on my shield, which is a child of my ship, which is a child of my background.

As requested, here's a picture:

The left is what it's suppose to look like. The right is what happens when I add a CCLiquid action to the shield. (notice also the shield position is down at the bottom left, when my player's location is where it is in the left image)

What you said sounds like the exact issue - the grid the CCLiquid action is on is not using an alpha channel (the transparency is off). The question is, how to enable it? As I said in my original post, people suggested using setPixelFormat in CCDirector, but that doesn't exist in the XNA port it seems like.
Apr 15, 2014 at 5:07 AM
try the current version. I posted a commit:

This should fix your problem. I adjusted the effects tests to exercise what I thought you were trying to do. Let me know if this does not fix your problem.
Apr 16, 2014 at 1:00 AM
Thanks totallyevil!

So this definitely fixed the background issue. It now runs the CCLiquid action without making the background black.

The only issue I'm trying to work out now is that the shield doesn't follow my ship when using this action. If you look in the picture up top to the right, the shield always wants to stay in the bottom left corner when using CCLiquid. If I remove the action, the shield follows the ship just fine.

One thing that works is if I run the CCLiquid action on my ship instead of the shield. The shield follows in this case, but my ship distorts along with the shield (not exactly what I was looking for, but a start).
Apr 16, 2014 at 4:14 AM
So you should have a "shield" sprite that has the liquid action running AND a movement action , both of which are in parallel.

shield.RunAction(new CCParallel(new CCLiquid(), new CCMoveBy()));

You need to adjust the moveby so that it runs in the same amount of time as the liquid, aka the shield duration. this is where you will likely NOT use an action. See, this is a strong case for a common ship "controller" that has a scheduled "update" and it updates the position of the ship outside of the action manager.

This technique is how we do the snowball movement in our Santa Shooter game. Santa moves with CCAction (a series of them), but we manage the snowballs manually. Sometimes conjugating CCAction instances is far too complicated for what it would take just to do your own controller.

MyGameLayer {
OnEnter() {

In your case, the liquid is staying at (0,0) because it is bound to that generic CCNode, which is not being acted upon. CCLiquid uses the target bounds to do the liquid action. You would have to apply the movement action on the CCNode that is running the liquid.
people suggested using setPixelFormat in CCDirector, but that doesn't exist in the XNA port it seems like.
XNA does not have pixel format like OpenGL. It uses blending states and effects/techniques. The shader model for XNA is more programmatic than OpenGL and so you don't have to do those silly things like setting pixel formats and such. All of that is handled by the effects. You just tell the framework what kind of blending state you want (CCBlendState). Everything you read in the XNA books applies to cocos2d-xna.