Raphael.js - scale an element over time - raphael

Very new to using Raphael.js
I'm looking at the tutorials and I am able to create a circle.
But how would I scale the circle to double the size over two seconds.

Assuming your circle is created like:
var circle = paper.circle(50, 40, 10);
You can scale it up over two seconds like:
circle.animate({
transform: 's2'
}, 2000, 'easeIn');
You could also just double its radius if it is fixed.

Related

Drawing a sprite on the circumference of a circle based on the position of other objects

I'm making a sniper shooter arcade style game in Gamemaker Studio 2 and I want the position of targets outside of the viewport to be pointed to by chevrons that move along the circumference of the scope when it moves. I am using trig techniques to determine the coordinates but the chevron is jumping around and doesn't seem to be pointing to the target. I have the code broken into two: the code to determine the coordinates in the step event of the enemies class (the objects that will be pointed to) and a draw event in the same class. Additionally, when I try to rotate the chevron so it also points to the enemy, it doesn't draw at all.
Here's the coordinate algorithm and the code to draw the chevrons, respectively
//determine the angle the target makes with the player
delta_x = abs(ObjectPlayer.x - x); //x axis displacement
delta_y = abs(ObjectPlayer.y - y); //y axis displacement
angle = arctan2(delta_y,delta_x); //angle in radians
angle *= 180/pi //angle in radians
//Determine the direction based on the larger dimension and
largest_distance = max(x,y);
plusOrMinus = (largest_distance == x)?
sign(ObjectPlayer.x-x) : sign(ObjectPlayer.y-y);
//define the chevron coordinates
chevron_x = ObjectPlayer.x + plusOrMinus*(cos(angle) + 20);
chevron_y = ObjectPlayer.y + plusOrMinus*(sign(angle) + 20);
The drawing code
if(object_exists(ObjectEnemy)){
draw_text(ObjectPlayer.x, ObjectPlayer.y-10,string(angle));
draw_sprite(Spr_Chevron,-1,chevron_x,chevron_y);
//sSpr_Chevron.image_angle = angle;
}
Your current code is slightly more complex that it needs to be for this, if you want to draw chevrons pointing towards all enemies, you might as well do that on spot in Draw. And use degree-based functions if you're going to need degrees for drawing anyway
var px = ObjectPlayer.x;
var py = ObjectPlayer.y;
with (ObjectEnemy) {
var angle = point_direction(px, py, x, y);
var chevron_x = px + lengthdir_x(20, angle);
var chevron_y = py + lengthdir_y(20, angle);
draw_sprite_ext(Spr_Chevron, -1, chevron_x, chevron_y, 1, 1, angle, c_white, 1);
}
(also see: an almost-decade old blog post of mine about doing this while clamping to screen edges instead)
Specific problems with your existing code are:
Using a single-axis plusOrMinus with two axes
Adding 20 to sine/cosine instead of multiplying them by it
Trying to apply an angle to sSpr_Chevron (?) instead of using draw_sprite_ext to draw a rotated sprite.
Calculating largest_distance based on executing instance's X/Y instead of delta X/Y.

Set interval for X and Y QwtPlotZoneItem

I need to plot a region on a graph using the QwtPlotZoneItem class. I need to set different intervals for both X and Y axes, how can I do that?
The orientation of my QwtPlotZoneItem is vertical, so based on the documentation, if I set the interval it will by applied to the X axis only.
"For a horizontal zone the interval is related to the y axis, for a
vertical zone it is related to the x axis."
My constructor sets:
setOrientation( Qt::Vertical );
setInterval( initDate, endDate );
Basically, what I need is to create multiple rectangles on my graph that represents the regions, for example:
Qt 5.3.2
Qwt 6.1.0
I was trying to use an incorrect class for my purposes. I found a note in the documentation:
"For displaying an area that is bounded for x and y coordinates use
QwtPlotShapeItem"
The QwtPlotShapeItem class does exactly what I need.
I need basically to set the brush and create the rectangle, for example:
QwtPlotShapeItem *shapeItem = new QwtPlotShapeItem();
shapeItem->setBrush(QColor(255,255,255, 0));
shapeItem->setPen(QColor(Qt::transparent), 0.0, Qt::SolidLine);
// TopLeft - BottomRight
QRect myRect(QPoint(startDate, yUpperPos), QPoint(endDate, yLowerPos));
shapeItem->setRect( QRectF(myRect) );
shapeItem->attach(myQwtPlot);
myQwtPlot->replot();

QGraphicsScene, how to place items based on center point

