Changing code inside an unexecuted if block alters my program - c++

I am making a physics-based where balls (gdi+ ellipses) will collide. There are 4 conditions I need to program to make the collisions work correctly. To do this I'm using if statements.
I noticed when debugging that in some cases, the code inside the if block is NOT executed as if the condition was not met - however - changing the code inside that if block will still alter the way my program works.
I've extensively debugged to ensure this is what's happening. I've also switched up the way I'm writing my if statements to ensure the logic is correct, but the problem persists.
When the game is started, I add a couple of balls to a vector.
/**
* Start a new game
*/
void CGame::NewGame()
{
this->mBalls.clear();
shared_ptr<CBall> cueBall = make_shared<CBall>(this);
cueBall->SetX(410.0);
cueBall->SetY(379.0 - (25 / 2) - 110);
cueBall->SetVelocityX(0);
cueBall->SetVelocityY(160.0);
this->mGameItems.push_back(cueBall);
shared_ptr<CBall> ball1 = make_shared<CBall>(this);
ball1->SetX(420.0);
ball1->SetY(379.0 - (25 / 2));
this->mGameItems.push_back(ball1);
}
They are then drawn on the screen by iterating through the vector CGame.mGameItems and calling a Draw function on each one.
/**
* Draw the ball with as a circle
* \param graphics The GDI+ graphics context to draw on
*/
void CBall::Draw(Gdiplus::Graphics* graphics)
{
SolidBrush colorBrush(Color(255, 1000, 1000, 1000));
graphics->FillEllipse(&colorBrush, Rect(this->GetX(), this->GetY(), this->diameter, this->diameter));
}
The redrawing and updating of the window is done in CChildView::OnPaint.
/** This function is called to draw in the window.
*
* This function is called in response to a drawing message
* whenever we need to redraw the window on the screen.
* It is responsible for painting the window.
*/
void CChildView::OnPaint()
{
CPaintDC paintDC(this); // device context for painting
CDoubleBufferDC dc(&paintDC); // device context for painting
Graphics graphics(dc.m_hDC); // Create GDI+ graphics context
mGame.OnDraw(&graphics);
// TODO: Add your message handler code here
// Do not call CWnd::OnPaint() for painting messages
if (mFirstDraw)
{
mFirstDraw = false;
SetTimer(1, FrameDuration, nullptr);
/*
* Initialize the elapsed time system
*/
LARGE_INTEGER time, freq;
QueryPerformanceCounter(&time);
QueryPerformanceFrequency(&freq);
mLastTime = time.QuadPart;
mTimeFreq = double(freq.QuadPart);
}
/*
* Compute the elapsed time since the last draw
*/
LARGE_INTEGER time;
QueryPerformanceCounter(&time);
long long diff = time.QuadPart - mLastTime;
double elapsed = double(diff) / mTimeFreq;
mLastTime = time.QuadPart;
mGame.Update(elapsed);
}
To handle collisions of the objects, a function calls a function called Update() on a CGame object which uses the following code to check if a collision happened.
/** Handle updates for animation
* \param elapsed The time since the last update
*/
void CGame::Update(double elapsed)
{
// Collisions of balls
for (shared_ptr<CBall> ball1 : this->GetBalls())
{
for (shared_ptr<CBall> ball2 : this->GetBalls())
{
double centerXBall1 = ball1->GetX() + ball1->GetDiameter() / 2;
double centerYBall1 = ball1->GetY() + ball1->GetDiameter() / 2;
double centerXBall2 = ball2->GetX() + ball2->GetDiameter() / 2;
double centerYBall2 = ball2->GetY() + ball2->GetDiameter() / 2;
double distance = sqrt((pow((centerXBall2 - centerXBall1), 2) +
pow((centerYBall2 - centerYBall1), 2)));
if (ball1 != ball2 && (distance <= ball1->GetDiameter() || distance <= ball2->GetDiameter()))
{
// The slope of the line that passes through the center of both
// balls
double slopeThroughCenters =
(centerYBall2 - centerYBall1) / (centerXBall2 -
centerXBall1);
// The angle between a vertical and the deflection direction of
// ball 1
double angleOfVelocity1 = 0.0;
// The angle between a horizontal line and the deflection
// direction of ball 2
double angleOfVelocity2 = 0.0;
double complimentaryAngle = atan(slopeThroughCenters);
if (centerXBall1 > centerXBall2 && centerYBall1 > centerYBall2)
{
angleOfVelocity1 = PI / 2 - complimentaryAngle;
angleOfVelocity2 = (PI / 2 - complimentaryAngle) + PI / 2;
}
double initialVelocityBall1 = sqrt(pow(ball1->GetVelocityX(), 2) +
pow(ball1->GetVelocityY(), 2));
double initialVelocityBall2 = sqrt(pow(ball2->GetVelocityX(), 2) +
pow(ball2->GetVelocityY(), 2));
double finalVelocityBall1 = ((ball1->GetMass() - ball2->GetMass()) * initialVelocityBall1) /
(ball1->GetMass() + ball2->GetMass());
double finalVelocityBall2 = (2 * ball1->GetMass() * initialVelocityBall1) /
(ball1->GetMass() + ball2->GetMass());
double velocityXBall1 = finalVelocityBall2 * cos(angleOfVelocity1);
double velocityYBall1 = finalVelocityBall2 * sin(angleOfVelocity1);
double velocityXBall2 = finalVelocityBall2 * cos(angleOfVelocity2);
double velocityYBall2 = finalVelocityBall2 * sin(angleOfVelocity2);
ball1->SetVelocityX(velocityXBall1);
ball1->SetVelocityY(velocityYBall1);
ball2->SetVelocityX(velocityXBall2);
ball2->SetVelocityY(velocityYBall2);
}
}
}
for (auto ball : this->mBalls)
{
ball->Update(elapsed);
}
}
When I run the debugger, the if block:
if (centerXBall1 > centerXBall2 && centerYBall1 > centerYBall2)
{
angleOfVelocity1 = PI / 2 - complimentaryAngle;
angleOfVelocity2 = PI - complimentaryAngle;
}
Doesn't seem to be executed, however, if I change the variable's values, for example,
angleOfVelocity1 = PI;
angleOfVelocity2 = PI;
My program actually changes according to the values of those variables. How is this possible if the debugger shows that the if block isn't executed in the first place?
Sorry if my code isn't minimalistic and concise enough, but I did not want to leave out anything important for solving this problem.

