How can I control an actor clockwise and anti-clockwise while in orbit using a keyboard?
![EddietheFistMonkey](http://forums.gamesalad.com/applications/dashboard/design/images/defaulticon.png)
Good early evening everyone (UK time),
I've come across a problem while creating my first game and after a thorough search and much experimentation I can't seem to find a solution.
I'll start by explaining in more detail what I want to achieve.
I have an Actor (Planet) in the centre orbited by 2 other actors at varying distances and at varying speeds. I have now begun creating a Player actor which I have set at the furthest distance of the three orbiting Actors from the central Actor (planet).
I have managed to allow the 'Player' to control this actor to move Clockwise or Anti-Clockwise by pressing either the Up or Down key. Now the problem is as some may have guessed by now that in switching direction the Player Actor will jump from one side of orbit to another before fulfilling it's direction change. For example it will be moving clockwise passing the theoretical hands of a clock 12, 1, 2, 3 ,4, 5, 6 upon changing direction it will jump back to 12 then 11,10,9,8.
I'm trying to work out how to make it so that the object will simply change direction with no transportation as it were. Now after searching the forums it seems that the problem is with both movements relying on the same Game.time within the game. I've tried piecing various bits of info together from a variety of forum posts and have attempted a solutions by creating a new attribute to replace Game.time and to then stagger them differently using timers or integers but by not really understanding this I feel I've gone wrong somewhere in implementing these approaches.
So now I turn to the community for help any of which would be greatly appreciated. I've included the formula I've used thus far below. Thank you I hope to hear from you guys on your thoughts.
ANTI-CLOCKWISE Movement
RULE: Actor receives event, key UP when Down.
(within RULE)
MOVE:
Direction formula is, 100*cos( self.Time *60%360)+128 Relative to Actor, Move type Additive.
Speed is 300
CONSTRAIN ATTRIBUTE: for Self position Y and X
Constrain to 140*sin( game.Time *60%360)+160 for Y
and 140*cos( game.Time *60%360)+236 for X
CLOCKWISE Movement
RULE: Same as Anti-Clockwise
(Within RULE)
MOVE: Same as Anti-Clockwise except replace sin with cos.
CONSTRAIN ATTRIBUTE: for self position Y and X
Constrain to 140*sin( game.Time *-60%360)+160 for Y
and 140*cos( game.Time *-60%360)+236 for X
Separate from Rules,
CONSTRAIN ATTRIBUTE (So player actor faces central Actor)
Constrain Attribute: Self.Rotation TO: vectorToAngle( game.Sun x - self.Position.X , game.sun y - self.Position.Y )
I've come across a problem while creating my first game and after a thorough search and much experimentation I can't seem to find a solution.
I'll start by explaining in more detail what I want to achieve.
I have an Actor (Planet) in the centre orbited by 2 other actors at varying distances and at varying speeds. I have now begun creating a Player actor which I have set at the furthest distance of the three orbiting Actors from the central Actor (planet).
I have managed to allow the 'Player' to control this actor to move Clockwise or Anti-Clockwise by pressing either the Up or Down key. Now the problem is as some may have guessed by now that in switching direction the Player Actor will jump from one side of orbit to another before fulfilling it's direction change. For example it will be moving clockwise passing the theoretical hands of a clock 12, 1, 2, 3 ,4, 5, 6 upon changing direction it will jump back to 12 then 11,10,9,8.
I'm trying to work out how to make it so that the object will simply change direction with no transportation as it were. Now after searching the forums it seems that the problem is with both movements relying on the same Game.time within the game. I've tried piecing various bits of info together from a variety of forum posts and have attempted a solutions by creating a new attribute to replace Game.time and to then stagger them differently using timers or integers but by not really understanding this I feel I've gone wrong somewhere in implementing these approaches.
So now I turn to the community for help any of which would be greatly appreciated. I've included the formula I've used thus far below. Thank you I hope to hear from you guys on your thoughts.
ANTI-CLOCKWISE Movement
RULE: Actor receives event, key UP when Down.
(within RULE)
MOVE:
Direction formula is, 100*cos( self.Time *60%360)+128 Relative to Actor, Move type Additive.
Speed is 300
CONSTRAIN ATTRIBUTE: for Self position Y and X
Constrain to 140*sin( game.Time *60%360)+160 for Y
and 140*cos( game.Time *60%360)+236 for X
CLOCKWISE Movement
RULE: Same as Anti-Clockwise
(Within RULE)
MOVE: Same as Anti-Clockwise except replace sin with cos.
CONSTRAIN ATTRIBUTE: for self position Y and X
Constrain to 140*sin( game.Time *-60%360)+160 for Y
and 140*cos( game.Time *-60%360)+236 for X
Separate from Rules,
CONSTRAIN ATTRIBUTE (So player actor faces central Actor)
Constrain Attribute: Self.Rotation TO: vectorToAngle( game.Sun x - self.Position.X , game.sun y - self.Position.Y )
Best Answers
-
MobileRocketGames Posts: 128
Joints would come in super handy right now.
If you could attach a joint to an arbitrary point and have an actor revolve around this joint you could just have the up and down arrow keys control the actors rotation with a simple rotate behavior. I will give this some thought. Maybe one of the more experienced forum members will come up with a quick solution.
Oh, I was just reminded of the old animators acronym K.I.S.S. Keep it simple, stupid!
What if you just cheated the math/position?
Does that actor have to be there for any collision purposes? Even if so, we can get around those as well.
Imagine this.
You have a large 512x512 image in the center of your screen.
This image is transparent except for lets say 64x64 pixels in the top right corner.
Those 64x64 pixels contain your earth or whatever planet actor that you want the player to control.
Pressing up on the keyboard accelerates the rotation CW and down accelerates the rotation CCW. You've now effectively fixed your problem and reduced the CPU load of the program by 1/3rd. Do the same for all 3 planets and your game will run at full speed all the time.
Now you might say, what about collisions? It cant calculate the collision if there's nothing there.
Well there doesn't have to be. You could create two game attribute that stores the theoretical location of the planet, (the center of those 64x64 pixels). You could update these points based on the rotation of the image and then calculate where that point would be at any given angle. If you had something you want to collide with the planet you could say, If self.Position.X is = game.PlanetX and self.position.Y is = game.PlanetY then spawn Explosion or etc.
Or even better yet!!! Constrain an actors X and Y positions to the theoretical position of the planet (which is being controlled by the rotation angle) and have that be the collision. If you did that, you wouldnt need to use a 512x512 image and cheat the location, you could use a transparent 20x20 actor in the center and use your original planet image on an actor constrained to that theoretical point.
I think the problem here is you are trying to move this planet actor based on the keys pressed, where as it should be constrained to a point and that point should be controlled by a simple rotation CW or CCW.
Food for thought.
Good luck! -
RThurman Posts: 2,881
game.Time is being used as a quick-n-dirty counter here. You can make your own counting attribute and replace game.Time with it. For example you could use an attribute called "counter" to do something like:
When key "downArrow" is down
-- change attribute: self.counter To: self.counter+1
When key "upArrow" is down
-- change attribute self.counter To: self.counter-1
Using your formula, the constrain would then be:
Constrain attribute: self.Position.Y To: 140*sin(self.counter*60%360)+160
Constrain attribute: self.Position.X To: 140*cos(self.counter*60%360)+236 -
ORBZ Posts: 1,304
You can simplify this whole problem if you think about it like a wheel and axle.
You will need four global variables:
Axis-Rotation: angle
Axis-x: real
Axis-y: real
Distance: real (set to however far away the player should be from the axis, ex: 300)
Have an invisible "axis" actor in the middle and constrain the global vars to its rotation, x, and y positions.
Like so:
Constrain global var = axis local var
You want the globals to be copies of the locals.
Now then, this "axle" will have the behavior logic in it that says when up is pressed rotate clockwise and when down is pressed rotate counter-clockwise. (tip: you can even relocate it's x and y and this will still work)
Finally, specify the player object to constrain it's x and y position using sin and cos functions, like so:
Player.x = game.Axis-x + cos(game.Axis-rotation) * game.distance
Player.y= game.Axis-y + sin(game.Axis-rotation) * game.distance
Tada!
Super simple, like maybe 10 lines of code.
-
MobileRocketGames Posts: 128
whoa! somewhere you've gotten off the track.
For example are Global Variables the Attributes that we create real, boolean etc and therefore would a local variable in this case be the self.postion.X or .Y?
Global attributes are the ones you create by selecting the attributes tab in the top level of the editor, from the Inspector pain in the top left (there are 3 tabs, Actor, Attributes and Devices). In other words, Game Attributes. these will be indicated by lowercase "game" before their name in the expression editor (e.g. "game.Time").
Local attributes would be the ones you create by double clicking an actor and opening up the prototype. These are indicated by a self preposition (e.g. "self.Position.X")
The only difference between these two is that you can link to and control game attributes from actor prototypes (global) where as scene and self attributes can only be controlled by actors already placed in the scene.
It's best if you just create a backup of your game, then delete your current movement control system and start over using the instructions here.
Basically just:
-Add those 4 game attributes
-Create "invisible actor" and place it directly in the center of the screen.
-Add to the invisible actor 3 constrain attribute behaviors to control those global variables like ORBZ mentioned.
-Create two rules, the first being "when up key is down" and the next being "when down key is down" and having each change the rotation CW or CWW.
Then on your player actor add two constrain attributes:
self.Position.X = game.Axis-x + cos(game.Axis-rotation) * game.distance
self.Position.Y = game.Axis-y + sin(game.Axis-rotation) * game.distance
-
MobileRocketGames Posts: 128
I took the liberty of creating this system for you. if you want to PM me your email I'll send you over the build so you can see how it works. -
MobileRocketGames Posts: 128
Oh crap, i realized I just saved over my previous comment instead of adding a new one.
it was a big one too =(
I will rewrite the important parts:
"For example are Global Variables the Attributes that we create real, boolean etc and therefore would a local variable in this case be the self.postion.X or .Y?
You seem to have gotten off track somewhere. Let's clarify those two.
A global attribute (in this case, known as a game attribute) is an attribute created by selecting the attributes tab in the inspector pane on the left hand side of the top level of the editor (the one that contains all your actors, it has 3 tabs, Actor, Attribute, Devices).
A local attribute is a self or scene attribute. These attributes can only be accessed locally (that is, by an actor already placed in the scene). For example, from a prototype you cannot say, if this actor is touched, move some other specific actor 200px to the right. But you can if you place that actor in the scene and unlock it, then you can actually select from a drop down list any other actor in the scene and directly modify or control any of their variables.
A global attribute will have the preposition "game" in the expression editor (e.g. "game.Time").
A local attribute will have the preposition "self" or "scene" in the expression editor (e.g. "self.Position.X").
The benefit of a game attribute is it can be accessed anywhere, by any actor. Where as local attributes are limited as to who or when they can be accessed.
"
I took the liberty of creating this system for you. If you want to PM me your email I'll send you over the build so you can see how it works. Super thanks to @ORBZ for the sin/cos formula.
Answers
I am however having real problems. Regarding Rthurmans solution I can only seem to create an attribute for Game.Counter and not Self.Counter showing how new i am to this.
Regarding your solution Orbz I'm having trouble following it in practice, though you clearly know what you're talking about.
For example are Global Variables the Attributes that we create real, boolean etc and therefore would a local variable in this case be the self.postion.X or .Y? This is the assumption I have made in trying out your method.
I have had my central actor (our axis) around which the others are rotating constrained using 'Real' Attributes (Axis X and Y) and constraining them to its Self. X and Y positions. I have also set two rules and a behaviour for each for rotating when keys are pressed up and down.
Now as for the acting player actor, how would this apply to the original formula I was using? I've thus far used;
A Rule for each Key command up and down, with a Move behaviour as before and then two constrain attributes again for each rule like before,
Example:
game.Axis y +sin( game.Axle Rotation *60%360) game.Distance, and a corresponding formula for X axis. (would the game.distance be set at the attributes list where it begins as 0?)
I also have a constrain attribute to 'vector angle' as before which seems to help the player return to the screen when down is pressed.
At the moment the player when 'up' is pressed disappears and returns to orbit the centre at o distance and then veers off, 'down' results just in the player going off screen.
I realise this must seem like gibberish but I'm rather confused and trying to get across as much information as possible.
Thank you very much for your help, any further explanation that could help drag me kicking and screaming to success would be fantastic. Thanks a lot guys.
well, anyway I'm glad you're on your way to making your first game.
The cookbook here on the gamesalad website actually has some helpful tutorials for learning the lingo and behaviors. Definitely worth checking out.
Also check out @Tshirtbooth videos on his website www.GShelper.com for some great tutorials for things you will most likely want in your game (e.g. score counter, tables, store, etc).
Good Luck!
Cheers