-1

I'm trying to recreate a small tween engine so I can interpolate values, leds hue, saturation and brightness in a easy way.

I'm having trouble to reference the value to interpolate into my tween object. If you look at the very last block, you'll see what i'm trying to achieve.

I've poor knowledge in pointers and references and it's driving me mad. Thanks for your help !


Pixel.h

class Pixel {
  public:
    Pixel(float a = 180, float b = 100, float c = 100);

    float hue;
    float saturation;
    float brightness;

    uint16_t toRGB();
}

Tween.h

class Tween {
  public:
    Tween(int fps = 60);

    float& target;
    float fps;

    void to(float& target, float from, float to, float duration, float (* ease)(float t, float b, float c, float d));

    void tick();
    float apply();
    bool active = false;

  private:
    float a = 0;
    float b = 1;
    float (* ease)(float t, float b, float c, float d);

    float increment = 1;
    float progress  = 0;
};

Tween.cpp

#include <Arduino.h>
#include "Tween.h"

int const ITERATIONS = 1000;

Tween::Tween(int f)
{ 
  this->fps = f;
  this->active = false;
}

void Tween::to(float& target, float from, float to, float duration, float (* ease)(float t, float b, float c, float d)) {
  if (this->active == true) {
    return;
  }

  this->target = target;
  this->active = true;

  this->a = from;
  this->b = to;

  this->ease = ease;

  int frame = 1000 / this->fps;
  int ms = duration * 1000;

  this->progress = 0;
  this->increment = ITERATIONS / (float)(ms / frame);
}

void Tween::tick() {  
  if (this->progress >= ITERATIONS) {
    this->progress = 0;
    this->active = false;
  }

  if (this->active == false) {
    return;
  }

  this->progress += this->increment;
}

float Tween::apply() {
  if (this->active == false) {
    return 0;
  }

  float value = this->ease(this->progress, 0, this->b, ITERATIONS);
  this->target = value;

  return value;
}

The use of those will be :

Pixel pixel = Pixel();
Tween tween = Tween(40);

void setup() {
  Serial.begin(115200);

  // reset the values of the pixel
  pixel.hue = 200;
  pixel.saturation = 100;
  pixel.brightness = 0;

  // setup the tween object
  tween.to(pixel.l, 0, 100, 3, Easing::linearTween);
}

void loop() {
  // progress
  tween.tick();

  // set pixel.l = tween value (this is where it's not working)
  tween.apply();

  Serial.println(pixel.brightness);

  // we defined 40fps in the tween so the delay should be 1000/40 => 25ms
  delay(25);
}

The easing library is actually Robert Penner's work translated to Arduino (https://github.com/tobiastoft/ArduinoEasing)

9
  • The variable reference must be known and initialized in constructor (in its initializer list). If you need later initialization use pointers.
    – KIIV
    Oct 26 '16 at 17:25
  • And that Easing library is pretty nasty one. So many sequence-point warnings...
    – KIIV
    Oct 26 '16 at 17:37
  • may i ask why you downvoted this ? thank you for your feedback regarding the easing library tho. also, is it only that i need to initialize the reference holder or did you mean the reference variable ?
    – y_nk
    Oct 27 '16 at 0:05
  • What is pixel.l? there is no "l" member (or function) in your PIxel class.
    – Kingsley
    Oct 27 '16 at 2:31
  • You don't need to use this->blah to access class member variables, just blah is enough. e.g.: this->hue = 47.96; can just be hue = 47.96; I guess you did this because you have the same parameter name as class member.
    – Kingsley
    Oct 27 '16 at 2:34
2

The member variable target does not need to be passed by reference at all.

void Tween::to(float target, float from, float to, float duration, float (* ease)(float t, float b, float c, float d)) 
{
  if (this->active == true) 
    return;

  this->target = target;
  this->active = true;

  // etc...
}

And then just call it without any sort of address or reference operator.

// setup the tween object
tween.to(pixel.l, 0, 100, 3, Easing::linearTween);

(but you still need to sort out what you mean by "pixel.l")

If you wanted to pass a Pixel object to the Tween::to() function, I would use a pointer to the object (although you could use a reference too).

void Tween::to(Pixel *pixel, /* ... etc*/)) 
{
    target = pixel->hue;
    other  = pixel->saturation;
    foo    = pixel->brightness;

    // etc.
}

Calling it like:

// setup the tween object
tween.to(&pixel, 0, 100, 3, Easing::linearTween);

It's not really clear exactly what you're trying to achieve just reading the code sample.

1
  • i'm sorry if the sample code didn't really show my goal. i guess my lack of knowledge in C confused people more than anything else ; but you guessed right with your 2 answers. Thank you very much for your patience.
    – y_nk
    Oct 27 '16 at 7:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.