KineticJS: is there any way of getting the height of a Sprite? - height

So KineticJS supports sprites, and I am using sprites in my current project. Is there any way I can get the height of a sprite object?
Because you can get the height of every single object in KineticJS like this:
object.getHeight();
That also applies for getting the width.
Thanks in advance!

getHeight() return 0 for Spline.
You can define your getHeight and getWidth functions:
Kinetic.Spline.prototype.getWidth = function(){
var points = this.getPoints();
var minX = points[0].x;
var maxX = points[0].x;
for(var i = 1; i < points.length;i++){
if(points[i].x < minX){
minX = points[i].x;
}
if(points[i].x > maxX){
maxX = points[i].x;
}
}
return maxX - minX;
}
Kinetic.Spline.prototype.getHeight = function(){
var points = this.getPoints();
var minY = points[0].y;
var maxY = points[0].y;
for(var i = 1; i < points.length;i++){
if(points[i].y < minY){
minY = points[i].y;
}
if(points[i].y > maxY){
maxY = points[i].y;
}
}
return maxY - minY;
}
But this is approximation of real height/width.
Example: http://jsfiddle.net/lavrton/EM35c/

Lavtron's answer refers to Spline, not Sprite (similar looking words for entirely different things!). Good news, for Sprite you can use:
spriteObj.getHeight() and spriteObj.getWidth() for sprites, just as you do for everything else.
However I have found that you must ensure that height and width properties are first specified explicitly in the declaration of your sprite object when you initialize it. Otherwise these methods return 'undefined' when later called. It won't automatically measure the height and return it with getHeight(), you must ensure it is specified in the Sprite object as a value (eg. 32) in order for getHeight() to return that value.

Related

Compute dimensions (bounding box) of packing algorithm result

