I am loading Tiled map via TmxMapLoader and I have no trouble getting tiles, etc. But when I want to extract values from Object Layer, I am only able to get x, y with this code:
MapProperties props = layer.getObjects().get(i).getProperties();
float x = (float) props.get("x");
float y = (float) props.get("y");
Which gets me the right values, but when I try to add this:
float width = (float) props.get("width");
float height = (float) props.get("height");
It throws me this error:
Exception in thread "LWJGL Application" java.lang.NullPointerException
at cz.vilix.managers.MapManager.<init>(MapManager.java:67)
at cz.vilix.main.Game.create(Game.java:50)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:136)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:114)
(Line 67 in MapManager is where I try to get the width value.) It seems a bit ood to me, because I though, that I can get anything from the properties of an object, which is listed in the properties window:
Also using "Width" & "Height" instead of "width" & "height" doesn't work.
Changing the type to Object like this:
Object width = props.get("Width");
Object height = props.get("Height");
System.out.println(width + " " + height);
Prints: null null.
The solution that works is to get RectangleMapObject (or any other shape), and the get the basic Rectangle with this code: Rectangle r = rect.getRectangle() and the you can use parameters of the Rectangle.
Or you can skip the step of creating a new Rectangle object and use it as in this code:
RectangleMapObject rect = (RectangleMapObject) layer.getObjects().get(i);
float x = (float) rect.getRectangle().x;
float y = (float) rect.getRectangle().y;
float width = rect.getRectangle().width;
float height = rect.getRectangle().height;
Related
Matter-js - How to get width and height of rectangle ?
I need to know is there distance return method implemented in Matter-js .
// part.vertices[0] and part.vertices[1]
I wanna integrate tiles option.
This is how looks critical part (i use override function for Render.bodies it is most interest for me) .:
for (let x = 0; x < this.tiles; x++) {
c.drawImage(
texture,
texture.width * -part.render.sprite.xOffset * part.render.sprite.xScale,
texture.height * -part.render.sprite.yOffset * part.render.sprite.yScale,
texture.width * part.render.sprite.xScale,
texture.height * part.render.sprite.yScale);
}
const { min, max } = part.bounds
it will contain what you need in { x, y }
just substract max.x - min.x & max.y - min.y
I went with a solution very similar to the following:
var width = 30;
var height = 30;
var rect = Bodies.rectangle(150, 100, width, height, {density:0.01, className:"brick", width:width, height:height});
console.log(rect.className, rect.width); // "brick", 30
I decided to carry the original width/height information along with other custom properties such as className
The reason why is because bounds is affected by the rotation of any non perfectly-circular object eg. a rotated rectangle's bounds could be up to ~30% wider than it's actual width.
There are two solutions that I've found.
1- Create a class to wrap the matter.js body, which will also hold onto the height and width. ie:
class rectWrapper {
constructor(x, y, width, height, options){
this.width = width
this.height = height
this.body = Matter.Bodies.rectangle(x, y, width, height, options)
}
}
2- Another way is to use the magic of math to determine the distance between two coordinate points, using Body.vertices[0] and Body.vertices[1] for the width, and Body.vertices[0] and Body.vertices[3] for height. This would also account for any rotation. This link explains it clearly, for 2 and 3 dimensions:
https://sciencing.com/calculate-distance-between-two-coordinates-6390158.html
I would recommend writing your own "utility function" to do this. A heavy handed example might look like this:
function distance(x1, y1, x2, y2){
var x = Math.abs(x1-x2)
var y = Math.abs(y1-y2)
return Math.sqrt((x*x)+(y*y))
}
So a call might look like:
var rect = Matter.Bodies.rectangle(0,0,10,50)
var width = distance(rect.vertices[0].x, rect.verticies[0].y, rect.vertices[1].x, rect.vertices[1].y)
var height = distance(rect.vertices[0].x, rect.vertices[0].y, rect.vertices[3].x, rect.vertices[3].y)
Alternatively, if you happen to be using p5.js as your renderer, you can use p5.dist() which takes x1, y1, x2, y2 as arguments and returns the distance (basically the same as the function above):
https://p5js.org/reference/#/p5/dist
Note, this will only work for rectangles. If you're using different kinds of geometry, I would probably just make a wrapper class myself.
I've seen lots of questions on how to zoom the camera so an object fills the screen, but I'm trying to move the object to fill the screen.
I've been trying something like this using the original photos pixel size, and these objects have been scaled:
var dist = object.originalSize.height > $(window).height()
|| object.originalSize.width > $(window).width()
? ( $(window).height() / object.originalSize.height ) * 100
: 10;
var pLocal = new THREE.Vector3( 0, 0, -dist);
var target = pLocal.applyMatrix4( camera.matrixWorld );
var tweenMove = new TWEEN.Tween(object.position).to(target, 1500).easing(TWEEN.Easing.Cubic.InOut);
To come up with a vector to move the object to, however, I can't get the object to fill the screen. Any idea of the maths I need to calculate how far an object needs to be to fill the screen?
The object is a Object3D with different children depending on it's type.
I know the original photographs dimensions (object.originalSize.height) and I know the geometry that has been scaled up to fit with power of 2.
Any clue gratefully received on how to calculate the distance required from the camera to ensure the object fits inside the bounds of the screen.
I also know the bounding box of the item, i.e. from 1024 to 128.
This works, not sure why..
var vFOV = camera.fov * Math.PI / 180;
var ratio = 2 * Math.tan( vFOV / 2 );
var screen = ratio * (window.innerWidth / window.innerHeight) ;
var size = getCompoundBoundingBox( object ).max.y;
var dist = (size/screen) / 4;
I want to display 3 lines of NSAttributedString. Is there a way to figure out the needed height, based on width and number of lines?
And I don't want to create a UILabel to do the size calculation, since I want the calculation to be done in background thread.
I wonder why this is still unanswered. Anyhow, here's the fastest method that works for me.
Make an NSAttributedString Category called "Height". This should generate two files titled "NSAttributedString+Height.{h,m}"
In the .h file:
#interface NSAttributedString (Height)
-(CGFloat)heightForWidth:(CGFloat)width;
#end
In the .m file:
-(CGFloat)heightForWidth:(CGFloat)width
{
return ceilf(CGRectGetHeight([self boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading
context:nil])) + 1;
}
Here's what's happening:
boundRectWithSize:options:context get's a rect constrained to a width you pass to the method. The NSStringDrawingUsesLineFragmentOrigin option tells it to expect multiline string.
Then we fetch the height parameter from that rect.
In iOS 7, this method returns decimals. We need a round figure. ceilf helps with that.
We add an extra unit to the returning value.
Here's how to use it
NSAttributedString *string = ...
CGFloat height = [string heightForWidth:320.0f];
You can use that height for your layout computations.
The answer by #dezinezync answers half of the question. You'll just have to calculate the maximum size allowed for your UILabel with the given width and number of lines.
First, get the height allowed based on number of lines:
let maxHeight = font.lineHeight * numberOfLines
Then calculate the bounding rect of the text you set based on the criteria:
let labelStringSize = yourText.boundingRectWithSize(CGSizeMake(CGRectGetWidth(self.frame), maxHeight),
options: NSStringDrawingOptions.UsesLineFragmentOrigin,
attributes: [NSFontAttributeName: font],
context: nil).size
There is a method in TTTAttributedLabel called
+ (CGSize)sizeThatFitsAttributedString:withConstraints:limitedToNumberOfLines:
Basically,this method use some Core Text API to calculate the height, the key function is
CGSize CTFramesetterSuggestFrameSizeWithConstraints(
CTFramesetterRef framesetter,
CFRange stringRange,
CFDictionaryRef __nullable frameAttributes,
CGSize constraints,
CFRange * __nullable fitRange )
which I think ,is also used by
- (CGRect)textRectForBounds:limitedToNumberOfLines:
this is a workaround and I think there are better way...
static UILabel *label;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
label = [UILabel new];
});
label.attributedText = givenAttributedString;
CGRect rect = CGRectMake(0,0,givenWidth,CGFLOAT_MAX)
CGFloat height = [label textRectForBounds:rect
limitedToNumberOfLines:2].size.height;
How do you determine the line height (in pixels) of the text in a Spark Label?
keyle's answer will only give you the height of the text, not the actual 'lineHeight' style. You can easily get that style like this:
myLabel.getStyle("lineHeight");
The problem is that this can return a relative value (a percentage) or an absolute value (in pixels). The default - if no lineHeight was explicitely set - is "120%".
So here's how we can get the value in pixels in both cases:
var lineHeightStyle:* = myLabel.getStyle("lineHeight");
//its already a value in pixels
if (lineHeightStyle is Number) var lineHeight:Number = lineHeightStyle;
//it's a relative value: let's calculate
else {
var lineMetrics:TextLineMetrics = myLabel.measureText(myLabel.text);
//get the numeric value from the string and divide it by 100
var ratio:Number = int(lineHeightStyle.match(/\d+/)[0]) / 100;
lineHeight = lineMetrics.height * ratio;
}
Have you tried the following?
var lineMetrics:TextLineMetrics = label.measureText(label.text);
var result:Number = lineMetrics.height;
I have created a Sprite in Actionscript and rendered it to a Flex Canvas. Suppose:
var fooShape:Sprite = new FooSpriteSubclass();
fooCanvas.rawChildren.addChild(myshape);
//Sprite shape renders on screen
fooShape.rotation = fooNumber;
This will rotate my shape, but seems to rotate it around the upper-left
point of its parent container(the canvas).
How can I force the Sprite to rotate about is own center point? I could obviously
write code to calculate the rotation, and then have it re-render, but I think there
must be a built-in way to do this, and certainly do not want to 'reinvent the wheel'
if possible.
I am using FlexBuilder, and therefore do not have access to the full Flash API.
Thank you much!
The following steps are required to rotate objects based on a reference point (using Matrix object and getBounds):
Matrix translation (moving to the reference point)
Matrix rotation
Matrix translation (back to original position)
For example to rotate an object 90 degrees around its center:
// Get the matrix of the object
var matrix:Matrix = myObject.transform.matrix;
// Get the rect of the object (to know the dimension)
var rect:Rectangle = myObject.getBounds(parentOfMyObject);
// Translating the desired reference point (in this case, center)
matrix.translate(- (rect.left + (rect.width/2)), - (rect.top + (rect.height/2)));
// Rotation (note: the parameter is in radian)
matrix.rotate((90/180)*Math.PI);
// Translating the object back to the original position.
matrix.translate(rect.left + (rect.width/2), rect.top + (rect.height/2));
Key methods used:
Matrix.rotate
Matrix.translate
DisplayObject.getBounds
Didn't have much luck with the other examples. This one worked for me. I used it on a UIComponent.
http://www.selikoff.net/2010/03/17/solution-to-flex-image-rotation-and-flipping-around-center/
private static function rotateImage(image:Image, degrees:Number):void {
// Calculate rotation and offsets
var radians:Number = degrees * (Math.PI / 180.0);
var offsetWidth:Number = image.contentWidth/2.0;
var offsetHeight:Number = image.contentHeight/2.0;
// Perform rotation
var matrix:Matrix = new Matrix();
matrix.translate(-offsetWidth, -offsetHeight);
matrix.rotate(radians);
matrix.translate(+offsetWidth, +offsetHeight);
matrix.concat(image.transform.matrix);
image.transform.matrix = matrix;
}
Actually I had to add this code to make above solutions work for me.
private var _rotateCount = 0;
var _origginalMatrix:Matrix=new Matrix();
.........
if (_rotateCount++ >= 360 / angleDegrees)
{
myObject.transform.matrix = _origginalMatrix;
_rotateCount = 0;
return;
}
var matrix:Matrix = myObject.transform.matrix;
....
Without that after some long time rotated object slowly moves somewhere right top.
An alternative solution is to put your object inside another View, move it so that your image's center is at the container's top-left corner, and then rotate the container.
import spark.components.*;
var myContainer:View = new View();
var myImage:Image = new Image();
myContainer.addElement(myImage);
myImage.x = myImage.width / -2;
myImage.y = myImage.height / -2;
addElement(myContainer);
myContainer.rotation = whateverAngle;
One issue might be that the width of the image isn't know at the moment it is created, so you might want to find a way around that. (Hardcode it, or see if myImage.preliminaryWidth works)
/**
* Rotates the object based on its center
* Parameters: #obj => the object to rotate
* # rotation => angle to rotate
* */
public function RotateAroundCenter(obj:Object, rotation:Number):void
{
var bound:Rectangle = new Rectangle();
// get the bounded rectangle of objects
bound = obj.getRect(this);
// calculate mid poits
var midx1:Number = bound.x + bound.width/2;
var midy1:Number = bound.y + bound.height/2;
// assign the rotation
obj.rotation = rotation;
// assign the previous mid point as (x,y)
obj.x = midx1;
obj.y = midy1;
// get the new bounded rectangle of objects
bound = obj.getRect(this);
// calculate new mid points
var midx2:Number = bound.x + bound.width/2;
var midy2:Number = bound.y + bound.height/2;
// calculate differnece between the current mid and (x,y) and subtract
//it to position the object in the previous bound.
var diff:Number = midx2 - obj.x;
obj.x -= diff;
diff = midy2 - obj.y;
obj.y -= diff;
}
//////////////////
Usage:
you can use the above function as described below,
var img:Canvas = new Canvas()
RotateAroundCenter(img, rotation);
This will help you
REf: http://subashflash.blogspot.in/2010/08/rotation-of-object-based-on-center.html
If you want to rotate around the center, merely center the asset inside your sprite by setting the internal assets x and y to half of the width and height of the asset. This swill center your content and allow it to rotate around a center point.
An example of runtime loaded assets is as follows:
var loader:Loader = new Loader():
var request:URLRequest = new URLRequest(path/to/asset.ext);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, _onLoaderComplete);
loader.load(request);
private function _onLoaderComplete(e:Event):void
{
var mc:MovieClip = e.target.content as MovieClip;
mc.x = -mc.width * 0.5;
mc.y = -mc.height * 0.5;
mc.rotation = 90;
addChild(mc);
}