i want to create a game and addes a image to my game, now i want it to move down smoothly. i have a code like this:
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
pos.Y = pos.Y + 1;
base.Update(gameTime);
}
the movement works but it dont looks smooth, it looks like it jiggle. pos is a vector2 for the position in the image.
how to make it more smooth?
If you want movement to be smooth without adding a physics library you just have to factor in gameTime to your position update.
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
pos.Y = pos.Y * 100 * (float)gameTime.ElapsedGameTime.TotalSeconds;
base.Update(gameTime);
}
I don't have access to XNA + visual studio right now, but the changes I made should give you an idea of what to try out. Keep in mind the Update call happens multiple times a second so the elapsed time will be a small number so then you have to multiply it by a larger "movement" value in this case I put 100. Tweak 100 until you see the movement speed you desire.
Beanish is right, you should multiply by GameTime if you want smoothness. Physics is an overkill if you only want your animation to look smooth.
The best way I've found to do animation is by using position interpolation, for this to work you have to know the initial (you already know this) and final position of the image.
If you want to move from A to B in, say, 2 seconds, you can use the following code.
Vector2 a = new Vector2(0, 0);
Vector2 b = new Vector2(0, 100);
float elapsedTime = 0;
float duration = 2.0;
public override void Update(GameTime gameTime)
{
float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
elapsedTime += dt;
if (elapsedTime > 1)
elapsedTime = 1;
float param = elapsedTime / duration;
pos = Vector2.Lerp(a, b, param);
}
The best thing about using this approach is that you can now use "easing" to make you animation look really really nice.
To do this just add a Power operation to the interpolator parameter:
pos = Vector2.Lerp(a, b, (float)Math.Pow(param /2.0, 0.5));
This will make you image slow down as it arrives to B. You can play with the exponent value (0.5) to get different results, try 2.0 for example.
Another important thing is that your image will always stop at B. If you use the Euler integration approach (your approach, adding a velocity each frame) you might have some trouble making the image stop at the right position (aka B) and it gets even worse when using 2 or 3 dimesions.
To know more about easing, check Robert Penner's Easing Equations.
First I can tell you what the problem isn't. You don't need a physics engine to have smooth movement. And changing the Update to include the ElapsedGameTime will not make a lick of difference for the smoothness (assuming you haven't changed the default of IsFixedTimestep to false). When there is a fixed timestep, ElapsedGameTime will always have the same value, it will not vary.
I don't how much you are doing in your code, but if it's too much, XNA will start skipping the Draw portion of your code, and this can definitely cause jerkiness. One way to check: in your Update method, test the value of IsRunningSlowly. Whenever it is true, XNA will skip some Draw calls.
If you are not doing anything complicated, then the culprit may be the refresh rate of your monitor. If it is set to anything other than 60Hz, you will have jerkiness. You could fix this by changing your monitor's refresh rate. Alternatively you can change the value of TargetElapsedTime to match your monitor's rate.
You should consider adding to your game a library for handling physics, as for example FarseerPhysics. By calculating the position in a per time base with physics rules applied your movements will be smooth and natural.
Related
I read a lot, and tried many things, but can't get this done, and it seems simple
I have the following p5js code
function setup() {
let canvas = createCanvas(400, 400);
noLoop();
}
function draw() {
background(220);
push();
translate(50,100);
point(25,25);
// MISSING CODE to get 75,125
pop();
}
And I'm trying to figure out if there is a way to get the actual coordinates were the point is drawn,
I read about getTransform, the matrix, and a lot of stuff, but seems impossible to get it done. Also I need to use rotation in the transform, so that makes it even harder
Thanks!
Use variables, so you can keep track of how much you translated and the location of your point, so you can them add them to obtain the desired result.
let trans_x = 50
let trans_y = 100
let point_x = 25
let point_y = 25
translate(trans_x, trans_y);
point(point_x, point_y);
result_x = trans_x + point_x // 50+25=75
result_y = trans_y + point_y // 100+25=125
You could use Vectors so you don't have to define 2 variables, but you get the idea.
Usually you would call WorldPosition to the absolute position of the object and RelativePosition to the position the object relative to the CameraPosition
The translation would be called CameraPosition and to make your code more efficient you should only draw objects that their RelativePosition falls inside the drawable area.
I am creating a model of a solar system in processing, and after removing the background I noticed the planets were leaving a trail of their image behind them. The program runs fine when the background is back in, but I want to add a lot more and I am sure this is inefficient and will bog things down.
I am very new to processing, and I am really not sure how to solve this. Maybe delete previous images after a delay to create a shortened trail?
These are just the parts I think are important cherry picked from the code, this is just the example of one planet. Sorry if the code is clunky, any suggestions are happily accepted.
Planet p1;
void setup() {
mercury = loadImage("mercury.png")
p1 = new Planet(40, random(TWO_PI), 0.05);
}
void draw() {
//background(0)
translate(width / 2, height / 2);
p1.display1();
p1.orbit();
}
class Planet {
float radius;
float angle;
float distance;
float orbitSpeed;
Planet(float r, float d, float o) {
radius = r;
distance = d;
orbitSpeed = o;
angle = random(TWO_PI);
}
void orbit() {
angle = angle + orbitSpeed;
}
void display1() {
pushMatrix();
rotate(angle);
translate(distance, 0);
imageMode(CENTER);
image(mercury, radius, radius, 10, 10);
popMatrix();
}
}
I realized that this would probably happen, and I am not sure how to stop it.
The behavior you describe is simply the nature of computer graphics; it's how games, operating systems, and hardware displays all work – they clear and redraw everything every frame.
In Processing, graphic objects that are pushed to a buffer remain there indefinitely until the buffer is cleared or something is pushed on top of them (this is why the planets are leaving a trail without calling background() – previous frames remain in the buffer).
You are worried about the background() being inefficient. Don't be, as it's one of the fastest operations (simply sets the value of each pixel, as given by the user).
Processing does provide a clear() function, but this is equivalent to background(0).
If you're are still concerned about efficiency and speed, one way to speed up Processing is to use the FX2D renderer rather than default AWT renderer. Another way is cache drawn objects into PGraphics objects to prevent successive rasterization (since your planets are image files and not drawn with processing, you needn't worry about this).
Your code is simple enough that it doesn't need optimisations at this stage.
As micycle mentions, you are are drawing an image at a translated position, pretty similar to blitting.
In terms of the trails, one common trick you could use is not clear the screen completely, but draw a transparent rectangle as the background. The more transparency, the longer the trails.
Here's a tweaked version of your code:
// planet object
Planet p1;
// planet texture
PImage mercury;
void setup() {
size(300, 300);
// draw image from center
imageMode(CENTER);
// clear to black one
background(0);
// remove strokes (we'll use rect() later)
noStroke();
// set the fill to black but with 9/255 transparency (~3.5% transparent)
fill(0,9);
// init texture
mercury = loadImage("mercury.png");
// init planet
p1 = new Planet(40, random(TWO_PI), 0.05);
}
void draw() {
// draw a transparent rectangle instead of completely clearing the screen
rect(0,0,width,height);
// render planet
translate(width / 2, height / 2);
p1.display1();
p1.orbit();
}
class Planet {
float radius;
float angle;
float distance;
float orbitSpeed;
Planet(float r, float d, float o) {
radius = r;
distance = d;
orbitSpeed = o;
angle = random(TWO_PI);
}
void orbit() {
angle = angle + orbitSpeed;
}
void display1() {
pushMatrix();
rotate(angle);
translate(distance, 0);
image(mercury, radius, radius, 10, 10);
popMatrix();
}
}
It's an efficient quick'n'dirty hack as you won't need to store previous position and redraw multiple times, however it has it limitations in terms of the flexibility of the trails. Hopefully tweaking the fill() alpha parameter will get you the desired effect.
Later on if you're drawing many many many planets it things start running slow have a peak at VisualVM. Profile the CPU and see the methods that take the longest to complete and focus on those. Don't need to optimise everything, just the slowest calls. Remember that Processing have multiple renderers: JAVA2D is the default one, but there's also FX2D and P2D/P3D and they will behave differently. I strongly recommend optimising at the last moment (otherwise code might be less flexible and readable and will slow down development/iteration).
Im a beginner at Leap Motion. I am wondering how to get the previous finger position of my hand. I am basically looking for the equivalent of pmouseX and pmouseY from Processing.
I'm not really familiar with Leap Motion, but assuming you have access to the current finger position, you could always track the previous position yourself. In Processing it would look something like this:
int previousMouseX;
int previousMouseY;
void draw(){
line(previousMouseX, previousMouseY, mouseX, mouseY);
previousMouseX = mouseX;
previouseMouseY = mouseY;
}
This is pretty much what Processing is doing for you with the pmouseX and pmouseY variables.
I'm working on a 3D scene viewer with the HOOPS Engine
I want to implement support for a 3D mouse. Everything is working fine but there is one remaining problem I don't know how to solve:
I move my camera with following formula:
HC_Dolly_Camera(-(factor.x * this->m_speed), factor.y * this->m_speed, factor.z * this->m_speed);
this->m_speed is dependent on scene extents. But if the scene is really big (e.g. a airport) the camera speed is on a deep zoom level ridiculous fast.
My first attempt was to implement a kind of damping factor which is dependent on the distance from objects to my camera. It works ... somehow. Sometimes I noticed ugly "bouncing effects" which I can avoid with smooth acceleration and a modified cosine function.
But my question is: Is there a best practice to reduce camera speed in closeup situations in a 3D scene? My approach is working, but I think it is not a good solution due it uses many raycasts.
Best regards,
peekaboo777
P.S.:
My code
if(!this->smooth_damping)
{
if(int res = HC_Compute_Selection_By_Area(this->view->GetDriverPath(), ".", "v", -0.5, 0.5, -0.5, 0.5) > 0)
{
float window_x, window_y, window_z, camera_x, camera_y, camera_z;
double dist_length = 0;
double shortest_dist = this->max_world_extent;
while(HC_Find_Related_Selection())
{
HC_Show_Selection_Position(&window_x, &window_y, &window_z, &camera_x, &camera_y, &camera_z);
this->view->GetCamera(&this->cam);
// Compute distance vector
this->dist.Set(cam.position.x - camera_x, cam.position.y - camera_y, cam.position.z - camera_z);
dist_length = sqrt(pow((cam.position.x - camera_x), 2) + pow((cam.position.y - camera_y), 2) + pow((cam.position.z - camera_z), 2));
if(dist_length < shortest_dist)
shortest_dist = dist_length;
}
// Reduced computation
// Compute damping factor
damping_factor = ((1 - 8) / (this->max_world_extent - 1)) * (shortest_dist - 1) + 8;
// Difference to big? (Gap)
if(qFabs(damping_factor - damping_factor * 0.7) < qFabs(damping_factor - this->last_damping_factor))
{
this->smooth_damping = true;
this->damping_factor_to_reach = damping_factor; // this is the new damping factor we have to reach
this->freezed_damping_factor = this->last_damping_factor; // damping factor before gap.
if(this->last_damping_factor > damping_factor) // Negative acceleration
{
this->acceleration = false;
}
else // Acceleration
{
this->acceleration = true;
}
}
else
{
this->last_damping_factor = damping_factor;
}
}
}
else
{
if(this->acceleration)
{
if(this->freezed_damping_factor -= 0.2 >= 1);
damping_factor = this->freezed_damping_factor +
(((this->damping_factor_to_reach - this->freezed_damping_factor) / 2) -
((this->damping_factor_to_reach - this->freezed_damping_factor) / 2) *
qCos(M_PI * this->damping_step)); // cosine function between freezed and to reach
this->last_damping_factor = damping_factor;
if(damping_factor >= this->damping_factor_to_reach)
{
this->smooth_damping = false;
this->damping_step = 0;
this->freezed_damping_factor = 0;
} // Reset
}
else
{
if(this->freezed_damping_factor += 0.2 >= 1);
damping_factor = this->damping_factor_to_reach +
((this->freezed_damping_factor - this->damping_factor_to_reach) -
(((this->freezed_damping_factor - this->damping_factor_to_reach) / 2) -
((this->freezed_damping_factor - this->damping_factor_to_reach) / 2) *
qCos(M_PI * this->damping_step))); // cosine functio between to reach and freezed
this->last_damping_factor = damping_factor;
if(damping_factor <= this->damping_factor_to_reach)
{
this->smooth_damping = false;
this->damping_step = 0;
this->freezed_damping_factor = 0;
} // Reset
}
this->damping_step += 0.01; // Increase the "X"
}
I've never used the HOOPS engine, but do you have any way to get the closest object to the camera? You could scale your speed with this value, so your camera gets slower close to objects.
Even better would be to take the closest point on bounding-box instead of center of object. This would improve the behaviour close to big objects like long walls/floor.
Another solution I'd try would be to raycast through the view center to look for the first object and use the distance the same way. In this approach you'll not be slowed down by objects behind you. You may also add additional raycast points, like in 1/4 of screen and blend resulting values, so you have more constant speed scale.
What I understand from your question is that you want a way to steer camera through large scenes, like an airport and still be able to move slowly close to the objects. I don't think there's some 'universal' way of doing it. All will depend on your Engine/API features and specific needs. If all those solutions doesn't work, maybe you should try with paper and pen ;) .
You said that m_speed is dependent on scene extent, I guess this dependency is linear (by linear I mean if you are measuring the scene extend with something called sExtent, m_speed equals c*sExtent that c is some constant coefficient).
So to make m_speed dependent on scene extent but avoid huge m_speed for large scale scenes , I suggest to make dependency of m_speed to sExtent non-linear, like logarithmic dependency:
m_speed = c*log(sExtent+1)
This way your m_speed will be bigger if scene is bigger, but not in the same ratio. you also can use radical to create non-linear dependency. below you can compare these functions:
Im working on a project where i want to generate a 3D mesh to represent a certain amount of data.
To create this mesh i want to use transformation Matrixes, so i created a class based upon the mathematical algorithms found on a couple of websites.
Everything seems to work, scale/translation but as soon as im rotating a mesh on its x-axis its starts to deform after 2 to 3 complete rotations. It feels like my scale values are increasing which transforms my mesh. I'm struggling with this problem for a couple of days but i can't figure out what's going wrong.
To make things more clear you can download my complete setup here.
I defined the coordinates of a box and put them through the transformation matrix before writing them to the screen
This is the formula for rotating my object
void appendRotation(float inXAngle, float inYAngle, float inZAngle, PVector inPivot ) {
boolean setPivot = false;
if (inPivot.x != 0 || inPivot.y != 0 || inPivot.z != 0) {
setPivot = true;
}
// If a setPivot = true, translate the position
if (setPivot) {
// Translations for the different axises need to be set different
if (inPivot.x != 0) { this.appendTranslation(inPivot.x,0,0); }
if (inPivot.y != 0) { this.appendTranslation(0,inPivot.y,0); }
if (inPivot.z != 0) { this.appendTranslation(0,0,inPivot.z); }
}
// Create a rotationmatrix
Matrix3D rotationMatrix = new Matrix3D();
// xsin en xcos
float xSinCal = sin(radians(inXAngle));
float xCosCal = cos(radians(inXAngle));
// ysin en ycos
float ySinCal = sin(radians(inYAngle));
float yCosCal = cos(radians(inYAngle));
// zsin en zcos
float zSinCal = sin(radians(inZAngle));
float zCosCal = cos(radians(inZAngle));
// Rotate around x
rotationMatrix.setIdentity();
// --
rotationMatrix.matrix[1][1] = xCosCal;
rotationMatrix.matrix[1][2] = xSinCal;
rotationMatrix.matrix[2][1] = -xSinCal;
rotationMatrix.matrix[2][2] = xCosCal;
// Add rotation to the basis matrix
this.multiplyWith(rotationMatrix);
// Rotate around y
rotationMatrix.setIdentity();
// --
rotationMatrix.matrix[0][0] = yCosCal;
rotationMatrix.matrix[0][2] = -ySinCal;
rotationMatrix.matrix[2][0] = ySinCal;
rotationMatrix.matrix[2][2] = yCosCal;
// Add rotation to the basis matrix
this.multiplyWith(rotationMatrix);
// Rotate around z
rotationMatrix.setIdentity();
// --
rotationMatrix.matrix[0][0] = zCosCal;
rotationMatrix.matrix[0][1] = zSinCal;
rotationMatrix.matrix[1][0] = -zSinCal;
rotationMatrix.matrix[1][1] = zCosCal;
// Add rotation to the basis matrix
this.multiplyWith(rotationMatrix);
// Untranslate the position
if (setPivot) {
// Translations for the different axises need to be set different
if (inPivot.x != 0) { this.appendTranslation(-inPivot.x,0,0); }
if (inPivot.y != 0) { this.appendTranslation(0,-inPivot.y,0); }
if (inPivot.z != 0) { this.appendTranslation(0,0,-inPivot.z); }
}
}
Does anyone have a clue?
You never want to cumulatively transform matrices. This will introduce error into your matrices and cause problems such as scaling or skewing the orthographic components.
The correct method would be to keep track of the cumulative pitch, yaw, roll angles. Then reconstruct the transformation matrix from those angles every update.
If there is any chance: avoid multiplying rotation matrices. Keep track of the cumulative rotation and compute a new rotation matrix at each step.
If it is impossible to avoid multiplying the rotation matrices then renormalize them (starts on page 16). It works for me just fine for more than 10 thousand multiplications.
However, I suspect that it will not help you, numerical errors usually requires more than 2 steps to manifest themselves. It seems to me the reason for your problem is somewhere else.
Yaw, pitch and roll are not good for arbitrary rotations. Euler angles suffer from singularities and instability. Look at 38:25 (presentation of David Sachs)
http://www.youtube.com/watch?v=C7JQ7Rpwn2k
Good luck!
As #don mentions, try to avoid cumulative transformations, as you can run into all sort of problems. Rotating by one axis at a time might lead you to Gimbal Lock issues. Try to do all rotations in one go.
Also, bare in mind that Processing comes with it's own Matrix3D class called PMatrix3D which has a rotate() method which takes an angle(in radians) and x,y,z values for the rotation axis.
Here is an example function that would rotate a bunch of PVectors:
PVector[] rotateVerts(PVector[] verts,float angle,PVector axis){
int vl = verts.length;
PVector[] clone = new PVector[vl];
for(int i = 0; i<vl;i++) clone[i] = verts[i].get();
//rotate using a matrix
PMatrix3D rMat = new PMatrix3D();
rMat.rotate(angle,axis.x,axis.y,axis.z);
PVector[] dst = new PVector[vl];
for(int i = 0; i<vl;i++) {
dst[i] = new PVector();
rMat.mult(clone[i],dst[i]);
}
return dst;
}
and here is an example using it.
HTH
A shot in the dark: I don't know the rules or the name of the programming language you are using, but this procedure looks suspicious:
void setIdentity() {
this.matrix = identityMatrix;
}
Are you sure your are taking a copy of identityMatrix? If it is just a reference you are copying, then identityMatrix will be modified by later operations, and soon nothing makes sense.
Though the matrix renormalization suggested probably works fine in practice, it is a bit ad-hoc from a mathematical point of view. A better way of doing it is to represent the cumulative rotations using quaternions, which are only converted to a rotation matrix upon application. The quaternions will also drift slowly from orthogonality (though slower), but the important thing is that they have a well-defined renormalization.
Good starting information for implementing this can be:
http://www.cprogramming.com/tutorial/3d/quaternions.html
http://www.scheib.net/school/library/quaternions.pdf
A useful academic reference can be:
K. Shoemake, “Animating rotation with quaternion curves,” ACM
SIGGRAPH Comput. Graph., vol. 19, no. 3, pp. 245–254, 1985. DOI:10.1145/325165.325242