How can I pass an arbitrary group of parameters “through” a method? - actionscript-3

I am using AIR v32.0. I have a class which extends netConnection. I need to override an existing method which receives an arbitrary group of parameters. I need to do a few odds & ends then let the original code handle the rest. I understand how to receive the parameters “…parameters” but I can’t find the proper way of calling the original code when I am done.
What I have so far which does not work is;
public override function call(strCommand:String, rspResponder:Responder,...parameters):void
{
trace("parameters.length=" + parameters.length)
if (parameters.length == 0)
{
super.call(strCommand, rspResponder);
}
else
{
super.call(strCommand, rspResponder, parameters);
}
}
The line;
super.call(strCommand, rspResponder);
Works as expected.
The line;
super.call(strCommand, rspResponder, parameters);
does not appear to be handled by the “call” method properly.
How can I properly pass the “…parameters” on to the “super.call” method of the netConnection class?
EDIT:
There is no error per se. What happens is it sends a message off to the FluorineFX web service in a format the web service is not expecting which then Ralphs on its shoes. The error is "Processing level error description Could not find a suitable method with name LoginCheck" If I remove the overidden method everything works fine.
When I look at the output results in Fiddler, there is a difference in some of the non printable characters between running it with & without the overridden method. But I cannot determine what the practical difference is.
Additional EDIT:
I have a very poor partial work around (at least it works), and perhaps this will spark someone's imagination. I would be embarrassed to put this into production.
public override function call(strCommand:String, rspResponder:Responder,...parameters):void
{
trace("parameters.length=" + parameters.length)
switch (parameters.length)
{
case 0:
super.call(strCommand, rspResponder);
break;
case 1:
super.call(strCommand, rspResponder, parameters[0]);
break;
case 2:
super.call(strCommand, rspResponder, parameters[0], parameters[1]);
break;
case 3:
super.call(strCommand, rspResponder, parameters[0], parameters[1], parameters[2]);
break;
case 4:
super.call(strCommand, rspResponder, parameters[0], parameters[1], parameters[2], parameters[3]);
break;
case 5:
super.call(strCommand, rspResponder, parameters[0], parameters[1], parameters[2], parameters[3], parameters[4]);
break;
case 6:
super.call(strCommand, rspResponder, parameters[0], parameters[1], parameters[2], parameters[3], parameters[4],
parameters[5]);
break;
case 7:
super.call(strCommand, rspResponder, parameters[0], parameters[1], parameters[2], parameters[3], parameters[4],
parameters[5], parameters[6]);
break;
case 8:
super.call(strCommand, rspResponder, parameters[0], parameters[1], parameters[2], parameters[3], parameters[4],
parameters[5], parameters[6], parameters[7]);
break;
case 9:
super.call(strCommand, rspResponder, parameters[0], parameters[1], parameters[2], parameters[3], parameters[4],
parameters[5], parameters[6], parameters[7], parameters[8]);
break;
case 10:
super.call(strCommand, rspResponder, parameters[0], parameters[1], parameters[2], parameters[3], parameters[4],
parameters[5], parameters[6], parameters[7], parameters[8], parameters[9]);
break;
}
}

To pass the extra ...arguments, which come in a form of Array, you need to invoke the method in a special Function.apply(...) way. The thing is, a Function in AS3 (or maybe in ECMA standards in general) is an Object too thus it has some own properties and methods, which, in certain cases, allow to perform some weird looking tricks.
public override function call(strCommand:String, rspResponder:Responder, ...parameters:Array):void
{
trace("parameters.length=" + parameters.length);
// Create a single deflated Array of incoming arguments.
var args:Array = [strCommand, rspResponder].concat(parameters);
// A special way of invoking a function where you provide
// all its arguments in a form of a single Array.
super.call.apply(this, args);
}
Keep in mind, I didn't test that. Also, I never tried apply(...) on overrides, but in theory there should be no problems, I think?

Related

Unable to setRotation to PhysicsBody::createBox in cocos2dx

