I'm new to C++ and trying to make a simple update function.
I have built a "clock" which tracks time between frames as well as time since T0.
I also have a loops which every so many "clock" frames calls an update function.
void Engine::start()
{
float count = 0;
Clock clock;
clock.startClock();
while (true)
{
clock.Time(.001F);
count += clock.deltaTime();
if (count >= 1000) {
update(clock.deltaTime());
count = 0;
}
}
}
However this feels inelegant to me.
The clock code:
class Clock
{
private:
public:
float startTime=0;
float nextTime=0;
float currentTime=0;
void startClock()
{
float startTime = 0;
float currentTime = startTime;
}
float deltaTime()
{
return nextTime - currentTime;
}
void Time(float incrementTime)
{
currentTime = 0;
nextTime = incrementTime;
}
};
It works as written; I have a "counter" class which prints to the console every time the update function is called; however I'd like advice on how to improve this, to make it more elegant/efficient.
Related
I have recently bought an Arduino which uses C++ to code on. I am familiar with Java and as C++ allows OO programming I didn't think it would have been that difficult. But...
CODE:
// LEDCLOCK CLASS /////////////////////////////////////////////////////////////////////////
class LedClock{
private:
int hours;
int minutes;
int seconds;
static const long secondInterval = 1000;
unsigned long previousMilliseconds;
unsigned long currentMilliseconds;
public:
LedClock(){
hours = 0;
minutes = 0;
seconds = 0;
previousMilliseconds = 0;
currentMilliseconds = 0;
};
int getHours(){
return hours;
};
int getMinutes(){
return minutes;
};
int getSeconds(){
return seconds;
};
long getSecondInterval(){
return secondInterval;
};
unsigned long getPreviousMilliseconds(){
return previousMilliseconds;
};
void setHours(int h){
if(h < 24 && h >= 0){
hours = h;
}else{
hours = 0;
}
};
void setMinutes(int m){
if(m < 60 && m > 0){
minutes = m;
}else{
minutes = 0;
}
};
void setSeconds(int s){
if(s < 60 && s > 0){
seconds = s;
}else{
seconds = 0;
}
};
void setPreviousMilliseconds(unsigned long ms){
previousMilliseconds = ms;
};
void increaseOneHour(){
// as there is no day counter to increment atm this if-else statement is a bit useless.
// setHour(getHours() + 1) would have sufficed here with the current setter
if(getHours()==23){
setHours(0);
}else{
setHours(getHours() + 1);
}
};
void increaseOneMinute(){
if(getMinutes() == 59){
increaseOneHour();
setMinutes(0);
}else{
setMinutes(getMinutes() + 1);
}
};
void increaseOneSecond(){
if(getSeconds() == 59){
increaseOneMinute();
setSeconds(0);
}else{
setSeconds(getSeconds() + 1);
}
};
void tick(){
currentMilliseconds = millis();
if(currentMilliseconds - getPreviousMilliseconds() >= getSecondInterval()){
setPreviousMilliseconds(currentMilliseconds);
increaseOneSecond();
}
};
};
// LEDCLOCKCONTROLLER CLASS ////////////////////////////////////////////////////////////////
class LedClockController{
private:
LedClock ledClock;
int mode = 2;
public:
LedClockController(LedClock lc){
ledClock = lc;
};
LedClock getLedClock(){
return ledClock;
};
int getMode(){
return mode;
};
void setMode(int newMode){
mode = newMode;
};
};
// ARDUINO CODE /////////////////////////////////////////////////////////////////////////
LedClock lc = LedClock();
LedClockController lcc(lc);
void setup() {
Serial.begin(9600); //Begin serializer to print out value
}
void loop() {
//doesn't give me updated values
if(lcc.getLedClock().getPreviousMilliseconds()<63000){
Serial.println(lcc.getLedClock().getSeconds());
lcc.getLedClock().tick();
}
//does give me updated values
//commented out for now
/*
if(lc.getPreviousMilliseconds()<63000){
Serial.println(lc.getSeconds());
lc.tick();
}
*/
}
Q1:
I have difficulties to update attributes of my LedClock attribute in my Controller class.
When I target the LedClock by itself, everything runs fine but when I would update it via the Controller, then it wouldn't. In short, when getting the seconds in the first case, I could see the increment in values in the output. When I did the same thing but via the controller, the seconds stayed 0.
So I am missing something vital here. Can someone help/explain what I am missing?
Q2: Ideally I would want to create the LedClock object inside the constructor but didn't seem to find how to.
I tried things that could make sense but with the issues I have been having, I was holding off on this:
LedClockController lcc(LedClock lc());
LedClockController lcc(LedClock);
//would make sense to me, I noticed C++ doesn't use the 'new' keyword so have no idea how to do that then
LedClockController lcc(LedClock());
All of those ran into compilation issues so probably another important C++ thing that I haven't taken into account.
P.S. I have been noticing that there are some different views on getter and setters (accessing the attributes directly vs actual functions). I have been using the method I am used to (and were mentioned on W3schools) because I will rely on setting logic in 1 place.
I had to create timelapse function to wait for X amount of time in a loop.
The following code checks the boolean value of m_abortTimeLapseThread but after running for an hour I noticed the execution time of this code created 10 seconds delay. Is there a way to check m_abortTimeLapseThread as frequently as possible and wait for X amount of time in the function without the kind of delay I observed ?
void Acquisition::TimeLapseCount() {
int max10msWaitTimes = m_timeLapseInMs / 10;
while (true) {
m_timeLapseImageSaved = true;
for (int i = 0; i < max10msWaitTimes; i++)
{
if (m_abortTimeLapseThread) {
return;
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
}
Thanks,
You could measure total time elapsed.
void Acquisition::TimeLapseCount() {
auto waitUntil = std::chrono::system_clock::now() + std::chrono::milliseconds(m_timeLapseInMs);
while (true) {
m_timeLapseImageSaved = true;
while (waitUntil > std::chrono::system_clock::now())
{
if (m_abortTimeLapseThread) {
return;
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
waitUntil += std::chrono::milliseconds(m_timeLapseInMs);
}
}
I keep getting unresolved externals when I try to run this code in Visual Studio.
Structure Time Assignment for College
Create a structure called Time that has members days, hours, minutes,
and seconds as ints.
Create an instance of Time and initialize the members.
Create a function to normalize the time when values are added to it.
For example, after adding values to the hours, call the normalize
function which should see if the hours > 24.
If so, add 1 to the days member and reset hours by subtracting 24
from the current value.
DO the same for minutes and seconds over 59.
Your main program should add values to hours, minutes and seconds and
after each, call the normalize function to properly set the values.
Output the members after each update. Assume hours use a 24-hour
clock.
#include <iostream>
using namespace std;
Struct time
{
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
};
void normalize();
int main()
{
int clockRepeating;
for (clockRepeating = 0; clockRepeating < 150; clockRepeating++)
{
normalize();
}
return 0;
}
void normalize(Time &timenormalize)
{
if (timenormalize.days > 31)
timenormalize.days = 1;
if (timenormalizehours > 24)
{
timenormalize.hours = 0;
timenormalize.days++;
}
if (timenormalize.minutes > 59)
{
timenormalize.minutes = 0;
timenormalize.hours++;
}
if (time normalize.seconds > 59)
{
timenormalize.seconds = 0;
timenormalize.minutes++;
cout << timenormalize.days, timenormalize.hours, timenormalize.minutes, timenormalize.seconds;
}
else
timenormalize.seconds++;
cout << timenormalize.days, timenormalize.hours, timenormalize.minutes,timenormalize.seconds;
The signature you declared for void normalize(); does not match the signature as it's defined in this file (void normalize(Time &timenormalize)).
Here's a fixed up version of your code. First the compilation errors:
changed Struct to struct: struct is a key word, must be lowercase;
changed Time to struct time in void normalize(..): symbols are case sensitive: Time isn't declared, but struct time is;
added missing . to if (timenormalizehours): if (timenormalize.hours);
added } to the end of the file (probably copy/paste error).
And then the linker error undefined reference to 'normalize':
change function declaration void normalize() to void normalize(struct time &): you declare the normalize function without parameters, but define it with one parameter.
And then finally the compilation error this introduces:
change the normalize(); call to normalize( mytime ); because it takes a paramter
and declare a local variable struct mytime to pass as the parameter.
#include <iostream>
using namespace std;
struct time
{
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
};
void normalize(struct time &);
int main()
{
int clockRepeating;
struct time mytime;
for (clockRepeating = 0; clockRepeating < 150; clockRepeating++)
{
normalize( mytime );
}
return 0;
}
void normalize(struct time &timenormalize)
{
if (timenormalize.days > 31)
timenormalize.days = 1;
if (timenormalize.hours > 24)
{
timenormalize.hours = 0;
timenormalize.days++;
}
if (timenormalize.minutes > 59)
{
timenormalize.minutes = 0;
timenormalize.hours++;
}
if (timenormalize.seconds > 59)
{
timenormalize.seconds = 0;
timenormalize.minutes++;
cout << timenormalize.days, timenormalize.hours, timenormalize.minutes, timenormalize.seconds;
}
else
timenormalize.seconds++;
cout << timenormalize.days, timenormalize.hours, timenormalize.minutes,timenormalize.seconds;
}
It prints a series of 0. Now it's up to you to put some values in struct time mytime. I hope this helps!
I'm trying to create a step sequencer in C++ that will eventually send out MIDI data. I created it by having a clock on its own thread that calculates the amount of time since the last beat, and if it is time for the next beat, it writes a piece of data to the console.
However, I find that no matter what I set the BPM to, I get messages at a rate that is obviously too slow. I can't seem to figure out why the timing on this thread is wrong, and it doesn't help that I'm not terribly familiar with how the std::chrono library works. Thoughts?
Code below:
#include <thread>
#include <mutex>
#include <chrono>
#include <vector>
#include <iostream>
class StepSequencer {
public:
StepSequencer();
~StepSequencer();
void run();
void setBeatsPerMinute(float bpm);
void addNote(int noteValue, int beatIndex);
void playNote(int beatIndex);
protected:
int mNumberOfBeatBins;
int mSequencerPlayhead;
float mBeatsPerMinute;
float mSecondsPerBeat;
std::vector<int> mBeatBins;
std::mutex mMutex;
std::thread mSequencerThread;
bool mRunSequencerThread;
std::chrono::time_point<std::chrono::system_clock> mLastBeatTime;
std::chrono::time_point<std::chrono::system_clock> mCurrentTime;
};
#include "stdafx.h"
#include "StepSequencer.h"
StepSequencer::StepSequencer() {
mNumberOfBeatBins = 16;
for(int i = 0; i < 16; i++) {
mBeatBins.push_back(0);
}
mBeatsPerMinute = 0;
mSecondsPerBeat = 1;
mLastBeatTime = std::chrono::system_clock::now();
mCurrentTime = std::chrono::system_clock::now();
mSequencerPlayhead = 0;
mRunSequencerThread = false;
mSequencerThread = std::thread(&StepSequencer::run, this);
}
StepSequencer::~StepSequencer() {
if(mSequencerThread.joinable()) {
mSequencerThread.join();
}
}
void StepSequencer::run() {
mRunSequencerThread = true;
while(mRunSequencerThread) {
mCurrentTime = std::chrono::system_clock::now();
mMutex.lock();
if (std::chrono::duration_cast<std::chrono::seconds>(mCurrentTime - mLastBeatTime).count() > mSecondsPerBeat) {
mSequencerPlayhead++;
mSequencerPlayhead = mSequencerPlayhead % mNumberOfBeatBins;
playNote(mSequencerPlayhead);
mLastBeatTime = std::chrono::system_clock::now();
}
mMutex.unlock();
this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
void StepSequencer::setBeatsPerMinute(float bpm) {
mMutex.lock();
mBeatsPerMinute = bpm;
if(mBeatsPerMinute > 0) {
mSecondsPerBeat = 60.0 / mBeatsPerMinute;
}
else {
mSecondsPerBeat = 1;
}
mMutex.unlock();
}
void StepSequencer::addNote(int noteValue, int beatIndex) {
mBeatBins[beatIndex] = noteValue;
}
void StepSequencer::playNote(int beatIndex) {
std::cout << mBeatBins[beatIndex] << std::endl;
}
std::chrono::seconds has a representation of 'A signed integral type of at least 35 bits'. So you are going to get a value of count() which increments only once per second, giving the option of 60,30,20,15,12, etc. beats per minute.
Work in milliseconds or use a custom duration which is backed by a floating point value instead.
I am trying to make a Clock with the timeGetTime function and some others. But I keep getting an exception error. I know mayby the quality of the program is not really good, but I was just trying to get it work. It's supposed to be a singleton. I hope you can help me!
// The Clock header file
// The Clock API for meassuring time.
#include<Windows.h>
#include<WinBase.h>
#include<MMSystem.h>
class cTime
{
private:
double m_Ns;
double m_Ms;
double m_S;
public:
// Set Values
void SetN(double N) {m_Ns = N;}
void SetM(double M) {m_Ns = M;}
void SetS(double S) {m_Ns = S;}
// Get Values
double GetN() {return m_Ns;}
double GetM() {return m_Ms;}
double GetS() {return m_S;}
// GetTime functions
//int GetDiffrenceNs();
//int GetDiffrenceMs();
//int GetDiffrenceS();
};
class cClock
{
private:
cTime m_CurrentTime; // CurrentTime object
static cClock* m_pClock; // Pointer to only instance
cTime m_LastTime; // LastTime object
bool m_PerformanceCounter; // Set to true if the performance counter is available
double m_Frequency; // Tells the frequenty of the PerformanceCounter. The value that the PerformanceCounter will increase each second.
double m_CounterTime; // The Counter of the PerformanceCounter.
double m_Trillingstijd; // How long one count of the performance counter will take.
public:
static cClock* GetClock();
cTime CurrentTime(); // Get the CurrentTime.
cTime LastTime(); // Get the LastTime.
// Virtual destructor.
virtual ~cClock();
protected:
// Protected constructor.
cClock();
};
// The clock cpp file
#include "Clock.h"
cClock* cClock::m_pClock = 0;
cClock* cClock::GetClock()
{
//BOOL perf_flag; // Timer Selection Flag
//double time_factor; // Time Scaling Factor
//LONGLONG last_time; // Previous timer value
//LONGLONG perf_cnt;
if (QueryPerformanceFrequency((LARGE_INTEGER *) &m_pClock->m_Frequency))
{
QueryPerformanceCounter((LARGE_INTEGER *) &m_pClock->m_CounterTime);
m_pClock->m_PerformanceCounter = true;
m_pClock->m_Trillingstijd=1.0/m_pClock->m_Frequency;
double LastedSeconds = m_pClock->m_CounterTime/m_pClock->m_Frequency;
m_pClock->m_LastTime.SetN(LastedSeconds*1000000);
m_pClock->m_LastTime.SetM(LastedSeconds*1000);
m_pClock->m_LastTime.SetS(LastedSeconds);
}
else
{
m_pClock->m_PerformanceCounter = false;
double LastedMiliseconds = timeGetTime();
m_pClock->m_LastTime.SetN(LastedMiliseconds*1000);
m_pClock->m_LastTime.SetM(LastedMiliseconds);
m_pClock->m_LastTime.SetS(LastedMiliseconds/1000);
}
return cClock::m_pClock;
}
cTime cClock::LastTime()
{
return m_LastTime;
}
cTime cClock::CurrentTime()
{
if(m_PerformanceCounter)
{
QueryPerformanceCounter((LARGE_INTEGER *) &m_CounterTime);
double LastedSeconds = m_CounterTime/m_Frequency;
m_CurrentTime.SetN(LastedSeconds*1000000);
m_CurrentTime.SetM(LastedSeconds*1000);
m_CurrentTime.SetS(LastedSeconds);
}
else
{
int LastedMiliseconds = timeGetTime();
m_CurrentTime.SetN(LastedMiliseconds*1000);
m_CurrentTime.SetM(LastedMiliseconds);
m_CurrentTime.SetS(LastedMiliseconds/1000);
}
m_LastTime = m_CurrentTime;
return m_CurrentTime;
}
This is my main, really simple but I just tried to get it to work but it doesn't...
#include "Clock.h"
#include<iostream>
using namespace std;
int main()
{
cClock* Clock = cClock::GetClock();
cTime Test = Clock->CurrentTime();
cout << Test.GetN();
cout << Test.GetM();
cout << Test.GetS();
int temp;
cin >> temp;
return 0;
}
It seems that the method cClock* cClock::GetClock() uses m_pClock without initializing it (it is still 0).
You are never creating an instance of cClock, just accessing a null pointer to one.
If you really think a singleton is a good idea, then cClock::GetClock() will have to create one if it doesn't already exist; along the lines of
cClock* cClock::GetClock()
{
if (!m_pClock) {
m_pClock = new cClock;
}
// remainder of function
return m_pClock;
}
Note that this isn't thread-safe, and also introduces a memory leak. Singletons are difficult to implement in C++, and best avoided unless there is a genuine reason for wanting one. I would move the logic of GetClock() into a public constructor, and allow client code to create and destroy clock objects as it sees fit.