Objects on the arduboy?


#1

Is posible to make objects on the ardbuoy.ino files?

Like a simple coin.

Making a class Coin with parameters of x and y coordinates and then making multiples instances of that class.

Is that posible?

Thanks


#2

Sure is, you are possible thinking of a struct. eg

typedef struct Coin { 
     uint8_t xpos, ypos;
     uint8_t value;
     uint8_t animation_step;
} Coin;

//then use it like follows.
Coin c;
c.xpos = 10;
c.ypos = 10;

//or an array of coins
Coin coins[10];
coins[0].xpos = 20;
coins[0].ypos = 30;

//or dynamically create it.
Coin *c = (Coin *) calloc(sizeof(Coin),1);
c->xpos = 10; 
c->ypos = 20;

hope that helps


(Mike McRoberts) #3

The Arduino language is C++ and so you can use C++ Classes as you wish.


#4

surely a struct is better memory wise though?


(Boti Kis) #5

Instances of a structs in c++ are objects like from classes. They are identical from the point of view of compiled code and there are no overheads. The difference is only from coders point of view where all members in structs are public, etc., etc…


#6

that, doesn’t make sense to me. A struct is just a block of bytes with some indexes into it, when all is said and done. I would have though C++ classes would have a bit more going on. I guess the compiler is smart enough to take care of that,


(Boti Kis) #7

that, doesn’t make sense to me.

See the reference here :slight_smile:


(Mike) #8

The short version is that a class indeed has more going on, but it’s all in the compiler, not in the generated code. At least if your class has no member functions.


#9

Got ya, I am not that familiar with C++, preferring to use straight C when i program in C family (Or objective C at work if i’m not using swift)

I wonder if class + member functions is bigger that struct + functions that operate on struct. Might have to experiment.


#10

FYI, in C++, struct and class are exactly the same.
The only difference is, by default, all struct members are public and all class members are private.
Otherwise you can struct <-> class without any change in code, performance, whatsoever…

So, in C++, with a struct, you can derive from it, create constructor/destructor, virtual function, etc.
And you can have POD class as well.


#11

@Bergasms Thanks for the answer, but can you please tell me, How can I draw a bit map inside the class?

I tried this way:

  #include <Arduboy2.h>
  
  Arduboy2 arduboy;
  
  void setup(){
    arduboy.begin();
    arduboy.setFrameRate(15);
  }
  
  const unsigned char image[] PROGMEM = {
    0x08, 0x0c, 0x0e, 0x0e, 0xff, 0x0e, 0x0e, 0x0c, 
    0x08, 
  };
  
  typedef struct Coin{ 
     uint8_t xpos, ypos;
     arduboy.drawBitmap(0, 0, image, 9, 8, 1);
  } Coin;
  
  
  void loop(){
    if (!(arduboy.nextFrame()))
      return;
      
    arduboy.clear;
    
    Coin c;
    c.xpos = 10;
    c.ypos = 10;
    
    arduboy.display();
  }

But it didn’t work, so then I try to call a function but it didn’t work either.

  #include <Arduboy2.h>
  
  Arduboy2 arduboy;
  
  void setup(){
    arduboy.begin();
    arduboy.setFrameRate(15);
  }
  
  const unsigned char image[] PROGMEM = {
    0x08, 0x0c, 0x0e, 0x0e, 0xff, 0x0e, 0x0e, 0x0c, 
    0x08, 
  };
  
  typedef struct Coin{ 
     int xpos, ypos;
     printImage(xpos, ypos);
  } Coin;

  void printImage(int x, int y){
    arduboy.drawBitmap(x, y, image, 9, 8, 1);
  }
  
  void loop(){
    if (!(arduboy.nextFrame()))
      return;
      
    arduboy.clear;
    
    Coin c;
    c.xpos = 10;
    c.ypos = 10;
    
    arduboy.display();
  }

(Mike) #12

First, you need to actually call the clear routine, not just mention it: arduboy.clear();

