I've recently been working a lot with CFrame mechanics while scripting and I've got kind of stuck on this.
Even after using .lookVector, or even Vector3, the Jetpack model position stays equal to the position of the Torso instead of 5 (* -5) behind the torso.
Here is the code I have so far:
local player = script.Parent
local jetpack = game.ReplicatedStorage.Jetpack
local jetpackClone = jetpack:Clone()
jetpackClone.PrimaryPart = jetpackClone.Core
jetpackClone.Parent = player
jetpackClone:moveTo(player.Torso.Position + player.Torso.CFrame.lookVector * -5)
local weld = Instance.new("Motor6D")
weld.Parent = jetpackClone.Core
weld.Part0 = jetpackClone.Core
weld.Part1 = player.Torso
The way to fix this is quite simple.
Like Ahmad said, moveTo is used for models that doesn't have a primary part. But it is not only that.
One thing that Ahmad forgot is that 'lookVector' is not a CFrame, it is a Vector3 instead.
In this fragment, you did
moveTo(player.Torso.Position + player.Torso.CFrame.lookVector * -5)
That would be fine, if you didn't use a numerical value with Vector3's. To fix this, instead, your code should be
local player = script.Parent
local jetpack = game.ReplicatedStorage.Jetpack;
local jetpackClone = jetpack:Clone();
jetpackClone.PrimaryPart = jetpackClone.Core;
jetpackClone.Parent = player; -- Is the 'Player' a Player, or a character??
local weld = Instance.new("Weld", player.Torso) -- We use 'Weld' here, instead of Motor6D
weld.Part1 = jetpackClone.Core;
weld.Part0 = player.Torso;
weld.C0 = CFrame.new(0, 0, -5); -- We use the C0 property of Weld's
That should do it for welding the jetpack to your torso. Though, I would check if the CFrame is correct in it, I am not sure if it is or not, but if the jetpack appears in front of your torso, then replace weld.C0 = CFrame.new(0, 0, -5) to weld.C0 = CFrame.new(0, 0, 5).
Hope my answer helps!
moveTo is used for models that doesn't have a primary part. Which can be inaccurate. Instead use :SetPrimaryPartCFrame() also u were adding Position+CFrame(it would cause an error did u check output?)
Related
heres the code
var _obj;
if (instance_exists(obj_text)) _obj = obj_txt_queued; else _obj = obj_text;
with (instance_create_layer(0, 0, "text_layer", _obj))
{
msg = argument[0];
if (instance_exists(other)) originInstance = other.id else originInstance = noone;
if (argument_count > 1) background = argument[1]; else background = 1;
}
with (obj_phae)
{ if (state != scr_player_state_lock)
{
lastState = state;
state = scr_player_state_lock;
}
}
[layers](https://i.stack.imgur.com/9u9tD.png)
I tried removing any extra rooms that were not needed and I tried changing the layer name to something else.
I also tried using var instance_create_layer() but that obviously didn't work
I'm a bit confused at this part:
with (instance_create_layer(0, 0, "text_layer", _obj))
Especially the with(), as that function will go through every object in the room if it sees an object within the parameter, since you suggested to create a new object with it, I'm surprised it doesn't create an infinite loop. Maybe it works, I've never tried it myself, but I think there's a more logical way to assign variables from one object to a newly created object.
Assuming you want to use the With() statement to address the variables within the _obj, I think you can manage something similair through this function:
var object = instance_create_layer(0, 0, "text_layer", _obj)
object.msg = argument[0];
object.originInstance = id
if (argument_count > 1) object.background = argument[1]; else object.background = 1;
It's probably a given at this point, but double-check that this part of code can only run if it's in the same room that has a layer called "text_layer"
In the worst case, you may also try out instance_create_depth() and use the build-in depth variable from the object instead of the layer names. Using depth is more flexible, but less organised than layers.
I am making a double pendulum simulation in javafx. I want to trace the lower bob's path by a clear line, not a trace of dots(which I have achieved). I am new to javafx. I have not used any transitions to animate it. I have used Timeline and KeyFrame to make it work.
private static void doCalc(){
a1_v+=a1_a;
a2_v+=a2_a;
a1+=a1_v;
a2+=a2_v;
a1_a = calcA1();
a2_a = calcA2();
System.out.println(a1_a+"\n"+a2_a+"\n");
x1 = calcX(x0,a1,r1);
y1 = calcY(y0,a1,r1);
x2 = calcX(x1,a2,r2);
y2 = calcY(y1,a2,r2);
Circle tracer = new Circle(x2,y2,1);
tracer.setFill(Color.BLUE);
root.getChildren().add(0,tracer);
}
This is the method that does the calculation and adds the tracer every time a new frame is created. But I want a single line to represent my node's path, not a trail of dots.
This might be a stupid question and I know my coding practices in javafx are a bit weak. I was just looking for a small solution to implement so that I can quickly add it to my simulator. Thanks in advance :)
Just add a line from the old coordinates to the new ones:
private static void doCalc(){
// I think these must be the old coordinates you need:
double oldX2 = x2 ;
double oldY2 = y2 ;
a1_v+=a1_a;
a2_v+=a2_a;
a1+=a1_v;
a2+=a2_v;
a1_a = calcA1();
a2_a = calcA2();
System.out.println(a1_a+"\n"+a2_a+"\n");
x1 = calcX(x0,a1,r1);
y1 = calcY(y0,a1,r1);
x2 = calcX(x1,a2,r2);
y2 = calcY(y1,a2,r2);
Line traceLine = new Line(oldX2, oldY2, x2, y2);
traceLine.setStroke(Color.BLUE);
root.getChildren().add(0,traceLine);
}
You could also use a Path and update it:
// do this once:
Path trace = new Path();
trace.getElements().add(new MoveTo(initialX2, initialY2));
trace.setStroke(Color.BLUE);
root.getChildren().add(trace);
// ...
private static void doCalc(){
a1_v+=a1_a;
a2_v+=a2_a;
a1+=a1_v;
a2+=a2_v;
a1_a = calcA1();
a2_a = calcA2();
System.out.println(a1_a+"\n"+a2_a+"\n");
x1 = calcX(x0,a1,r1);
y1 = calcY(y0,a1,r1);
x2 = calcX(x1,a2,r2);
y2 = calcY(y1,a2,r2);
trace.getElements().add(new LineTo(x2, y2));
}
Note that either of these approaches (and indeed your original approach with the circles) create indefinitely many UI nodes and add them to the scene. Consequently, if the simulation runs for long enough, you will eventually run out of memory. If the simulation is expected to run for a while, you probably want to limit the number of these you keep in memory (e.g. stop adding new lines after some fixed number, or keep the number at a maximum by removing the earlier ones once you reach a limit, etc).
I'm new to GameMaker, and to making games, for my second game ever I was just going to use GameMakers built in physics. It's a RPG and I'm having lot's of trouble getting the guy to shoot the bullet. I can get the bullet to be placed in the room and at the angle it needs to be at. You could normally then just use the objectnamehere.speed = to what ever you want your speed to be. But! using physics you could use the phy.speed but that's a read only variable. So i half to use the phy_speed_x and phy_speed_y. But how do I get it to shoot in the direction the bullet object is? Here's the code I have so far.
// Player shoot
var shootButton = mouse_check_button_pressed(mb_left);
var bulletSpeed = 10;
if (shootButton) {
bullet = instance_create(ot_player.x, ot_player.y, ot_bullet);
bullet.phy_rotation = phy_rotation;
bullet.phy_speed_x = bulletSpeed;
bullet.phy_speed_y = bulletSpeed;
}
I have tried putting many different variables where I have the bulletSpeed variables but nothing has seem to work. I'm stuck here, I've watch tutorials and read lots of stuff but nothing has worked!
I figured it out.
var shootButton = mouse_check_button_pressed(mb_left);
var bulletSpeed = 10;
if (shootButton) {
bullet = instance_create(ot_player.x, ot_player.y, ot_bullet);
with(bullet) {
phy_rotation = other.phy_rotation;
ldx = lengthdir_x(15, -phy_rotation)
ldy = lengthdir_y(15, -phy_rotation)
physics_apply_impulse(x, y, ldx, ldy);
}
}
Or putting it more accurately, I want to be able to get the distance between the top of a control to the top of one of its children (and adding the height member of all the above children yields specious results!) but the process of getting the absolute coordinates, and comparing them, looks really messed up.
I use this function to calculate the height between the tops of 2 tags:
private static function GetRemainingHeight(oParent:Container, oChild:Container,
yParent:Number, yChild:Number):Number {
const ptParent:Point = oParent.localToGlobal(new Point(0, yParent));
const ptChild:Point = oChild.localToGlobal(new Point(0, yChild));
const nHeightOfEverythingAbove:Number = ptChild.y - ptParent.y;
trace(ptChild.y.toString() + '[' + yChild.toString() + '] - ' +
ptParent.y.toString() + '[' + yParent.toString() + '] = ' + nHeightOfEverythingAbove.toString() + ' > ' + oParent.height.toString());
return nHeightOfEverythingAbove;
}
Note that oParent.y == yParent and oChild.y == yChild but I did it this way for binding reasons.
The result I get is very surprising:
822[329] - 124[0] = 698 > 439
which is impossible, because the top of oChild does not disappear below oParent. The only figure I find unexpected is ptChild.y. All the other numbers look quite sane. So I'm assuming that my mistake was in subtracting two figures that are not supposed to be comparable.
Of course, if anyone has a method of calculating the difference between two points that doesn't involve localToGlobal(), that'd be fine, too.
I'm using the 3.5 SDK.
I found a partial answer by looking to http://rjria.blogspot.ca/2008/05/localtoglobal-vs-contenttoglobal-in.html (including the comments). It dithers on whether or not I should be using localToGlobal() or contentToGlobal(), but it filled in some blanks that Adobe's documentation left, which is that you get the global coordinates by feeding the function new Point(0, 0). In the end, I used this:
public static function GetRemainingHeight(oParent:DisplayObject, oChild:DisplayObject,
yParent:Number, yChild:Number):Number {
const ptParent:Point = oParent.localToGlobal(new Point(0, 0));
const ptChild:Point = oChild.localToGlobal(new Point(0, 0));
const nHeightOfEverythingAbove:Number = ptChild.y - ptParent.y;
return nHeightOfEverythingAbove;
}
See question for an explanation for the seemingly unnecessary parameters, which now seem like they might really be irrelevant.
However, I didn't need this function as often as I thought, and I'm not terribly happy w/the way it works anyway. I've learned that the way I've done it, it isn't possible to just make all those parameters to the function Bindable and expect this function to be called when changes to oChild are made. In one case I had to call this function in the handler for the updateComplete event.
I've ran into a weird problem with getCharBoundaries, I could not figure out what coordinate space the coordinates returned from the function was in. What ever I tried I could not get it to match up with what I expected.
So I made a new project and and added simple code to highlight the last charater in a textfield, and all of a sudden it worked fine. I then tried to copy over the TextField that had been causing me problems, into the new project. And now the same weird offset appeared 50px on the x axis. Everything else was spot on.
So after some headscracthing comparing the two TextFields, I simply can not see a difference in their properties or transformation.
So I was hoping that someone might now what property might affect the coordinates returned by getCharBoundaries.
I am using Flash CS4.
I've just had exactly the same problem and thought I'd help out by offering what my findings are. With a help from this thread, I tried to find everything that wasn't 'default' about the textfield I was using. I found that when I had switched my TextFormatAlign (or 'align' in the IDE) and TextFieldAutoSize properties to 'LEFT' as opposed to 'CENTER', it solved the problem.
A little late in the game perhaps, but worth knowing for anyone running into the same problem. This was the only thread I could find that raised the right flag...
Well the getCharBoundaries returns the boundaries in the textfield coordinate system. Where the origin is topleft corner of the textfield.
getCharBoundaries does not take into consideration the scrolling. you need to check if there are scrollbars on its parent (textarea) and if so relocate. One quick way of doing it is using localtoglobal and globaltolocal. Use the first to translate from the textfield coordinate system to the application coordinate system and then use the second to translate from the app coordinate system to the coordinate system of the parent of the textfield which is the textarea. I'm fine tuning a my method to get char boundaries i will publish it today on my blog
http://flexbuzz.blogspot.com/
Works For Me(tm) (Flex Builder AS3 project):
[Embed(systemFont="Segoe UI", fontWeight="bold", fontName="emb",
mimeType="application/x-font")]
private var EmbeddedFont:Class;
public function ScratchAs3()
{
stage.scaleMode = 'noScale';
stage.align = 'tl';
var m:Matrix = new Matrix(.8, .1, -.1, 1.1, 26, 78);
var t:TextField = new TextField();
t.autoSize = 'left';
t.wordWrap = false;
t.embedFonts = true;
t.defaultTextFormat = new TextFormat("emb", 100, 0, true);
t.transform.matrix = m;
t.text = "TEST STRING.";
addChild(t);
var r:Rectangle = t.getCharBoundaries(8);
var tl:Point = m.transformPoint(r.topLeft);
var tr:Point = m.transformPoint(new Point(r.right, r.top));
var bl:Point = m.transformPoint(new Point(r.left, r.bottom));
var br:Point = m.transformPoint(r.bottomRight);
graphics.beginFill(0xFF, .6);
graphics.moveTo(tl.x, tl.y);
graphics.lineTo(tr.x, tr.y);
graphics.lineTo(br.x, br.y);
graphics.lineTo(bl.x, bl.y);
graphics.lineTo(tl.x, tl.y);
}
To literally answer your question, it returns the coordinates in the TextField's coordinate system, not it's parent, and it is affected by DisplayObject.transform.matrix, which is the backing for the .x, .y, .scaleX, .scaleY, .width, .height, and .rotation properties.
What ever it was the solution was simple to add a new TextField, never found out what property screwed everything up.
The first answer is correct in most cases. However if your field is parented to another movie clip it may still return the wrong y coordinate. try this code:
//if this doesn't work:
myTextFormat = new TextFormat();
myTextFormat.align = TextFormatAlign.LEFT;
myFieldsParent.myField.autoSize = TextFieldAutoSize.LEFT;
myFieldsParent.myField.setTextFormat( myTextFormat);
//try this:
var x = myFieldsParent.myField.getCharBoundaries(o).x;
var y = myFieldsParent.myField.getCharBoundaries(o).y;
var myPoint:Point = new Point(myField.getCharBoundaries(o).x,myField.getCharBoundaries(o).y);
var pt:Point = new Point(myFieldsParent.myField.getCharBoundaries(o).x, myFieldsParent.myField.getCharBoundaries(o).y);
pt = myFieldsParent.myField.localToGlobal(pt);
//pt is the variable containing the coordinates of the char in the stage's coordinate space. You may still need to offset it with a fixed value but it should be constant.
I didn't test this code as I have adapted this example from code that is embedded into my project so I apologize if I'm missing something...