I'm using this binary pack code. I'm using its GrowingPacker approach. It works fine, but I have a hard time figuring out the dimensions of the final pack, I mean the bounding box of final result like (xMin, xMax, yMin, yMax). What is the best approach to find it?
Can I use the final values of x, y, w, h for this.root to compute the bounding box?
I'm not sure if it is correct, but currently I'm using a loop like that loop to compute the bounding box of final pack (I'm using C++):
#include <cfloat> // For FLT_MAX
float minX = FLT_MAX;
float minY = FLT_MAX;
float maxW = - FLT_MAX;
float maxH = - FLT_MAX;
for (const Block &block : blocks) {
if (block.fit) {
if (block.fit->x < minX)
minX = block.fit->x;
if (block.fit->y < minY)
minY = block.fit->y;
if (block.fit->w > maxW)
maxW = block.fit->w;
if (block.fit->h > maxH)
maxH = block.fit->h;
}
}
To calculate the bounding box that encompasses all the bounding boxes in your list of blocks, you need find the minimum and maximum X and Y and then use that to calculate the width and height of the overall bounding box.
Calculating the maximum width and height of the smaller boxes won't work because that will be the size of the widest and highest of the individual smaller boxes, which won't necessarily be the dimensions of the overall bounding box that encompasses all of them.
float minX = FLT_MAX;
float minY = FLT_MAX;
float maxX = - FLT_MAX;
float maxY = - FLT_MAX;
for (const Block &block : blocks) {
if (block.fit) {
if (block.fit->x < minX)
minX = block.fit->x;
if (block.fit->y < minY)
minY = block.fit->y;
if (block.fit->x + block.fit->w > maxX)
maxX = block.fit->x + block.fit->w;
if (block.fit->y + block.fit->h > maxY)
maxY = block.fit->y + block.fit->h;
}
}
// now that you have the min/max of x and y, calculate overall w and h:
float w = maxX > minX ? maxX - minX : 0.0f;
float h = maxY > minY ? maxY - minY : 0.0f;

GLUT timer function

I am trying to get my tokens on a board game to fall slowly. Right now, they fall, but they fall so fast. How could I implement the timer function in my code? Right now I do a loop, that updates the y coordinate of glTranslate. But it is still too fast! the top y is the y coordinate where I press on the screen, and the bottomy is the coordinates of the lowest open spot for a token.
col =0;
double bottomy = 0;
int row = 0;
circlex = (double)x / width ;
circley = (double)y / height ;
row = board.getRow(col) + 1;
bottomy = 500 - (25*row);
for( double topy = y ; topy <= bottomy; topy += 2 ){
glTranslatef(circlex, circley, 0.0f);
circley += .0000000000000000001;
display();
}
r = board.makeMove(col);
You can use glutTimerFunc to execute a function at a regular time period. This has the signature
void glutTimerFunc(unsigned int msecs,
void (*func)(int value),
value);
For example if your drawing function was
void UpdateTokens(int time);
Then you could call an update every 0.5 seconds with the following call (where current_time was the current simulation time)
glutTimerFunc(500, UpdateTokens, current_time);
For more precise timing, I would recommend using <chrono> instead, and performing your timing using things like std::chrono::duration with a std::chrono::steady_clock.
The actual problem here is how glut works. Basically, the user only gets a image presented at the end of the main loop. As long as you do not return from the mouse function, nothing is presented on screen. You can solve the problem by transferring the work to the display function and distribute the translation across multiple frames:
global variables:
double circlex = 0, circley = 0, bottomy = 0;
bool isfalling = false;
int topy = 0;
mouse_func:
if (isfalling == false) //Prevents the user from clicking during an animation
{
circlex = (double)x / width ;
circley = (double)y / height ;
int row = board.getRow(col) + 1;
bottomy = 500 - (25*row);
topy = y;
isfalling = true;
}
display_func:
if (isfalling)
{
circley += .0000000000000000001;
topy += 2;
if (topy >= bottomy)
isfalling = false;
}
glTranslatef(circlex, circley, 0.0f);
display();

Max and min vertices in a rectangle

I am re asking this question with a better explanation.
I have obtained the four points of a rectangle that I wish to perform a warp perspective transformation on. I have successfully achieved a transform on one of my images as I manually selected the points and assigned their location for the transform.
cv::Point2f src_vertices[4];
src_vertices[0] = corners[3];
src_vertices[1] = corners[1];
src_vertices[2] = corners[0];
src_vertices[3] = corners[2];
Point2f dst_vertices[4];
dst_vertices[0] = Point(0, 0);
dst_vertices[1] = Point(box.boundingRect().width-1, 0);
dst_vertices[2] = Point(0, box.boundingRect().height-1);
dst_vertices[3] = Point(box.boundingRect().width-1, box.boundingRect().height-1);
As you can see I assigned the corners to the transformation vertices manually.
As I wish to use this code on multiple slightly different images I would like a more accurate way of assigning the corners.
All the images will look similar to this:
http://imgur.com/t0cgTzr
The corners for this image are as follows:
Top left - (1106, 331),
Top right- (810, 747),
Bottom left- (825, 187),
Bottom right- (510, 537)
I have found the max and min x and y values as follows:
float X, Y;
float maxX= 0;
float minX = 10000;
float maxY= 0;
float minY = 10000;
for(int i=0; i< 4; i++){
if( corners[i].x > maxX){
maxX = corners[i].x;
}
if( corners[i].x < minX){
minX = corners[i].x;
}
if( corners[i].y > maxY){
maxY = corners[i].y;
}
if( corners[i].y < minY){
minY = corners[i].y;
}
}
This gives me:
maxX - 1106, minX - 510, maxY - 747, minY - 187.
I would like to know how to recombine the max and min values to their respective values so I can use the points to perform the transform. I am quite new to opencv so sorry if this is very obvious.
What you can do to get the corners without losing information on the other coordinate is to find the whole point. Instead of storing just float maxX= 0; you can store Point2f maxX(0,0); and modify you for loop to keep track of the point itself, not only the x coordinate.
Better yet, get rid of those loops and make use of STL
Point2f maxX =
*std::max_element(corners, corners+4, [](Point2f a, Point2f b){return a.x < b.x;});

Why ball1.boundingrect.center returns the same value as ball2.boundingrect.center?

I'm programming a physis simulation with circles.
Ball.cpp Code:
Ball::Ball()
{
angle = 0;
setRotation(angle);
//set the speed
speed = 5;
double StartX = 720;
double StartY = 80;
StartX = (qrand() % 800);
StartY = (qrand() % 400);
radius = 40;
setTransformOriginPoint(radius,radius);
setPos (StartX,StartY);
}
QRectF Ball::boundingRect() const
{
return QRect(0,0,2*radius,2*radius);
}
bool Ball:: circCollide(QList <QGraphicsItem *> items) {
QPointF c1 = mapToParent(this->boundingRect().center());
foreach (QGraphicsItem * t, items) {
Ball * CastBall = dynamic_cast<Ball *>(t);
if(CastBall)
{
QPointF t1 = mapToScene(CastBall->boundingRect().center());
double distance = QLineF(c1,t1).length();
double radius1 = this->boundingRect().width() / 2;
double radius2 = CastBall->boundingRect().width() / 2;
double radii = radius1 + radius2;
if ( distance <= radii )
{
// qDebug() << "true collision";
return true;
}
}
}
// qDebug() << "false collision";
return false;
}
I've got the problem that this string of code returns always the same values for the position of the center for both objects, (t1.x == c1.x , t1.y == c1.y) but this == CastBall returns false, so it wasn't the same object, it just has the same coordinates for the centerpoint of the boundingRect.
The coordinates are already equal before this function is called and that for all 3 objects I generate, although the sets always have a different value.
First I thought it was a problem because boundingRect is defined as a const, so I made this function in my class
QRectF Ball:: centerRect()
{
return QRect(0,0,2*radius,2*radius);
}
and just replaced every use of boundingRect with it (was no problem since I already cast it in the method), but it still returned the same value for both centers.
Im really at my wits end with this one and hope to find some help.
The problem was following: the center of the bounding rectangle was not mapped to the coordinates of the ball. Following statement should work:
mapToScene(mapToItem(castBall, castBall->boundingRect().center()));

cocos2dx inverse scaling a layer

I have a CCLayer which holds all my game objects and i have implemented scaling and scrolling. To make sure that you can't scroll out of bounds i am calculating a rect that represents the screen and use it to check if the rect is within bounds. The problem is that my calculations are wrong. The layer is scaled by a scaleFactor like so:
world->setScale(scaleFactor);
and then i calculate the scroll rect:
float scrollWidth = winSize.width * ( 1 / scaleFactor); // winSize is the size of the screen (1280x
float scrollHeight = winSize.height * ( 1 / scaleFactor);
if(scrollRect.l < 0) scrollRect.l = 0;
if(scrollRect.l + scrollWidth > levelWidth) scrollRect.l -= (scrollRect.l + scrollWidth - levelWidth);
scrollRect.r = scrollRect.l + scrollWidth;
world->setPosition(-scrollRect.l, -scrollRect.b);
(the scale factor value is between 1.0 and 0.5)
This sort of works but only when the layer is zoomed out to the max or zoomed in to the minimum but when scaleFactor isn't MAX/MIN it is wrong (there is some left space).
What am i doing wrong? I've also tried changing the anchor points (they are currently set to 0,0) but without any success.
You can do this whatever your scale factor...
here _tileMap is your world
//Code for getting difference b/w two position
CCTouch *fingerOne = (CCTouch*)touchArray->objectAtIndex(0);
CCPoint newTouchLocation = fingerOne->getLocationInView();
newTouchLocation = CCDirector::sharedDirector()->convertToGL(newTouchLocation);
newTouchLocation=_tileMap->convertToNodeSpace(newTouchLocation);
CCPoint oldTouchLocation = fingerOne->getPreviousLocationInView();
oldTouchLocation = CCDirector::sharedDirector()->convertToGL(oldTouchLocation);
oldTouchLocation = _tileMap->convertToNodeSpace(oldTouchLocation);
//get the difference in the finger touches when the player was dragging
CCPoint difference = ccpSub(newTouchLocation, oldTouchLocation);
CCPoint ASD=ccpAdd(_tileMap->getPosition(), ccpMult(difference, _tileMap->getScale()));
CCPoint bottomLeft =ASD;
// Bounding Box....
if (bottomLeft.x >0) {
bottomLeft.x = 0;
}
if (bottomLeft.y>0) {
bottomLeft.y = 0;
}
if (bottomLeft.x < -(mapWidth*_tileMap->getScale() - _screenSize.width)) {
bottomLeft.x = -(mapWidth*_tileMap->getScale()- _screenSize.width);
}
if (bottomLeft.y <-(mapHieght*_tileMap->getScale() - _screenSize.height)) {
bottomLeft.y = - (mapHieght*_tileMap->getScale() - _screenSize.height);
}
_tileMap->setPosition(bottomLeft);
I hope this may help you..