I'm able to rotate the sprite 90-degree angle but unable to change the angle of the physics body. My purpose is to connect multiple sprites with createBlock() to make a breakable tower object. I want to add setRotation() to PhysicsBody::createBox but error showed up and was unable to implement what I want to do. I googled for some solutions but wasn't able to find a helpful solution to my problem. I would love to hear some tips or examples from you!
Here is the function to create a Block sprite. Added 90 so that the sprite will be rotated to 90 degrees.
createBlock(BlockType::Block1, Point(586, 150), 90);
↓
void GameLayer::createBlock(BlockType type, Point position, float angle)
{
std::string fileName;
switch (type)
{
case BlockType::Block1:
fileName = "block1.png";
break;
case BlockType::Block2:
fileName = "block2.png";
break;
case BlockType::Roof:
fileName = "roof.png";
break;
default:
fileName = "stone.png";
break;
}
auto block = Sprite::create(fileName.c_str());
block->setPosition(position);
block->setRotation(angle);
block->setTag(T_Block);
PhysicsBody* body;
switch (type)
{
case BlockType::Block1:
case BlockType::Block2:
{
body = PhysicsBody::createBox(block->getContentSize(), PhysicsMaterial(0.5, 0.5, 0.3));
body->setDynamic(true);
body->setContactTestBitmask(0x01);
break;
}
case BlockType::Roof:
{
Point points[3] = {Point(-50, -25), Point(0, 25), Point(50, -25)};
body = PhysicsBody::createPolygon(points, 3, PhysicsMaterial(0.5, 0.5, 0.3));
body->setDynamic(true);
body->setContactTestBitmask(0x01);
break;
}
default:
{
body = PhysicsBody::createBox(block->getContentSize(), PhysicsMaterial(0.5, 0.5, 0.3));
body->setDynamic(false);
break;
}
}
block->setPhysicsBody(body);
addChild(block, Z_Block);
}
If you want to rotate not only the sprite but also physics, we must call setRotation(angle) after calling block->setPhysicsBody(body).
So, please fix code like below...
1st: block->setPhysicsBody(body);
next: block->setRotation(angle);
last: addChild(block, Z_Block);
I know your code and have experienced same problem before! I have this text book, too.(^ ^)

How to catch Press and Hold key board event in cocos2d-x?

I have a function here for moving a Sprite on every key pressed. Now I also want to move it on key hold instead of pressing the key repeatedly but I have no idea how to do it. Please guide me, your help is very much appreciated.
keyBoardListener->onKeyPressed = [](EventKeyboard::KeyCode keyCode, Event* event)
{
Vec2 location = event->getCurrentTarget()->getPosition();
switch (keyCode)
{
case EventKeyboard::KeyCode::KEY_LEFT_ARROW:
case EventKeyboard::KeyCode::KEY_A:
event->getCurrentTarget()->setPosition(location.x - 10.0f, location.y);
break;
case EventKeyboard::KeyCode::KEY_RIGHT_ARROW:
case EventKeyboard::KeyCode::KEY_D:
event->getCurrentTarget()->setPosition(location.x + 10.0f, location.y);
break;
case EventKeyboard::KeyCode::KEY_UP_ARROW:
case EventKeyboard::KeyCode::KEY_W:
event->getCurrentTarget()->setPosition(location.x, location.y + 10.0f);
break;
case EventKeyboard::KeyCode::KEY_DOWN_ARROW:
case EventKeyboard::KeyCode::KEY_S:
event->getCurrentTarget()->setPosition(location.x, location.y - 10.0f);
break;
}
};
There's no event that triggers continuously when a key is pressed so one way to solve your problem is to have a global(or class or whatever) variable that tracks the movement on the x axis and one for the y axis.
To use only two variables and not a separate one for each key you could use 2 integers, let's say xMovement and yMovement and set their values to -1, 0 or 1, based on what keys are pressed. If xMovement is -1, move your sprite to the left, if it's 1 move it to the right and if it's 0 don't move it at all. Same thing for the y axis. To achieve this you should change your code like this:
keyBoardListener->onKeyPressed = [](EventKeyboard::KeyCode keyCode, Event* event)
{
switch (keyCode)
{
case EventKeyboard::KeyCode::KEY_LEFT_ARROW:
case EventKeyboard::KeyCode::KEY_A:
xMovement--;
break;
case EventKeyboard::KeyCode::KEY_RIGHT_ARROW:
case EventKeyboard::KeyCode::KEY_D:
xMovement++;
break;
case EventKeyboard::KeyCode::KEY_UP_ARROW:
case EventKeyboard::KeyCode::KEY_W:
yMovement++;
break;
case EventKeyboard::KeyCode::KEY_DOWN_ARROW:
case EventKeyboard::KeyCode::KEY_S:
yMovement--;
break;
}
};
Now you should also add a key release event, where the incrementation/decrementation should be the opposite from the key pressed event:
keyBoardListener->onKeyReleased = [](EventKeyboard::KeyCode keyCode, Event* event)
{
switch (keyCode)
{
case EventKeyboard::KeyCode::KEY_LEFT_ARROW:
case EventKeyboard::KeyCode::KEY_A:
xMovement++;
break;
case EventKeyboard::KeyCode::KEY_RIGHT_ARROW:
case EventKeyboard::KeyCode::KEY_D:
xMovement--;
break;
case EventKeyboard::KeyCode::KEY_UP_ARROW:
case EventKeyboard::KeyCode::KEY_W:
yMovement--;
break;
case EventKeyboard::KeyCode::KEY_DOWN_ARROW:
case EventKeyboard::KeyCode::KEY_S:
yMovement++;
break;
}
};
And now, to actually move you sprite, just do something like this in an update function that gets called every frame:
float newPosX = sprite->getPositionX() + (xMovement * 10.f);
float newPosY = sprite->getPositionY() + (yMovement * 10.f);
sprite->setPosition(newPosX, newPosY);
You'll also need some mechanism to ensure that xMovement and yMovement stay within the boundaries(in my example if you press both left arrow and the 'a' key the sprite will move twice as fast :P ), but this is just a rough example to demonstrate how to achieve continuous movement using keyboard events and an update function.

