Need help to develop KSboy (Kerbal Space Program 8-bits)


#1

Hi i just start to programing on the arduboy and i need help to develop my game.
It a Kerbal Space Program remake.
Here is the code:
KSboy


(Stephane C) #2

Contrats on trying to develop your first game on the Arduboy!

Please be more specific about the help you need. Some of us may help you in different part of your game.
But we can’t offer if you don’t ask something specific and more information about what is your game and ideas you have for it.


(Simon) #3

Before you get going, please take a few minutes to convert to the Arduboy2 library. You code is still using the original, unsupported library.

This is a huge undertaking and I think you need to plan out the game - what is to be included and what is going to be left out - as you will (very) quickly run into memory issues and so forth. Putting aside the question of whether the Arduboy is an appropriate platform to begin with, planning how you will strip the game down to still be a playable and enjoyable remake will prevent you wasting time on items that may look good on screen (graphics for example) but add little to the play value.

As @Vampirics mentioned, detail what help you need as the skills will sit with many people.

If you are looking for someone to collaborate with then, again, call it out!


(Scott) #4

More like 30 seconds. Just change the 1st two lines to:

#include <Arduboy2.h>
Arduboy2 arduboy;

(Simon) #5

Right … I wish @crait would update his tutorials to use the new (old now) libraries. I guess he is too busy playing with chickens!


(Pharap) #6

I’m assuming you’re looking for someone to partner up with?
So I changed your post’s category to ‘help wanted’.

If you just want advice, we’d need some specific questions.

Though I think that if you are quite new to programming, KSP is probably a bit beyond you at the moment.
Instead perhaps find a small aspect of KSP that you like, e.g. ships orbiting planets, and write a program that simulates just that aspect.

Something KSP-like would be hard for anyone to pull off on the Arduboy because of space constraints (if you’ll pardon the pun).


#7

How much progmem did your physics program take up? I haven’t compiled it yet. KSP doesn’t actually simulate gravity as there are no Lagrangian points. I could see a linear equation comparing velocity to orbital height working in a 2d setting. KSP actually started out as a 2d project. I think the building aspect might be too much of a scope for the arduboy. At least at first while the orbital mechanics are worked out. Perhaps it could fit in a really simplified design. Like a few choices for a cockpit, fuel amount, motor.


(Pharap) #8

Dammit Jim, I’m a programmer, not a rocket scientist.

Sketch uses 10684 bytes (37%) of program storage space. Maximum is 28672 bytes.
Global variables use 1323 bytes (51%) of dynamic memory, leaving 1237 bytes for local variables. Maximum is 2560 bytes.

I don’t doubt that a trimmed down version of KSP would be possible, but it would still take a lot of know-how and effort.


#9

Shorthand is there’s points where gravity cancels out and an object in those points will stay puy unlike a normal orbit that decays.

Ksp works off of sphere of influences. So if your within x away from a body that’s all that exists basicly as far as physics calculations.

Which really burns down to just calculating the orbits using your velocity and position. I said 2d but really a 2d overlook would just be a 1 dimensional calculating with a clockwise or counter clockwise direction applied. 1 planet should be too hard but adding an orbiting moon would definitely add a lot of complexity.

I think your fixed points library would also be necessary since plants are spherical and more importantly orbits follow an elipse. I don’t see how else you could do those calculations.

Aerodynamics could be boiled down pretty easy too. A switchcase for drag based on altitude wouldn’t be too complex.

Velocity = Velocity - gravity factor - aerodrag + engine acceleration.


(Pharap) #10

Sounds like KSP may have chosen to do that for optimisation reasons.

Checking for object interractions often ends up being an O(N^2) check unless you’re prepared to do space partitioning of some description (e.g. binary space partitioning or octrees).


#11

Ok thank you very much :slight_smile:


#12

i am trying to do at first a start page:
start


(Stephane C) #13

Ok… and what kind of help do you need? Is there something you want to add that you don’t know to do it?
Don’t take it bad but usually things like title screen are better be worked on later (even though it’s the first thing we see).

You maybe should start by trying to work on the mechanism of the game first to see if it’s possible for you to create it on the Arduboy, it would be sad to see a lot of your time wasted on a beautiful title screen and graphics if the game can’t be done right?

