How to switch between multiple players with the same class and same ActionMap
by Kal El · in Torque Game Builder · 09/18/2010 (6:01 pm) · 8 replies
Hi!
I'm trying to develop a hockey game that has 2 teams, player1 and player2. Each team has 3 players and the keyboard input control (ActionMap) is assigned to the player that is controlling the puck (ball). However whenever I start the game just the first player of each team is capable of moving even when another player is in contact whith the puck.
My code is something like this:
player.cs
function PlayerHockey::onLevelLoaded(%this, %scenegraph)
{
$HockeyPlayer = %this;
%this.testActionMap=new ActionMap();
}
function PlayerHockey::pushAction(%this)
{
%this.testActionMap.bindCmd(keyboard, "w", "hockeyPlayerUp();", "hockeyPlayerUpStop();");
%this.testActionMap.bindCmd(keyboard, "s", "hockeyPlayerDown();", "hockeyPlayerDownStop();");
%this.testActionMap.bindCmd(keyboard, "a", "hockeyPlayerLeft();", "hockeyPlayerLeftStop();");
%this.testActionMap.bindCmd(keyboard, "d", "hockeyPlayerRight();", "hockeyPlayerRightStop();");
%this.testActionMap.push();
}
function PlayerHockey::popAction(%this)
{
%this.testActionMap.pop();
%this.testActionMap.unbind(keyboard, "w");
%this.testActionMap.unbind(keyboard, "s");
%this.testActionMap.unbind(keyboard, "a");
%this.testActionMap.unbind(keyboard, "d");
}
function PlayerHockey::updateMovement(%this)
{
// Movement functions...
}
puck.cs
function puckShot()
{
if($puck.getIsMounted()){ // if someone has the puck
%player = $puck.getMountedParent(); //gets the player that has the puck
%player.popAction(); //disables the movement of the player that had the puck
$puck.dismount(); //unmounts the puck from the player
$puck.setLinearVelocityY(100);
}
}
function HockeyPuck::onCollision(%srcObj, %dstObj, %srcRef, %dstRef, %time, %normal, %contactCount, %contacts)
{
if(!$ppuck.getIsMounted()){ //if no one has the puck
$puck.mountToLinkpoint(%dstObj,1,10,false,false,false,false); //mounts the puck to the player
%dstObj.pushAction(); //enables ActionMap in the player that has the puck
}
}
all the players from team 1 belong to the class PlayerHockey, but I can only control one player.
What I want to do is to control the player that has the puck, like in FIFA games that the player that moves is the one that has the soccer ball.
I'm trying to develop a hockey game that has 2 teams, player1 and player2. Each team has 3 players and the keyboard input control (ActionMap) is assigned to the player that is controlling the puck (ball). However whenever I start the game just the first player of each team is capable of moving even when another player is in contact whith the puck.
My code is something like this:
player.cs
function PlayerHockey::onLevelLoaded(%this, %scenegraph)
{
$HockeyPlayer = %this;
%this.testActionMap=new ActionMap();
}
function PlayerHockey::pushAction(%this)
{
%this.testActionMap.bindCmd(keyboard, "w", "hockeyPlayerUp();", "hockeyPlayerUpStop();");
%this.testActionMap.bindCmd(keyboard, "s", "hockeyPlayerDown();", "hockeyPlayerDownStop();");
%this.testActionMap.bindCmd(keyboard, "a", "hockeyPlayerLeft();", "hockeyPlayerLeftStop();");
%this.testActionMap.bindCmd(keyboard, "d", "hockeyPlayerRight();", "hockeyPlayerRightStop();");
%this.testActionMap.push();
}
function PlayerHockey::popAction(%this)
{
%this.testActionMap.pop();
%this.testActionMap.unbind(keyboard, "w");
%this.testActionMap.unbind(keyboard, "s");
%this.testActionMap.unbind(keyboard, "a");
%this.testActionMap.unbind(keyboard, "d");
}
function PlayerHockey::updateMovement(%this)
{
// Movement functions...
}
puck.cs
function puckShot()
{
if($puck.getIsMounted()){ // if someone has the puck
%player = $puck.getMountedParent(); //gets the player that has the puck
%player.popAction(); //disables the movement of the player that had the puck
$puck.dismount(); //unmounts the puck from the player
$puck.setLinearVelocityY(100);
}
}
function HockeyPuck::onCollision(%srcObj, %dstObj, %srcRef, %dstRef, %time, %normal, %contactCount, %contacts)
{
if(!$ppuck.getIsMounted()){ //if no one has the puck
$puck.mountToLinkpoint(%dstObj,1,10,false,false,false,false); //mounts the puck to the player
%dstObj.pushAction(); //enables ActionMap in the player that has the puck
}
}
all the players from team 1 belong to the class PlayerHockey, but I can only control one player.
What I want to do is to control the player that has the puck, like in FIFA games that the player that moves is the one that has the soccer ball.
#2
When ever a player is controlling the puck or is the nearest one to it, I should modify a variable that indicates that this particular player is the one that can move. now, does this variable has to be local, global or like %this.PlayerWithPuck = true?
function hockeyPlayerUp()
{
if( isObject( $PlayerWithPuck ) )
$PlayerWithPuck.MoveUp();
}
$PlayerWithPuck is a variable?, if it is an object, how do I create this object?
Thank you very much!
09/19/2010 (1:13 am)
Thanks for your answer, I´m not really used to TGB objects but let my see if I understood.When ever a player is controlling the puck or is the nearest one to it, I should modify a variable that indicates that this particular player is the one that can move. now, does this variable has to be local, global or like %this.PlayerWithPuck = true?
function hockeyPlayerUp()
{
if( isObject( $PlayerWithPuck ) )
$PlayerWithPuck.MoveUp();
}
$PlayerWithPuck is a variable?, if it is an object, how do I create this object?
Thank you very much!
#3
This will automatically call MoveUp() on the object that the puck is mounted to, if it is mounted to a player. This saves you the trouble of maintaining another global variable.
//BTW: rather than using a global $puck variable, you could just name your puck object "Puck". You then get
09/19/2010 (1:34 am)
It has to be global and hold a reference to the object. Since you already have a $puck variable, though, as I see now and you're using mounting, you could just do:function hockeyPlayerUp()
{
if( $puck.getIsMounted() )
$puck.getMountedParent().MoveUp();
}This will automatically call MoveUp() on the object that the puck is mounted to, if it is mounted to a player. This saves you the trouble of maintaining another global variable.
//BTW: rather than using a global $puck variable, you could just name your puck object "Puck". You then get
function hockeyPlayerUp()
{
if( Puck.getIsMounted() )
Puck.getMountedParent().MoveUp();
}
#4
09/20/2010 (5:14 am)
.
#5
09/20/2010 (6:17 pm)
see next post
#6
I will start trying this method right now.
I have a doubt with the code of switchPlayer and switchControlledPlayer, this code should be inside the PlayerHockey Class? or I should create another class that would be the "manager" of the moveMap deciding which of the players will be in control by the keys in any moment? This new class and not the PlayerHockey class, will be the one that is binded to the keyboard, and the movement will be assigned to the player that is having the puck or the nearest one to it.
By the way, I've been trying the methods previoslly suggested but there is still a problem trying to unbind the comands from an object. When the game is starting, the objects (players) are added in secuential mode, one by one, and the first one that is added to the level keeps the moveMap, even if I unbind the moveMap form this player and bind it to another. I think this is beacause all the players of team 1 belongs to the same class, and the global variable of this class is afected at the same time by the other objects and this causes problems. Trying some tutorial I found that in the Miniplatformer tutorial there is a note in the Keyboard Input section:
I will post my results as soon as I can.
Thanks, Kal
09/20/2010 (6:25 pm)
Thank you very much for your response.I will start trying this method right now.
I have a doubt with the code of switchPlayer and switchControlledPlayer, this code should be inside the PlayerHockey Class? or I should create another class that would be the "manager" of the moveMap deciding which of the players will be in control by the keys in any moment? This new class and not the PlayerHockey class, will be the one that is binded to the keyboard, and the movement will be assigned to the player that is having the puck or the nearest one to it.
By the way, I've been trying the methods previoslly suggested but there is still a problem trying to unbind the comands from an object. When the game is starting, the objects (players) are added in secuential mode, one by one, and the first one that is added to the level keeps the moveMap, even if I unbind the moveMap form this player and bind it to another. I think this is beacause all the players of team 1 belongs to the same class, and the global variable of this class is afected at the same time by the other objects and this causes problems. Trying some tutorial I found that in the Miniplatformer tutorial there is a note in the Keyboard Input section:
Quote:
Note: We are using a global variable, $pGuy, to communicate to our playerClass object from the functions bound to the keyboard (playerLeft(), playerLeftStop(), etc.). This means that there can be only one playerClass object in existence. If we wanted to have a game that could include more than one such object, we would have to do this part differently.
I will post my results as soon as I can.
Thanks, Kal
#7
in the original player script: player.cs
the puck.cs code remains the same, I will add the functions that check when ever the puck is unmounted which is the nearest player to it.
I will continue working around the other solutions and post the results
Thanks, Kal
09/20/2010 (7:55 pm)
For the moment I've found a solution. I avoids all the bind-unbind code. It´s not the solution I think I will leave in the game but for the moment has given results.in the original player script: player.cs
function PlayerHockey::onLevelLoaded(%this, %scenegraph)
{
//$HockeyPlayer = %this; I removed this assignment because
// every object loaded having this class will store the global
// variable and causes the problem
moveMap.bindCmd(keyboard, "w", "hockeyPlayerUp();", "hockeyPlayerUpStop();");
moveMap.bindCmd(keyboard, "s", "hockeyPlayerDown();", "hockeyPlayerDownStop();");
moveMap.bindCmd(keyboard, "a", "hockeyPlayerLeft();", "hockeyPlayerLeftStop();");
moveMap.bindCmd(keyboard, "d", "hockeyPlayerRight();", "hockeyPlayerRightStop();");
}
function PlayerHockey::pushAction(%this)
{
//DEACTIVATE AI
$HockeyPlayer = %this; //I assign the object with the puck or
//the nearest one to it so all the movement
//functions will affect only this object
}
function PlayerHockey::popAction(%this)
{
//ACTIVATE AI
}
function PlayerHockey::updateMovement(%this)
{
// Movement functions...
}the puck.cs code remains the same, I will add the functions that check when ever the puck is unmounted which is the nearest player to it.
I will continue working around the other solutions and post the results
Thanks, Kal
#8
09/21/2010 (4:50 am)
.
Associate Rene Damm
Rather than solving this through separate ActionMaps, it's far easier to solve this through the commands being run by the actions. I.e. just store a reference to the player that currently has the puck and then go through that.
For example with something like:
function hockeyPlayerUp() { if( isObject( $PlayerWithPuck ) ) $PlayerWithPuck.MoveUp(); }Then you can just leave your single action map with the WASD bindings in place all the time while playing and just update the reference as the puck moves to and away from players.