I have a QGraphicsScene, and I have determined where my center point is, but I now need to figure out how to place my items in the scene based on that information.
I have 2 pieces of data I need to work with: range and bearing.
Range obviously is how far away from the center point (or my location), and bearing is the direction from center point, with 0 being north, 180 being south and so on.
So for example, if I need to place an item at range: 20, bearing: 90, the item will be 20 (units) directly to the right of center point. Currently, placing the item with this data it is based off 0,0 being top left of the scene.
This all needs to be able to scale with the zoom state of the QGraphicsScene as well.
I'm totally lost at this conversion.
Unsure of how to get proper offsets with converting from coordinate system to coordinate system I managed to find a solution. Hopefully it's not considered too much of a hack job.
First I needed to offset from the top left (0,0), and knowing that my scene was 360, 360 that was easy.
Not being a math guy I was unsure about getting the angles, but after some research I saw that the info I had was exactly what I needed to derive a vector.
Here is the method I wrote to help me generate items in my QGraphicsScene.
QPointF Mainwindow::pointLocation(double bearing, double range){
int offset = 90; //used to offset Cartesian system
double centerX = 180;//push my center location out to halfway point
double centerY = 180;
double newX = centerX + qCos(qDegreesToRadians(bearing - offset)) * range;
double newY = centerY + qSin(qDegreesToRadians(bearing - offset)) * range;
QPointF newPoint = QPointF(newX, newY);
return newPoint;
}

How to draw a segment of a circle in Cocos2d-x?

Context
I try to draw pie chart for statistic in my game. I'm using Cocos2d-x ver.3.8.1. Size of the game is important, so I won't to use third-party frameworks to create pie charts.
Problem
I could not find any suitable method in Cocos2d-x for drawing part of the circle.
I tried to do
I tried to find a solution to this problem in Internet, but without success.
As is known, sector of a circle = triangle + segment. So, I tried to use the method drawSegment() from DrawNode also.
Although it has parameter radius ("The segment radius" written in API reference), radius affects only the thickness of the line.
drawSegment() method draw a simple line, the thickness of which is set by a method call.
Question
Please prompt me, how can I draw a segment or a sector of a circle in Cocos2d-x?
Any advice will be appreciated, thanks.
I think the one of the ways to draw a sector of a circle in Cocos2d-X is the way to use drawPolygon on DrawNode. I wrote little sample.
void drawSector(cocos2d::DrawNode* node, cocos2d::Vec2 origin, float radius, float angle_degree,
cocos2d::Color4F fillColor, float borderWidth, cocos2d::Color4F bordercolor,
unsigned int num_of_points = 100)
{
if (!node)
{
return;
}
const cocos2d::Vec2 start = origin + cocos2d::Vec2{radius, 0};
const auto angle_step = 2 * M_PI * angle_degree / 360.f / num_of_points;
std::vector<cocos2d::Point> circle;
circle.emplace_back(origin);
for (int i = 0; i <= num_of_points; i++)
{
auto rads = angle_step * i;
auto x = origin.x + radius * cosf(rads);
auto y = origin.y + radius * sinf(rads);
circle.emplace_back(x, y);
}
node->drawPolygon(circle.data(), circle.size(), fillColor, borderWidth, bordercolor);
}
This is the function to calculate the position of edge point of circle and draw polygon. If you want to use it, you need to call like following,
auto canvas = DrawNode::create();
drawSector(canvas, cocos2d::Vec2(400, 400), 100, 60, cocos2d::Color4F::GREEN, 2, cocos2d::Color4F::BLUE, 100);
this->addChild(triangle);
The result would be like this. I think the code will help your problem.

CDC::Ellipse doesn't draw correctly circles