But if you really want to start with the title screen like you mention, please be more specific about the help that you need. Saying that you are trying to make a start screen doesn’t tell us much (at least me).

Do you need help with the graphics for that screen?
Do you need to know how to make it so that when you press a button it goes in-game?
Do you need to know how to animate something on that screen?
Etc…

Don’t take it bad, i am just trying to help you asking for the help you might need.

Also, having a look at the @filmote HERE and @crait 's HERE tutorials in this forum might help you a lot and more often then not your answers will be there.

Also, you can have a look at the sources of other games to see how others are doing things, i learned a lot that way (not that i am good now, but i know a lot more and i understand things better).


#14

My problem is when i turn on the arduboy the screen don’t display anything but at line 26 :

arduboy.drawBitmap(50,50, Start, 64, 128, BLACK);

I say to display start so my start page
And…
it does’nt work :’(


(Boti Kis) #15

Took a brief look at your code.
The loop() function is a bit messy and I suggest to clean it up. :slight_smile:
There is a for-loop at line 28 which don’t make any sense to me and is the root of your problem.

A very simplified version of your menu would be:

void loop() {
   arduboy.clear();
   arduboy.drawBitmap(50,50, Start, 64, 128, BLACK);

   if(arduboy.pressed(A_BUTTON))
  {
      // Do stuff
  }

   arduboy.display();
}

I believe that there is something wrong with your drawBitmap() since I don’t think that the image is 64 in width and 128 in height.

I also don’t understand what you want to happen after line 28. If you want some help on that, please be more specific. As @Vampirics already suggested, I also recommend you to first go through the tutorials of @filmote and @crait before you start to make your own game.


(Stephane C) #16

I kinda understand what you are trying to do, but not sure you are doing it the best way.
You want to make it so that the ship(player) launches after we press A…

For starter…

@Botisaurus is right about your Start bitmap, it sure isn’t 64 x 128 so that must be wrong, if you enter the wrong dimension there, it will always display garbage or parts of things that are in memory.

Another thing, i am pretty sure you may have mixed what is BLACK and what is WHITE ( or maybe you wanted the background white? but looking at the image you posted it’s all inverted.

In your code you are also inverting X and Y, playerx should be the coordinate for when the player moves horizontally, and playery vertically. your code is still working, but it’s weird to see playery as the X coordinate.


(Holmes) #17

I WILL BE SOON! :slight_smile: Also still working on the latest tutorial!


(Pharap) #18

To point out some of the specific problems

arduboy.clear() clears the screen.

In your code you’re drawing Start and then clearing the screen, so that sprite will be erased before it’s shown.

It also means that in this case:

    if(var > 10){
       arduboy.drawBitmap(97,15, base2, 32, 32, BLACK);
      
      arduboy.clear();
}

You’re drawing a sprite and then immediately erasing it.

Secondly the loop @Botisaurus hinted at:

for (int i=0; i <= 150; i++){

Seems to not really serve a purpose.


A better approach

From reading this code I think where you’re going wrong is in your approach to the code.
You’re trying to tell it what you want it to do all at once in a single function.

Games generally don’t work like that.
Nearly every modern game consists of an update-render loop in which the code:

  1. Updates input
  2. Updates the game state (physics, ai, general logic)
  3. Renders the graphics

These are generally kept distinct and not mixed (i.e. not moving the character and then drawing the character’s sprite immediately after).

The key bit of information that I think you’re missing is the concept of a state machine and how to get your game to be in different states and change state.

For example:

#include <Arduboy2.h>

// You'll probably want to replace this with a separate image of the rocket
// and the actual title when you know how
const uint8_t TitleScreenImage[] PROGMEM =
{
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFC, 0xFF, 0xC3, 0xFF, 0xFC, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x60, 0x60, 0x60, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x07, 0x0C, 0x0C, 0x0C, 0x0C, 0x98, 0xF8, 0xF0, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x03, 0x03, 0x03, 0x00, 0xE0, 0xE6, 0x33, 0x33, 0x33, 0xB7, 0xFE, 0xFC, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x06, 0x03, 0x03, 0x03, 0x00, 0x03, 0xFF, 0xFF, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x3F, 0xFF, 0x00, 0xE0, 0xFC, 0x3F, 0x1F, 0x3F, 0x3F, 0xFF, 0x3F, 0x3F, 0x1F, 0x3F, 0xFC, 0xE0, 0x00, 0xFF, 0x3F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x3F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x44, 0x44, 0x7C, 0x30, 0x00, 0x7C, 0x04, 0x04, 0x00, 0x7C, 0x54, 0x54, 0x5C, 0x00, 0x00, 0x5C, 0x54, 0x74, 0x00, 0x00, 0x5C, 0x54, 0x74, 0x00, 0x00, 0x00, 0x7C, 0x82, 0x01, 0x7D, 0x15, 0x7D, 0x01, 0x82, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00
};

const unsigned char PlayerImage[] PROGMEM  =
{
	0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xff, 0xff, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xf1, 0xf9, 0xf9, 0xdd, 0xd, 0x86, 0x80, 0x80, 0x00, 0x3, 0x7, 0xc, 0xc, 0x1c, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0xff, 0xff, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x3f, 0x7f, 0x7f, 0xef, 0xc3, 0x87, 0x7, 0x7, 0x3, 0x00, 0x00, 0x00, 0x00, 0x2, 0x6, 0xe, 0xe, 0xe, 0xe, 0xf, 0xf, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xa, 0x1, 0x00, 0x00, 0x00,
};

// This is a scoped enumeration (often called an 'enum class')
// Don't worry too much about how this works,
// just see how it's used
enum class GameState : uint8_t
{
	TitleScreen,
	Gameplay,
};

Arduboy2 arduboy = Arduboy2();
GameState gameState = GameState::TitleScreen;

// int16_t is the same as int on the Arduboy,
// but int isn't the same size on all platforms,
// while int16_t is
uint16_t playerX = 0;
uint16_t playerY = 0;

// The 'void' in the brackets means 'this function takes no arguments'
// If you don't know what functions and arguments are,
// you need to read more tutorials - they're crucial to writing manageable games
void setup(void)
{
	arduboy.begin();
}

void loop(void)
{
	// This stops the Arduboy trying to draw before it's ready
	if(!arduboy.nextFrame())
		return;

	// This updates the button state
	arduboy.pollButtons();
	
	// Do different things depending on the current game state
	switch(gameState)
	{
		case GameState::TitleScreen:
			updateTitleScreen();
			break;
		case GameState::Gameplay:
			updateGameplay();
			break;
	}
		
	// This clears the screen
	arduboy.clear();
	
	// Do different things depending on the current game state
	switch(gameState)
	{
		case GameState::TitleScreen:
			renderTitleScreen();
			break;
		case GameState::Gameplay:
			renderGameplay();
			break;
	}
	
	// This displays the screen
	arduboy.display();
}

void updateTitleScreen(void)
{
	// If A is pressed, move to Gameplay state
	if(arduboy.justPressed(A_BUTTON))
	{
		gameState = GameState::Gameplay;
	}
}

void updateGameplay(void)
{
	// If left is pressed, move the player left
	if(arduboy.pressed(LEFT_BUTTON))
	{
		--playerX;
	}
	
	
	if(arduboy.pressed(RIGHT_BUTTON))
	{
		++playerX;
	}
	
	// I'll let you fill in the equivalent for Y
}

void renderTitleScreen(void)
{
	// You don't need to specify the colour, it defaults to 'BLACK', 
	// which means 'draw the image normally'
	// Using 'WHITE' inverts the image
	arduboy.drawBitmap(0, 0, TitleScreenImage, 128, 64);
}

void renderGameplay(void)
{
	// Draw the player at the player position
	arduboy.drawBitmap(playerX, playerY, PlayerImage, 32, 32);
}

(Gist available here.)

Feel free to ask questions, I’m probably doing at least half a dozen things in that code that you haven’t encountered before.


Some other tips

Avoid delay.
It delays all the code, which includes drawing and input, so your game can end up feeling unresponsive.

(Also, never be afraid to ask questions, most programmers love discussing code and explaining how it works because code is cool.)

(Specific questions are more likely to get good answers though, vague or general questions are hard to answer.)


(Simon) #19

Nothing like a little heckling to get you worked up!.


#21

Thank you so much @Pharap i just updated my code with your own and…
Start work :slight_smile: