Имеется несколько переменных одной структуры (с переменными и функциями). Точнее массив из этой структуры на N элементов. Есть необходимость использовать переменные из одного элемента в функции другого. Но они не видны. Я использовал костыли для решения этой задачи в виде обращения изнутри структуры к внешней функции, в которую передается номер элемента массива. Та в свою очередь выуживает данные из нужного элемента и возвращает обратно в функцию структуры. Это не очень удобно, не наглядно, и что то мне подсказывает, что не совсем правильно. Есть ли способ получше?
1. Переменные класса можно сделать видимыми. 2. Можно в классе определить функции, которые будут возвращать или задавать значения полей класса. Тащите исходник, разберемся как лучше поступить в вашем случае.
Собственно неработающего куска кода и нет, ибо он не работает. Программа все та же с прыгающими по матрице 8х8 шариками, только теперь они могут скакать не только по вертикали, горизонтали и по диагонали, но и под произвольным углом. С проблемой столкнулся при попытке научить их соударяться и отскакивать друг от друга. В каждом элементе массива шариков есть, кроме прочих, данные о его координатах, направлении и скорости. Идея была в том, что при очередном шаге смещения функция проверяет есть ли другой шарик по ходу движения. Если есть, то меняется угол и скорость этого шарика и того, что у него на пути. Поменять данные расчитываеиого шарика не сложно, а вот изменить их в другом элементе не понятно как, т.к, они в параллельной вселенной. Тут либо стучать на него во внешнюю функцию с просбой поменять направление его полета, либо непонятно как еще.
Вот код. Обратите внимание на место где упомянуто столкновение, от туда вызывается внешняя функция с передачей туда данных о номерах шаров которым следует сымитировать отскок. Сама функция видит данные обоих шаров, в отличие от внутренней функции структуры. Вообще то все работает, но мне кажется это как то не совсем правильным. Код (Text): #include "FastIO.h" #define DATA_PIN 13 #define LATCH_PIN 12 #define CLOCK_PIN 11 //#define DDD // отладка и печать в ком порт byte masRG [8][8] = { // поле 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; byte cBall_1; byte cBall_2; struct runBall { //--------------------- структура шарика byte posX = 0, posY = 0; // позиция X в реальном поле 8х8 byte posXx = 0, posYx = 0; // позиция в виртуальном поле 80х80 byte deltaX = 0, deltaY = 0; // смещение по осям за шаг в поле 80х80 byte color = 0; // цвет int MS = 0; // время задержки между шагом (мс) long unsigned int TS; // таймер void setVector(int vector) { // перевод вектора в градуcах по часовой стрелке в дельту X и Y (от -10 до +10) deltaX = 7 * sin(vector * 3.14 / 180); deltaY = 7 * cos(vector * 3.14 / 180); } void setBall () { // функция шага masRG[posX][posY] = 0; // тушим прошлую позицию posXx = posXx + deltaX; // сдвигаем по X и Y posYx = posYx + deltaY; if ((posXx >= 65) or (posXx <= 5)) { // определяем пределы поля и переключаем направления deltaX = deltaX * (-1); } if ((posYx >= 65) or (posYx <= 5)) { deltaY = deltaY * (-1); } posX = posXx / 10 + ((posXx % 10) >= 5); posY = posYx / 10 + ((posYx % 10) >= 5); posX = constrain(posX, 0, 7); posY = constrain(posY, 0, 7); if (masRG[posX][posY] > 0) { // столкновение! (номер шаров пока определяем по цвету) crashBall((color - 1), (masRG[posX][posY] - 1)); } masRG[posX][posY] = color; // зажигаем в новом месте } }; //-------------------------------- конец структуры //unsigned long int bum; #if defined (DDD) // для подсчета fps unsigned long int ttt; unsigned int fps = 0; #endif runBall mBall[3]; // определяем три шарика void setup() { mBall[0].posXx = 20; // красный mBall[0].posYx = 40; mBall[0].color = 1; mBall[0].MS = 200; mBall[0].setVector(65); // вычисление приращения шага от угла вектора mBall[1].posXx = 20;// зеленый mBall[1].posYx = 40; mBall[1].color = 2; mBall[1].MS = 30; mBall[1].setVector(110); mBall[2].posXx = 50;// желтый mBall[2].posYx = 50; mBall[2].color = 3; mBall[2].MS = 100; mBall[2].setVector(20); MC_SET_PIN_OUTPUT(DATA_PIN); MC_SET_PIN_OUTPUT(CLOCK_PIN); MC_SET_PIN_OUTPUT(LATCH_PIN); for (byte i = 0; i < 3; i++) { // запускаем таймеры mBall[i].TS = millis(); } #if defined (DDD) Serial.begin(9600); #endif } void loop() { for (byte i = 0; i < 3; i++) { // проверяем таймеры на время шага if ((millis() - mBall[i].TS) >= mBall[i].MS) { mBall[i].setBall(); // которому пора, тот сдвигаем mBall[i].TS = millis(); // и обнуляем ему таймер } } setKadr_RG(); // рисуем поле с шарами #if defined (DDD) // подсчет fps fps++; if ((millis() - ttt) > 2000) { Serial.println(fps); while (true); } #endif } void crashBall (byte Ball_1, byte Ball_2) { // условно упругое столкновение, обмениваются скоростями и направлениями byte dropX = mBall[Ball_1].deltaX; byte dropY = mBall[Ball_1].deltaY; byte dropMS = mBall[Ball_1].MS; mBall[Ball_1].deltaX = mBall[Ball_2].deltaX; mBall[Ball_1].deltaY = mBall[Ball_2].deltaY; mBall[Ball_1].MS = mBall[Ball_2].MS; mBall[Ball_2].deltaX = dropX; mBall[Ball_2].deltaY = dropY; mBall[Ball_2].MS = dropMS; } void setKadr_RG () { // отрисовка кадра byte bytSTR; byte mR; byte mG; for (byte s = 0; s <= 7; s++) { bytSTR = 0; bitSet(bytSTR, s); for (byte i = 0; i <= 7; i++) { bitWrite(mR, i, !(bitRead(masRG[s][i], 0))); bitWrite(mG, i, !(bitRead(masRG[s][i], 1))); } MC_WRITE_PIN(LATCH_PIN, LOW); writeByte(bytSTR); writeByte(mR); writeByte(mG); MC_WRITE_PIN(LATCH_PIN, HIGH); } } void writeByte(byte byteW) { // аналог shiftOut, работает чуть быстрее for (int i = 7; i >= 0; i--) { MC_WRITE_PIN(DATA_PIN, (bitRead(byteW, i))); MC_WRITE_PIN(CLOCK_PIN, HIGH); MC_WRITE_PIN(CLOCK_PIN, LOW); } } Да, и вопрос вдогонку, как изнутри структуры узнать в какой именно переменной в данный момент происходит вычисление? В моем случае как получить номер элемента массива обрабатываемого прямо сейчас?
Если закрыть поля структуры и читать/писать их только с помощью функций, то в момент вызова функции структура "узнает" о том, что к ее полю кто-то обратился.
Совершенно не понятно как именно она "узнает" и где мне узнать о том, что она "узнала"? Впрочем, не совсем понятно что именно требуется получить, указатель на переменную или ее номер в массиве. Для второго случая, наверное, проще добавить в структуру еще одно поле с его номером.
Узнает по факту вызова своей функции. Указатель на структуру всегда известен в случае вызова функции структуры - это this.
а) передавать в функцию, как параметр; б) проводить вычисление в коде, владеющим всем массивом и знающем о переменной цикла.