In a project of mine (VC++2010, MFC), I want to draw a circle using the CDC::Ellipse. I set two points: the first one is the center of the circle, the second one is a point I want it to be on the circumference.
I pass to the CDC::Ellipse( int x1, int y1, int x2, int y2 ) the coordinates of the upper-left corner and lower-right one.
Briefly: with Pitagora Theorem I calculate the distance between the two points ( radius ), then I subtract this value from the coordinates of the center to obtain the upper-left corner and add to obtain the lower-right one.
When I draw the cirlce and the points, and I zoom in, I see that the second one isn't on the circumference as expected, it is slightly inside unless you set it at 0°, 45°, 90° and so on with respect to the absolute sistem of coordinates.
Then I tried to draw the same circle using CDC::Polyline, I gave to this method the points obtained rotating another point around the center, at the distance equal to the radius. In this case the point is on the circumference every where I set it.
The overlap of these two circles has shown that they perfectly overlap at 0°, 45°, 90° and so on, but the gap is maximum at 22.5°, 67.5° and so on.
Has anyone ever noticed a similar behavior?
Thanks to everybody that can help me!
Code snippet:
this is how I calculate the radius given 2 points:
centerPX = vvFPoint( 1380, 845 );
secondPointPX = vvFPoint( 654,654 );
double radiusPX = (sqrt( (secondPointPX.x - centerPX.x) * (secondPointPX.x - centerPX.x) + (secondPointPX.y - centerPX.y) * (secondPointPX.y - centerPX.y) ));
( vvFPoint is a custom type derived from CPoint )
this is how I draw the "circle" with the CDC::Ellipse:
int up = (int)(((double)(m_p1.y-(double)originY - m_radius) / zoom) + 0.5) + offY;
int left = (int)(((double)(m_p1.x-(double)originX - m_radius) / zoom) + 0.5) + offX;
int down = (int)(((double)(m_p1.y-(double)originY + m_radius) / zoom) + 0.5) + offY;
int right = (int)(((double)(m_p1.x-(double)originX + m_radius) / zoom) + 0.5) + offX;
pDC->Ellipse( left, up, right, down);
(m_p1 is the center of the circle, originX/Y is the origin of the image, m_radius is the radius of the circle, zoom is the scale factor, offX/Y is an offset in the client area of my SW)
this is how I draw the circle "manually" (and quite trivial method) using a custom polyline class:
1) create the array of points:
point.x = centerPX.x + radiusPX;
point.y = centerPX.y;
for ( i=0; i < 3600; i++ )
{
pt1.RotateDeg ( centerPX, (double)0.1 );
poly->AddPoint( pt1 );
}
(RotateDeg is a custom method to rotate a point using first argument as a pivot and second argument as angle value in degrees, AddPoint is a custom method to create the array of points, poly is my custom polyline object).
2) draw it:
When I call the Draw( CDC* pDC ) I use the previous array to draw the polyline:
pDC->MoveTo(p);
I hope this can help you to reproduce my weird observations!
code snippet 2:
void vvPoint<Tipo>::RotateDeg(const vvPoint<Tipo> &center, double angle)
{
vvPoint<Tipo> ptB;
angle *= -(M_PI / 180);
*this -= center;
ptB.x = ((this->x * cos(angle)) - (this->y * sin(angle)));
ptB.y = ((this->x * sin(angle)) + (this->y * cos(angle)));
*this = ptB + center;
}
But to let you better understand my observations I would like to add a few images so you can see where my whole question started from... The problem is: I can't add images since I need to have 10 reputation. I uploaded a .zip file on dropbox and if you want I can send you the URL of this file. Let me know if this is the correct (and safe..) way to bypass this problem.
Thanks!
This might be a possible explanation. As MSDN says about CDC::Ellipse (with my emphasis):
The center of the ellipse is the center of the bounding rectangle
specified by x1, y1, x2, and y2, or lpRect. The ellipse is drawn with
the current pen, and its interior is filled with the current brush.
The figure drawn by this function extends up to, but does not include,
the right and bottom coordinates. This means that the height of the
figure is y2 – y1 and the width of the figure is x2 – x1.
The way you described how you calculate the bounding rectangle is not entirely clear (some source code would have helped) but, given the second paragraph quoted above, you possibly need to add 1 to your x2 and y2 values, to make sure you have a circle with the desired radius.
It's also worth noting that there may be slight rounding differences between your two drawing methods where you have an odd-sized bounding box (i.e. so the centre point falls logically on a half-pixel).
UPDATE
Using your code snippets (thanks), and assuming no zoom and zero offsets etc., I get a radius of 750.704 pixels and the following parameters for the ellipse:
pDC->Ellipse(629, 94, 2131, 1596);
According to MSDN, this means that the ellipse will be drawn in a figure of the following dimensions:
width = (2131 - 629) = 1502
height = (1596 - 94) = 1502
So as far as I can see, this should produce a circle rather than an ellipse.
The next thing to do is to find out how you're drawing the polygon - for that we need to see the implementation of RotateDeg - can you post that code? I'm suspecting some simple rounding error here, that maybe gets magnified when you zoom.
UPDATE 2
Just looking at this code:
for ( i=0; i < 3600; i++ )
{
pt1.RotateDeg ( centerPX, (double)0.1 );
poly->AddPoint( pt1 );
}
You are rotating your polygon points incrementally by 0.1 degrees each time. This will possibly accumulate some errors, so it may be worth doing it something like this instead:
for ( i=0; i < 3600; i++ )
{
vvFPoint ptNew = pt1;
ptNew.RotateDeg ( centerPX, (double)i * 0.1 );
poly->AddPoint( ptNew );
}
Maybe this will mean you have to change your RotateDeg function to take care of the correct quadrants.
One other point, you mentioned that you see the problem when you zoom into the image. If this means you are using you zoom variable, it is worth checking in this line ...:
pDC->Ellipse( left, up, right, down);
... that the parameters still form a square shape, so (right - left) == (down - up).
UPDATE 3
I just ran your RotateDeg function, in its current form, to see how the error accumulates (by feeding in the previous result to the next iteration). At each step, I calculated the distance between the new point and the centre and compared this with the required radius.
The chart below shows the result, where you can see an error of 4 pixels by the time the points have been calculated.
I think that this at least explains part of the difference (i.e. your polygon drawing is flawed) and - depending on zoom - you may introduce asymmetry into the ellipse parameters, which you can debug by comparing the width to the height as I described above.