At 9/12/14 03:39 AM, Hero101 wrote:
Depending on the level the character's control attributes will vary. By that I mean the player will use the same keys to move control the player (WASD or Arrows) but some levels the controls will be reversed or his speed will be greatly increased or reduced.
So say you have some class that takes all the user input and transforms it into movement of the player:
// Controller.as
public function Controller (target:Player)
Which could be used like this:
var player:Player = new Player();
addChild(player);
var controller:Controller = new Controller(player);
To do that, your Player class could provide public methods like these:
// Player.as
public function set speedX(value:Number):void
{
// ...
}
public function set speedY(value:Number):void
{
// ...
}
The controller knows the player object and can set the speed of it.
Therefore the controller controls the player.
Now how could you make this connection between controller and player different for each level?
You could extract those methods into an interface as a start.
Again, all the controller does is call those two methods that set the speed, they do not necessarily have to be on a player object.
At the moment, the Controller asks for "some Player" and with the interface this changes to "something that has these two methods, I don't care what it actually is, because all I do all day long is call those methods. Did I mention those two methods?"
// ISpeedSettable.as
public function set speedX(value:Number):void;
public function set speedY(value:Number):void;
Now the Controller should expect that interface instead of Player as the type of its constructor parameter:
// Controller.as
public function Controller (target:ISpeedSettable)
Problem is that this breaks the code. You cannot pass Player to the Controller any more, because Player is not ISpeedSettable.
To fix this, let Player implement that interface:
// Player.as
public class Player implements ISpeedSettable
public function set speedX(value:Number):void
{
// ...
}
public function set speedY(value:Number):void
{
// ...
}
And sure enough it has both methods and the code compiles.
Finally, this code works again:
var player:Player = new Player();
addChild(player);
var controller:Controller = new Controller(player);
And we are right where we started. Ain't that awesome? *yay*
Except that there's this interface thingy now which we can do cool things with.
Instead of passing the Player, we could create something else that implements the interface and pass that thing to the Controller instead.
The Controller can be "fooled" to control something that isn't actually the player.
like this thing for example:
// TheThingThatFoolsTheController.as
public class TheThingThatFoolsTheController implements ISpeedSettable
public function set speedX(value:Number):void
{
// trollolol, the controller is calling this function thinking it controls the player, but it's not
}
public function set speedY(value:Number):void
{
// omg, we can totally take all the information originally sent to the player object and do secret stuff with it, this is feels so James Bond
}
Ok, let's fool the controller and give it that other object instead of Player:
var player:Player = new Player();
addChild(player);
var controller:Controller = new Controller(new TheThingThatFoolsTheController());
That should compile but nothing's happening, because we cut the connection between the Controller and the Player.
TheThingThatFoolsTheController should have a connection to Player, so the Player moves (after all, that's what we want, right?) so let's pass the Player to this class:
// TheThingThatFoolsTheController.as
public class TheThingThatFoolsTheController implements ISpeedSettable
private var _target:Player;
public function TheThingThatFoolsTheController(target:Player)
{
_target = target;
}
public function set speedX(value:Number):void
{
// trollolol, the controller is calling this function thinking it controls the player, but it's not
}
public function set speedY(value:Number):void
{
// omg, we can totally take all the information originally sent to the player object and do secret stuff with it, this is feels so James Bond
}
To complete the connection, each of both method calls is delegated to the player:
// TheThingThatFoolsTheController.as
public class TheThingThatFoolsTheController implements ISpeedSettable
private var _target:Player;
public function TheThingThatFoolsTheController(target:Player)
{
_target = target;
}
public function set speedX(value:Number):void
{
_target.speedX = value;
}
public function set speedY(value:Number):void
{
_target.speedY = value;
}
After all this effort we are where we started - again! (second round walking in this circle, w00t)
And because NG is retarded I have to continue in another post.