Related

C++ / SDL2 - Ball bouncing/glitching together

I was trying to write some ball bouncing program in C++ using SDL2. I had a hard time getting the velocity exchange correct, but it works pretty neat so far. The only problem I have right now is that the balls are sometimes glitching/stucking together and after some seconds they release themself again.
That is my update() function which gets called every frame:
void Game::update() {
updateFPS();
checkBallCollision();
updateCanCollide();
int newtime = SDL_GetTicks();
int diff = newtime - lasttime;
if (diff > 10)
diff = 10;
for (Ball *ball : balls) {
ball->x = ball->x + ball->velocity->x * (float) diff / 100;
ball->y = ball->y + ball->velocity->y * (float) diff / 100;
checkBorderCollision(ball);
}
lasttime = newtime;
}
I guess that the balls are getting to close and don't bounce at the border of the balls. Therefore I tried to give every ball a boolean canCollide which is always true except a ball is colliding. Then it stays false until the two balls aren't overlapping anymore.
Here are my checkBallCollision() and updateCanCollide() functions:`
void Game::updateCanCollide() {
Ball **ballArr = &balls[0];
int length = balls.size();
for (int i = 0; i < length; i++) {
if (ballArr[i]->canCollide)
continue;
bool updatedCollide = true;
for (int k = i + 1; k < length; k++) {
Ball *ball1 = ballArr[i];
Ball *ball2 = ballArr[k];
int xdiff = abs(ball1->x - ball2->x);
int ydiff = abs(ball1->y - ball2->y);
float distance = sqrt(xdiff * xdiff + ydiff * ydiff);
if (distance <= ball1->radius + ball2->radius) {
updatedCollide = false;
}
}
ballArr[i]->canCollide = updatedCollide;
}
}
// do all collision checks and update the velocity
void Game::checkBallCollision() {
Ball **ballArr = &balls[0];
int length = balls.size();
for (int i = 0; i < length; i++) {
if (!ballArr[i]->canCollide)
continue;
for (int k = i + 1; k < length; k++) {
if (!ballArr[k]->canCollide)
continue;
Ball *ball1 = ballArr[i];
Ball *ball2 = ballArr[k];
int xdiff = abs(ball1->x - ball2->x);
int ydiff = abs(ball1->y - ball2->y);
float distance = sqrt(xdiff * xdiff + ydiff * ydiff);
if (distance <= ball1->radius + ball2->radius) {
// ball1 and ball2 are colliding
// update the velocity of both balls
float m1 = ball1->radius * ball1->radius * 3.14159;
float m2 = ball2->radius * ball2->radius * 3.14159;
Vector2D *v1 = new Vector2D(ball1->velocity->x, ball1->velocity->x);
Vector2D *v2 = new Vector2D(ball2->velocity->x, ball2->velocity->x);
ball1->velocity->x = ((v1->x * (m1 - m2) + 2 * m2 * v2->x) / (m1 + m2));
ball1->velocity->y = ((v1->y * (m1 - m2) + 2 * m2 * v2->y) / (m1 + m2));
ball2->velocity->x = ((v2->x * (m2 - m1) + 2 * m1 * v1->x) / (m1 + m2));
ball2->velocity->y = ((v2->y * (m2 - m1) + 2 * m1 * v1->y) / (m1 + m2));
ball1->canCollide = false;
ball2->canCollide = false;
}
}
}
}
The proper fix
The main problem is that you are letting the balls overlap each other, then update their velocities. However, if the next time step is shorter than the previous one, it can be that after updating their positions, they are still overlapping. Then you think they are colliding again, and update their velocities, but this will most likely cause then to move closer together again. This explains why they get stuck.
The proper wait to solve this is to calculate the exact point in time that two moving balls collide. This can be done analytically, for example by treating time as a third dimension, and then calculating a line-sphere intersection. If this happens during the time step, you advance the time up to the point that the collision happens, then update the velocities, and then perform the rest of the step. If you have more than two balls, then be aware that you can have more than two balls colliding all with each other in the same timestep. This is also solvable, just calculate all the time points that collisions happen, select the earliest one, update velocities at that point, and then recalculate the collision times, and so on until there are no collisions in the time step.
The workaround
Your workaround might fix two balls sticking to each other, but the result is not physically accurate. It breaks down when you start increasing the density of balls, since at some point the chance will be very high that at least one ball of a pair that should collide was in a collision in the previous timestep, and then they will all just start passing through each other all the time.
Another issue is that you have to check every possible pair of balls in updateCanCollide(), which is not efficient. There is a simpler and more common workaround to this problem: when two balls collide, after updating their velocities, immediately update their positions as well such that the balls are no longer colliding. You can try to calculate exactly how much to move them so they no longer overlap, or if you don't want to involve mathematics, you can just have a while loop to do a small step until they no longer overlap.
Other issues in your code
Note that there are also some other thing in your code that you could improve:
Don't new a temporary Vector2D, just declare it on the stack. If for some reason this is not possible, at least delete v1 and v2 afterwards.
You don't need to call abs() if you are going to square the result anyway.
Use std::hypot() to calculate the distance.
Did you write Vector2D yourself or is it from a library? If the latter, maybe it already has functions to reflect two 2D vectors? If the former, consider using a library like GLM, even if you are not using OpenGL.
Use a proper value of π. A simple, portable solution is to declare static constexpr pi = std::atan(1) * 4.

A ball animation in simple harmonic motion using SDL2 and C++

I'm trying to emulate the following ball. Notice the simple harmonic motion of the ball, with the very ends of the ball bounce having a smaller velocity compared to the velocity in the middle:
I'm able to implement a bouncing ball, however it's not simple harmonic motion:
The corresponding code is as follows:
Dot::Dot() {
//Initialize the offsets
mPosX = 300;
mPosY = 0;
//Initialize the velocity
mVelX = 0;
mVelY = 4;
}
void Dot::move() {
//Move the dot up or down
mPosY += mVelY;
//If the dot went too far up or down
if( ( mPosY < 0 ) || ( mPosY + DOT_HEIGHT > SCREEN_HEIGHT ) )
{
//Move back
mVelY = -mVelY;
}
}
I have a simple harmonic motion model, like so:
The corresponding code is as follows:
Dot::Dot() {
//Initialize the offsets
mPosX = 300;
mPosY = 0;
//Initialize the velocity
mVelX = 0;
mVelY = 0;
}
void Dot::move() {
time_t current_time;
current_time = time(NULL);
mPosY = int(((460) - 10) * sin(2.4 * 2 * 3.141592 / 60 * current_time + (SCREEN_HEIGHT / 2)
));
//const int SCREEN_HEIGHT = 480
}
The issues with this implementation are that:
(1). the ball image appears every now and then, rather than continuously like in the blue ball model I tried to emulate at the very beginning
(2). the ball goes well beyond the top frame of the window, rather than slowing down at the very top of the window, again like the blue ball model.
For (2), I understand that I need to add a phase shift, i.e x in A*sin(wt + x), however changing this value doesn't do anything to prevent the ball from disappearing at the top of the window.
Any ideas on how to solve these issues?
Edit: I was able to solve (1) by doing += to mPosY rather than =, such as:
mPosY += int(4 * cos(2.4 * 2 * 3.141592 / 60 * current_time + (SCREEN_HEIGHT / 2) ));
However, I'm still unable to get the ball to bounce up and down within the frame of the window I created.
I recommend using actual simple harmonic equations.
For example, if your display dimensions are (500, 500), the center Y is 250. from there say your equation is in the form of x = acos(nt + m) + c where x is displacement (meters), a is amplitude n is for the period, for example the period (T) = 2PI/n t is time (seconds) and m is for phase shift and c is for the center. That way when you need the velocity of the object, you have a function that follows along the lines of
double Velocity(double time){
double vel = derivative_of_displacement_equation(time);
return vel;
}
And so in the program, you adjust the equation to suit the display dimensions, then you set the objects X/Y coordinates as the value returned from the displacement equation (PLUS THE CENTER OFFSET, in this example, if the center is at the middle of the screen, you would set the Y coordinate to the equation PLUS 250). Keep in mind coordinates begin at (0,0) so your displacement equation (at least the part where it involves the proportional factor, which in this case is time), you make that negative instead.
Here is some code that I believe answers your question:
#include <SDL2/SDL.h>
#include <chrono>
#include <math.h>
#include <iostream>
const double PI = 3.14159265358979;
void draw_circle(SDL_Renderer *renderer, int x, int y, int radius, SDL_Color color)
{
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
for (int w = 0; w < radius * 2; w++)
{
for (int h = 0; h < radius * 2; h++)
{
int dx = radius - w; // horizontal offset
int dy = radius - h; // vertical offset
if ((dx*dx + dy*dy) <= (radius * radius))
{
SDL_RenderDrawPoint(renderer, x + dx, y + dy);
}
}
}
}
double Displacement(double time, double a, double n, double m, double c)
{
double displacement = a*cos(n*time + m) + c;
return displacement;
}
int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window = SDL_CreateWindow("SHM", 0, 30, 500, 500, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);// | SDL_WINDOW_SHOWN);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED );
double timeDifference;
std::chrono::steady_clock::time_point start, finish;
start = std::chrono::steady_clock::now();
finish = start;
SDL_Event event;
bool running = true;
while (running){
while (SDL_PollEvent(&event)){
if (event.type == SDL_QUIT){
running = false;
break;
}
}
SDL_SetRenderDrawColor(renderer, 255,255,255,255);
SDL_RenderClear(renderer);
finish = std::chrono::steady_clock::now();
timeDifference = std::chrono::duration_cast<std::chrono::nanoseconds>(finish - start).count();
timeDifference = timeDifference / 1000000000;
///The "-(250-20) is the center y (250) minus the radius of the circle (20), and its - out the front as negative a due to coordinates
double yPosition = round( Displacement(timeDifference, -(250-20), 2, 0, 250 ) );
draw_circle(renderer, 250, yPosition, 20, {255,0,0});
SDL_RenderPresent(renderer);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
In general you have a0 + a/2*cos (2*𝝥*t/T + 𝝫) where a0 is the vertical position of the half of the vertical travel, a is the height of the travel, t is time, T the period ie., the time to do a complete cycle for going and coming back to the same state or uple { position, momentum }, and 𝝫 the time shift, ie., the moment where the height is at zero of the cos.
So if you want the ball to be on the floor at t=0, you want cos at the minimum, ie., 𝝫 = -𝝥/2.
You want to manage your position in function of your game's time t, so you can decouple the time to compute (which depend on your compute calpabilities) and the game's time (that you want constant from a machine to another).
Therefore you want:
auto VerticalPosition(double t)
-> double { return CorrectedScreenHeight/2*(1 + cos(2*PI*t/T + phi)); }
And you define CorrectedScreenHeight = SCREEN_HEIGHT - DOT_HEIGHT, T and phi outside, as properties of your system.
Between two consecutive images, you increment t, in order to have the correct experienced time. Typically you have 60 images/s (WPF, DirectX, web, etc), hence a period of 1.0/60s between consecutive images, this goes in your function that modifies t. The speed of your ball then depend on T, that you can tune independently.

Repulsion Vector

I am trying to implement a basic AI for a Turrets game in SFML and C++ and I have some problems.
This AI follows some waypoints stablished in a Bezier Courve.
In first place, this path was followed only by one enemy. For this purpose, the enemy has to calculate his distance between his actual position
to the next waypoint he has to pick.
If the distance is less than a specific value we stablish, then, we get to the next point. This will repeat until the final destination is reached. (in the submitting code, forget about the var m_go)
Okay, our problem gets when we spawn several enemies and all have to follow the same path, because it produces a bad visual effect (everyone gets upside another).
In order to solve this visual problem, we have decided to use a repulsion vector. The calculus gets like this: representation of what we want
As you can see, we calculate the repulsion vector with the inverse of the distance between the enemy and his nearest neighbor.
Then, we get it applying this to the "theorical" direction, by adding it, and we get a resultant, which is the direction that
our enemy has to follow to not "collide" with it's neighbors.
But, our issue comes here:
The enemys get sepparated in the middle of the curve and, as we spawn more enemys, the speed of all of them increases dramatically (including the enemies that don't calculate the repuslion vector).
1 - Is it usual that this sepparation occours in the middle of the trajectory?
2 - Is it there a way to control this direction without the speed getting affected?
3 - Is it there any alternative to this theory?
I submit the code below (There is a variable in Spanish [resultante] which it means resultant in English):
if (!m_pathCompleted) {
if (m_currentWP == 14 && m_cambio == true) {
m_currentWP = 0;
m_path = m_pathA;
m_cambio = false;
}
if (m_neighbors.size() > 1) {
for (int i = 0; i < m_neighbors.size(); i++) {
if (m_enemyId != m_neighbors[i]->GetId()) {
float l_nvx = m_neighbors[i]->GetSprite().getPosition().x - m_enemySprite.getPosition().x;
float l_nvy = m_neighbors[i]->GetSprite().getPosition().y - m_enemySprite.getPosition().y;
float distance = std::sqrt(l_nvx * l_nvx + l_nvy * l_nvy);
if (distance < MINIMUM_NEIGHBOR_DISTANCE) {
l_nvx *= -1;
l_nvy *= -1;
float l_vx = m_path[m_currentWP].x - m_enemySprite.getPosition().x;
float l_vy = m_path[m_currentWP].y - m_enemySprite.getPosition().y;
float l_resultanteX = l_nvx + l_vx;
float l_resultanteY = l_nvy + l_vy;
float l_waypointDistance = std::sqrt(l_resultanteX * l_resultanteX + l_resultanteY * l_resultanteY);
if (l_waypointDistance < MINIMUM_WAYPOINT_DISTANCE) {
if (m_currentWP == m_path.size() - 1) {
std::cout << "\n";
std::cout << "[GAME OVER]" << std::endl;
m_go = false;
m_pathCompleted = true;
} else {
m_currentWP++;
}
}
if (l_waypointDistance > MINIMUM_WAYPOINT_DISTANCE) {
l_resultanteX = l_resultanteX / l_waypointDistance;
l_resultanteY = l_resultanteY / l_waypointDistance;
m_enemySprite.move(ENEMY_SPEED * l_resultanteX * dt, ENEMY_SPEED * l_resultanteY * dt);
}
} else {
float vx = m_path[m_currentWP].x - m_enemySprite.getPosition().x;
float vy = m_path[m_currentWP].y - m_enemySprite.getPosition().y;
float len = std::sqrt(vx * vx + vy * vy);
if (len < MINIMUM_WAYPOINT_DISTANCE) {
if (m_currentWP == m_path.size() - 1) {
std::cout << "\n";
std::cout << "[GAME OVER]" << std::endl;
m_go = false;
m_pathCompleted = true;
} else {
m_currentWP++;
}
}
if (len > MINIMUM_WAYPOINT_DISTANCE) {
vx = vx / len;
vy = vy / len;
m_enemySprite.move(ENEMY_SPEED * vx * dt, ENEMY_SPEED * vy * dt);
}
}
}
}
} else {
float vx = m_path[m_currentWP].x - m_enemySprite.getPosition().x;
float vy = m_path[m_currentWP].y - m_enemySprite.getPosition().y;
float len = std::sqrt(vx * vx + vy * vy);
if (len < MINIMUM_WAYPOINT_DISTANCE) {
if (m_currentWP == m_path.size() - 1) {
std::cout << "\n";
std::cout << "[GAME OVER]" << std::endl;
m_go = false;
m_pathCompleted = true;
} else {
m_currentWP++;
}
}
if (len > MINIMUM_WAYPOINT_DISTANCE) {
vx = vx / len;
vy = vy / len;
m_enemySprite.move(ENEMY_SPEED * vx * dt, ENEMY_SPEED * vy * dt);
}
}
}
I will try to answer your questions one by one, but first, I don't see anything terribly wrong in the code, so it could be simply a set of non contemplated situations.
1 - Is it usual that this sepparation occours in the middle of the
trajectory?
Well, you're applying repulsion forces to every enemy based on distance of near enough others. If something weird happens or if you're moving them more than necessary, could result on a considerable deviation from their original trajectory.
2 - Is it there a way to control this direction without the speed
getting affected?
In this line
m_enemySprite.move(ENEMY_SPEED * l_resultanteX * dt, ENEMY_SPEED * l_resultanteY * dt);
we see you're, in fact, applying that repulsion force based on l_resultante vector. That vector depends directly on l_nv (repulsion vector), which its module (or length) is proportional to the distance between this (enemy you are processing now) and other (the neighbor). As you're multiplying this vector by the speed of the enemy (a constant value), greater the distance, greater the force applied and more separation will be between them.
I suggest you to:
Normalize the vector l_nv (Easier): This is, force it to have module 1. With this solution every enemy will be pushed with the same force (basically ENEMY_SPEED) but in proper direction.
Inverse the vector l_nv (Little harder): If you apply this vector inversely proportional to the distance (module = 1/distance), they will behave the opposite and they will be pushed less if they are farther from each other.
Also consider that you are applying forces consecutively and you're making them effective by every neighbor processed. This implies something undesirable. If you push an enemy, this force could move it into a location where a future enemy (in the for loop) could push it maybe more than before. If this effect concatenates several times, could trigger a chain reaction where your enemy is pushed more and more. This effect will be amplified if you're applying the forces proportional to the distance.
3 - Is it there any alternative to this theory?
I actually run out of ideas, but I left this space here if someone want to edit the answer and suggest something

Updating time and position using GetTickCount() in C++

Problem: I am attempting to update time using getTickCount without avail.
Situation: I currently obtain the timedifference using getTickCount and pass it into world update method parameters. However within the update method where I update the position, a large value is passed in (even though I have divided by 1000) and so the position adds an odd 4000 to the position vector.
Code below:
Simulation.CPP:
int Simulation::simControlLogic(HWND hWnd, keyEvent event)
{
/* TO DO: add relevant code */
if (event != QUIT)
{
previousTime = 0;
frameStartTime = GetTickCount();
if (previousTime == 0)
previousTime = frameStartTime;
timeDifference = (frameStartTime - previousTime) / 1000.0f; // this generates the difference between the last and current time
world.update(event, &graphics, timeDifference); // update parameters of virtual world
gameLoopDelay(frameStartTime);
simDisplayFrame(hWnd); // display frame
previousTime = frameStartTime; //the current time is set to the previous time for the next loop step
}
return 1;
}
looking into the world Update method:
int WorldData::update(keyEvent kEvent, GraphicsM * pGraphicsModule, float timeStep)
{
//updates the particle
for (int i = 0; i < 3; i++)
{
particles[i].Update(kEvent, pGraphicsModule, timeStep);
}
return 1;
}
looking into particles Update method:
void ParticleModel::Update(keyEvent kEvent, GraphicsM * pGraphicsModule, float timeStep)
{
move(timeStep);
}
looking into move method:
void ParticleModel::move(float timeStep)
{
velocity.y = 0.5F;
velocity.x = 0.5F;
acceleration.x = 0.0F;
acceleration.y = 0.0F;
pos.x += velocity.x * timeStep; //here is the problem. I get a large value e.g 79637.1788 causing pos.x to be ridiculously large
pos.y += velocity.y * timeStep; //here is the problem. I get a large value e.g 79637.1788 causing pos.y to be ridiculously large
}
After moving previousTime to the simulator constructor initializing it to 0, it worked. Thanks for replies

For an Arduino Sketch based light meter, functions outside of 'loop' are not being set off/firing

I'm very new to Arduino. I have much more experience with Java and ActionScript 3. I'm working on building a light meter out of an Arduino Uno and a TAOS TSL235R light-to-frequency converter.
I can only find a tuturial using a different sensor, so I am working my way through converting what I need to get it all to work (AKA some copy and paste, shamefully, but I'm new to this).
There are three parts: this is the first tutorial of the series Arduino and the Taos TSL230R Light Sensor: Getting Started.
The photographic conversion: Arduino and the TSL230R: Photographic Conversions.
At first, I could return values for the frequency created by the TSL235R sensor, but once I tried to add the code for photographic conversions I only get zero returned, and none of the funcions outside of the main loop seem to fire being that my Serial.Println() doesn't return anything.
I am more concerned with making the functions fire than if my math is perfect. In ActionScript and Java there are event listeners for functions and such, do I need to declare the function for it to fire in C/C++?
Basically, how can I make sure all my functions fire in the C programming language?
My Arduino Sketch:
// TSL230R Pin Definitions
#define TSL_FREQ_PIN 2
// Our pulse counter for our interrupt
unsigned long pulse_cnt = 0;
// How often to calculate frequency
// 1000 ms = 1 second
#define READ_TM 1000
// Two variables used to track time
unsigned long cur_tm = millis();
unsigned long pre_tm = cur_tm;
// We'll need to access the amount of time passed
unsigned int tm_diff = 0;
unsigned long frequency;
unsigned long freq;
float lux;
float Bv;
float Sv;
// Set our frequency multiplier to a default of 1
// which maps to output frequency scaling of 100x.
int freq_mult = 100;
// We need to measure what to divide the frequency by:
// 1x sensitivity = 10,
// 10x sensitivity = 100,
// 100x sensitivity = 1000
int calc_sensitivity = 10;
void setup() {
attachInterrupt(0, add_pulse, RISING); // Attach interrupt to pin2.
pinMode(TSL_FREQ_PIN, INPUT); //Send output pin to Arduino
Serial.begin(9600); //Start the serial connection with the copmuter.
}//setup
void loop(){
// Check the value of the light sensor every READ_TM ms and
// calculate how much time has passed.
pre_tm = cur_tm;
cur_tm = millis();
if( cur_tm > pre_tm ) {
tm_diff += cur_tm - pre_tm;
}
else
if( cur_tm < pre_tm ) {
// Handle overflow and rollover (Arduino 011)
tm_diff += ( cur_tm + ( 34359737 - pre_tm ));
}
// If enough time has passed to do a new reading...
if (tm_diff >= READ_TM ) {
// Reset the ms counter
tm_diff = 0;
// Get our current frequency reading
frequency = get_tsl_freq();
// Calculate radiant energy
float uw_cm2 = calc_uwatt_cm2( frequency );
// Calculate illuminance
float lux = calc_lux_single( uw_cm2, 0.175 );
}
Serial.println(freq);
delay(1000);
} //Loop
unsigned long get_tsl_freq() {
// We have to scale out the frequency --
// Scaling on the TSL230R requires us to multiply by a factor
// to get actual frequency.
unsigned long freq = pulse_cnt * 100;
// Reset pulse counter
pulse_cnt = 0;
return(freq);
Serial.println("freq");
} //get_tsl_freq
void add_pulse() {
// Increase pulse count
pulse_cnt++;
return;
Serial.println("Pulse");
}//pulse
float calc_lux_single(float uw_cm2, float efficiency) {
// Calculate lux (lm/m^2), using standard formula
// Xv = Xl * V(l) * Km
// where Xl is W/m^2 (calculate actual received uW/cm^2, extrapolate from sensor size
// to whole cm size, then convert uW to W),
// V(l) = efficiency function (provided via argument) and
// Km = constant, lm/W # 555 nm = 683 (555 nm has efficiency function of nearly 1.0).
//
// Only a single wavelength is calculated - you'd better make sure that your
// source is of a single wavelength... Otherwise, you should be using
// calc_lux_gauss() for multiple wavelengths.
// Convert to w_m2
float w_m2 = (uw_cm2 / (float) 1000000) * (float) 100;
// Calculate lux
float lux = w_m2 * efficiency * (float) 683;
return(lux);
Serial.println("Get lux");
} //lux_single
float calc_uwatt_cm2(unsigned long freq) {
// Get uW observed - assume 640 nm wavelength.
// Note the divide-by factor of ten -
// maps to a sensitivity of 1x.
float uw_cm2 = (float) freq / (float) 10;
// Extrapolate into the entire cm2 area
uw_cm2 *= ( (float) 1 / (float) 0.0136 );
return(uw_cm2);
Serial.println("Get uw_cm2");
} //calc_uwatt
float calc_ev( float lux, int iso ) {
// Calculate EV using the APEX method:
//
// Ev = Av + Tv = Bv + Sv
//
// We'll use the right-hand side for this operation:
//
// Bv = log2( B/NK )
// Sv = log2( NSx )
float Sv = log( (float) 0.3 * (float) iso ) / log(2);
float Bv = log( lux / ( (float) 0.3 * (float) 14 ) ) / log(2);
return( Bv + Sv );
Serial.println("get Bv+Sv");
}
float calc_exp_tm ( float ev, float aperture ) {
// Ev = Av + Tv = Bv + Sv
// need to determine Tv value, so Ev - Av = Tv
// Av = log2(Aperture^2)
// Tv = log2( 1/T ) = log2(T) = 2^(Ev - Av)
float exp_tm = ev - ( log( pow(aperture, 2) ) / log(2) );
float exp_log = pow(2, exp_tm);
return( exp_log );
Serial.println("get exp_log");
}
unsigned int calc_exp_ms( float exp_tm ) {
unsigned int cur_exp_tm = 0;
// Calculate mS of exposure, given a divisor exposure time.
if (exp_tm >= 2 ) {
// Deal with times less than or equal to half a second
if (exp_tm >= (float) int(exp_tm) + (float) 0.5 ) {
// Round up
exp_tm = int(exp_tm) + 1;
}
else {
// Round down
exp_tm = int(exp_tm);
}
cur_exp_tm = 1000 / exp_tm;
}
else if( exp_tm >= 1 ) {
// Deal with times larger than 1/2 second
float disp_v = 1 / exp_tm;
// Get first significant digit
disp_v = int( disp_v * 10 );
cur_exp_tm = ( 1000 * disp_v ) / 10;
}
else {
// Times larger than 1 second
int disp_v = int( (float) 1 / exp_tm);
cur_exp_tm = 1000 * disp_v;
}
return(cur_exp_tm);
Serial.println("get cur_exp_tm");
}
float calc_exp_aperture( float ev, float exp_tm ) {
float exp_apt = ev - ( log( (float) 1 / exp_tm ) / log(2) );
float apt_log = pow(2, exp_apt);
return( apt_log );
Serial.println("get apt_log");
}
That is a lot of code to read, where should I start.
In your loop() you are assigning frequency but printing freq
// get our current frequency reading
frequency = get_tsl_freq();
-- snip --
Serial.println(freq);
in get_tsl_freq() you are creating a local unsigned int freq that hides the global freq and using that for calculation and returning the value, maybe that is also a source of confusion for you. I do not see a reason for frequency and freq to be globals in this code. The function also contains unreachable code, the control will leave the function on return, statements after the return will never be executed.
unsigned long get_tsl_freq() {
unsigned long freq = pulse_cnt * 100; <-- hides global variable freq
// re-set pulse counter
pulse_cnt = 0;
return(freq); <-- ( ) not needed
Serial.println("freq"); <-- Unreachable
}
Reading a bit more I can suggest you pick up a C++ book and read a bit. While your code compiles it is not technically valid C++, you get away with it thanks to the Arduino software that does some mangling and what not to allow using functions before they are declared.
On constants you use in your calculations
float w_m2 = (uw_cm2 / (float) 1000000) * (float) 100;
could be written as
float w_m2 = (uw_cm2 / 1000000.0f) * 100.0f;
or even like this because uw_cm2 is a float
float w_m2 = (uw_cm2 / 1000000) * 100;
You also seem to take both approaches to waiting, you have code that calculates and only runs if it has been more than 1000 msec since it was last run, but then you also delay(1000) in the same code, this may not work as expected at all.