Second, you need to do something to display the bitmap. For instance, calling c.printImage(c.xpos, c.ypos); in the loop.

As an aside, you might note that Arduboy2 is a C++ class, and arduboy an instance of that class.


#13
#include <Arduboy2.h>

  Arduboy2 arduboy;

  void setup(){
    arduboy.begin();
    arduboy.setFrameRate(15);
  }

  const unsigned char image[] PROGMEM = {
    0x08, 0x0c, 0x0e, 0x0e, 0xff, 0x0e, 0x0e, 0x0c, 
    0x08, 
  };

  typedef struct Coin{ 
     int xpos, ypos;
  } Coin;

  void printImage(int x, int y){
    arduboy.drawBitmap(x, y, image, 9, 8, WHITE);
  }

  void loop(){
    if (!(arduboy.nextFrame()))
      return;
  
    arduboy.clear();

    Coin c;
    c.xpos = 10;
    c.ypos = 10;

    printImage(c.xpos,c.ypos);

    arduboy.display();
  }

(Pharap) #14

Not at all, classes and structs are the same thing under the hood. The only difference is that things put in a class are private by default and things put in a struct are public by default (hence some people prefer structs because they’re prone to forgetting the public declaration). You can test that yourself. Take every struct in your code, swap out ‘struct’ for ‘class’ and add the proper ‘public:’ declaration and the code should compile to exactly the same size.

When it comes down to it all the member functions are actually just regular functions with an implicit ‘this’ argument. e.g. player.SetPos(x, y); is effectively translated to Player::SetPos(&player, x, y);
(People tend not to realise what actually goes on because of all the mystical object-orientation jargon like ‘encapsulation’.)

Otherwise all member variable accesses are just pointer arithmetic/memory accesses like they would be in a struct. Naturally there are also optimisations involved e.g. getX() { return this->x; } would usually be inlined to the equivalent of doing this->x;, none of which are class or struct specific since both are the same thing.

Try not to think of C++ as an extension of C and think of it as a completely different language that just happens to share syntax. In fact despite popular hand wavery, C is not a subset of C++. C++ has rules that are in direct opposition to C’s rules and there are lines of code that would have different meanings in different languages.


#15

Yeah, I understand all that, thanks for the explanation.


(Mike) #16

Wow. I had figured only C++ class member functions would do dynamic dispatch because C functions didn’t to dynamic dispatch. Sure enough, I was wrong. Yet another reason to continue not writing C++.


(Pharap) #17

You don’t have a choice. The Arduino compiler is a C++ compiler, it follows the rules of C++, there is no “I’m using C” option. Even if you write in a C-like way, the code is still C++ because the compiler treats it as such.

And C++ only does dynamic dispatch on virtual methods. If you don’t have any virtual methods there is no vtable and thus no dynamic dispatch. Even if you do have virtual methods, only the virtual methods use dynamic dispatch, all the others will use static dispatch and possibly even be inlined.


(Mike) #18

I may have gotten the terminology wrong for C++. You can overload ordinary functions, which means they dispatch based on the type of the arguments. If one of the variables passed as an argument to such a function is a member of a class that has subclasses that are dispatched to different functions, then that dispatch needs to happen dynamically at run time. At least, any rational language would behave that way, but we’re talking about C++.

And I do have a choice - I can write whatever language I feel like - C, C++, Rust, Python, etc. I don’t have a choice in what language the Arduino IDE will try and compile, and writing something other than C or C++ is unlikely to work. I find it a lot less frustrating to write C than C++ when creating a .ino file.


#19

I’m going to assume though, that if i write code that is 100% compatible with a C compiler, the C++ compiler isn’t going to do anything stupid to make it significantly worse than a regular C compiler would.


#20

I didn’t look in details in the arduino toolchain and options, but as a rule of thumb: if you’re writing a pure c code file, just give it the .c extension: some toolchains may enforce by default to compile as C code and not C++.