different kernels for different architectures

I am wondering if there is some easy way as to have different versions of a kernel for different architectures. Is their an easy way? or the only possibility is to define independent kernels in independent files and ask nvcc to compile to different architecture per file?
You can do that by compiler directives. Something like
__global__ void kernel(...) {
# if __CUDA_ARCH__ >= 350
do something
# else
do something else
# endif
}
With a little more C++ JackOLanterns Answer slightly modified:
template <unsigned int ARCH>
__global__ void kernel(...)
{
switch(ARCH)
{
case 35:
do something
break;
case 30:
do something else
break;
case 20:
so something else
break;
default:
do something for all other ARCH
break;
}
}
EDIT: to remove the error #sgar91 pointed out:
you can call the kernel with the porperties form your CUDA device queried via
cudaGetDeviceProperties(&props, devId);
unsigned int cc = props.major * 10 + props.minor;
switch(cc)
{
case 35:
kernel<35><<<1, 1>>>(/* args */);
break;
...
}

multiple variables and complex expressions in AS3 switch case statements

I'm cleaning up some AS3 code today, and want to replace a bunch of messy if/else if/else statements with a switch statement.
private const myConstant:int = 3;
private var someNumber:int = 1000;
for(var i:int=0; i < someNumber; i++){
switch(i, myConstant){
case 0:
function1();
break;
case (i % myConstant == 0):
function2();
break;
default:
function3();
}
}
My program has many more case statements and variables, however, I cut it down for the sake of brevity. In this example, I want to call function2() on every third iteration of the loop. Now, myConstant is an important setting for the class which is used elsewhere, so I can't just put a literal 3 in the expression.
Can I evaluate multiple variables (and constants) in one switch?
Can I evaluate expressions such as the second case statement in my example?
The switch keyword takes only one expression inside the parentheses (your comma separated variables above would not evaluate to one expression).
The case keyword also expects to evaluate one expression.
In your example, it's unnecessary to pass either i or myConstant into the switch statement. These vars are declared immediately above the switch and are accessible to any code inside the switch statement.
Perhaps you want something like this:
for (var i:int = 0, i < someNumber; i++)
{
switch (true)
{
case i == 0:
function1();
break;
case i % myConstant == 0:
function2();
break;
default:
function3();
}
}

Minimax with Alpha-beta pruning, getting the result

I have followed the pseducode on the wikipedia article, and I think I got it working. However, it returns the score, and that doesn't exactly help when I want to know what move I want to make.
I tried what I think would be a way to get the best move, but I don't think it is working as when I actually try to play against it (chess), the AI makes somewhat retarded moves with a depth level of 3.
Here is my function:
public static function alphaBeta(node, depth, alph, beta, team, tellTheMove:Boolean = false):* {
var pointer:ChessMove;
if (depth == 0) {
return scoreOf(node);
}
var childrenOf:Vector.<ChessMove > = returnPossibleMoves(node,team);
if (childrenOf.length == 0) {
return scoreOf(node);
}
if (team == 0) {
for (var i in childrenOf) {
var that:Number = alphaBeta(childrenOf[i],depth - 1,alph,beta,1);
if(tellTheMove){
}
if (that > alph) {
alph = that;
if(tellTheMove){
pointer = childrenOf[i];
}
}
if (beta <= alph) {
break;
}
}
if(tellTheMove){
return pointer; //Returns the move that's score last exceeded alpha.
}
return alph;
} else {
for (var j in childrenOf) {
var that2:Number = alphaBeta(childrenOf[j],depth - 1,alph,beta,0);
if (that2 < beta) {
beta = that2;
}
if (beta <= alph) {
break;
}
}
return beta;
}
}
Depth 3 is very little for a problem like chess. At this depth most of the power depends on your final evaluation function. This evaluation function is very hard to do in way that it can predict the value of the board efficiently.
Try something simpler, which can be solved efficiently at a lower depth. Tic-Tac-Toe is a very good game for a first attempt at Min-Max. This is because the final outcome is well known. If you get your algorithm correctly you should not be able to beat it at all. If you do Tic-Tac-Toe and the algorithm is loosing, you know that you have a mistake.
Also note that in some cases Min-Max plays optimal, but still will look retarded to a human opponent. For example if there is no chance at winning, Min-Max will start to play randomly and do very dumb moves. This is the case , because Min-Max expects the opponent to also play perfect, which is usually not the case with humans. There are some simple changes that can be done to the algorithm to change this behavior and have min-max play "less retarded" in such cases.