Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Следующая версия
Предыдущая версия
products:laboratory_iot_c:exp53 [2024/12/13 19:29] – создано labuser30products:laboratory_iot_c:exp53 [2024/12/15 17:03] (текущий) – [Программный код эксперимента] labuser30
Строка 4: Строка 4:
 Как мы уже поняли, это стены, ящики, кладовщик и цели, куда нужно перетащить ящики. Теперь нужно описать каждый из классов. Как мы уже поняли, это стены, ящики, кладовщик и цели, куда нужно перетащить ящики. Теперь нужно описать каждый из классов.
  
-=== Класс ящика === +=== Структура позиция === 
-Начнем с класса ящика. Главные свойства ящика, это его координаты на карте и его состояние — находится он на цели или нет.+В связи с тем, что в некоторых методах следующих классов нам нужно будет возвращать положение объектов состоящее из двух переменных (координаты х и y), а методы могут возвращать только одну переменную, создадим структуру ''Pos''. Структуру можно описать как упрощенную версию класса. Обычно структуры не имеют методов, хотя могут.
  
-<code python+<code arduino
-class Box: +struct Pos { 
-    def __init__(self, tft, x, y): +  int x = 0; 
-        self.tft tft +  int y = 0;
-        self.x = x +
-        self.y = +
-        self.picture = 'box.bmp' +
-        self.picture_onGate = 'boxngate.bmp' +
-        self.onGate = False +
-        self.draw()+
  
-    def draw(self): +  bool operator == (const Pos &posconst { 
-        if (self.onGate): +    return x == pos.x && y == pos.y
-            self.tft.draw_bmp(self.x * 16,self.y * 16,  self.picture_onGate) +  } 
-        else: +}; 
-            self.tft.draw_bmp(self.x * 16,self.y * 16, self.picture)+</code>
  
-    def setOnGate(selfstate): +Определенная нами структура содержит две переменные координат и определение оператора равенства. Две переменные типа ''Pos'' равны только тогдакогда попарно равны их координаты 
-        self.onGate = state+
  
-    def getOnGate(self): +=== Класс ящика === 
-        return self.onGate+Начнем с класса ящика. Главные свойства ящика, это его координаты на карте и его состояние — находится он на цели или нет.
  
-    def getPos(self)+<code arduino> 
-        return (self.x, self.y)+class Box { 
 +  private
 +    Adafruit_ST7735 *tft_ptr; 
 +    LittleFS_ImageReader *reader_ptr; 
 +    Pos pos; 
 +    String picture = "/box.bmp"; 
 +    String picture_on_gate = "/boxngate.bmp"; 
 +    bool on_gate = false;
  
-    def setPos(self, x, y): +  public: 
-        self.x = x +    Box(Adafruit_ST7735 *_tft_ptr, LittleFS_ImageReader *_reader_ptrint x, int y) { 
-        self.y = y +      tft_ptr = _tft_ptr; 
-        self.draw()+      reader_ptr = _reader_ptr; 
 +      pos.x = x; 
 +      pos.y = y
 +    }   
 +     
 +    void draw() { 
 +      if (on_gate) reader_ptr->drawBMP(picture_on_gate, *tft_ptr, pos.x * 16, pos.y * 16); 
 +      else reader_ptr->drawBMP(picture, *tft_ptr, pos.x * 16, pos.y * 16);  
 +    } 
 +  
 +    void setOnGate(bool state) { 
 +      on_gate = state; 
 +    } 
 +         
 +    bool getOnGate() const { 
 +      return on_gate; 
 +    } 
 +  
 +    Pos getPos() const { 
 +      return pos; 
 +    } 
 +  
 +    void setPos(Pos _pos) {  
 +      pos.x = _pos.x; 
 +      pos.y = _pos.y; 
 +      draw()
 +    } 
 +};        
 </code> </code>
  
-В конструктор мы передаем такие параметры как объект дисплея, координата x, координата y. Координата ящика указывается не в пикселях, а в клетках игрового поля. В самом конструкторе мы задаем имя спрайта для ящика на цели ''self.picture_onGate 'boxngate.bmp''' и вне цели ''self.picture 'box.bmp'''. Свойство ''onGate'' как раз описывает состояние ящика. В конце конструктор вызывает метод отрисовки ''draw''.+В при создании экземпляра класса следующим свойствам будут присвоены значения по умолчанию:  имя спрайта для ящика вне цели ''String picture "/box.bmp";'' и  на цели ''String picture_onGate "/boxngate.bmp"''состояние ящика на цели или нет ''bool on_gate = false;''
  
-Метод ''draw()'' предназначена для отрисовки ящика. Если ящик находится на цели, то функция отображает спрайт ''self.picture_onGate'', иначе ''self.picture''. Координата ящика указывается не в пикселях, а в клетках игрового поля, поэтому для отображения картинки ее необходимо пересчитать в пиксели. Для этого координата умножается на размер ящика в пикселях.+В конструктор мы передаем такие параметры как указатели на объект дисплея и считывателя изображений, координата x, координата y. Координата ящика указывается не в пикселях, а в клетках игрового поля. 
 +Метод ''draw()'' предназначена для отрисовки ящика. Если ящик находится на цели, то функция отображает спрайт ''picture_on_gate'', иначе ''picture''. Координата ящика указывается не в пикселях, а в клетках игрового поля, поэтому для отображения картинки ее необходимо пересчитать в пиксели. Для этого координата умножается на размер ящика в пикселях.
  
 Метод ''setOnGate()'' служит для установки свойства нахождения на цели. А метод ''getOnGate()'' для чтения этого свойства. Метод ''setOnGate()'' служит для установки свойства нахождения на цели. А метод ''getOnGate()'' для чтения этого свойства.
  
-Метод ''getPos'' возвращает текущие координаты ящика. А метод ''setPos'' устанавливает новые координаты ящика, после чего перерисовывает его на новом месте.+Метод ''getPos'' возвращает текущую позицию ящика. А метод ''setPos'' устанавливает новые координаты ящика, после чего перерисовывает его на новом месте.
  
 === Класс цели === === Класс цели ===
 Класс цели намного проще. Цель никуда не перемещается и свойств не имеет. Цель имеет только координаты и должна отображаться на экране с помощью своего спрайта. Класс цели намного проще. Цель никуда не перемещается и свойств не имеет. Цель имеет только координаты и должна отображаться на экране с помощью своего спрайта.
  
-<code python+<code arduino
-class Gate: +class Gate 
-    def __init__(self, tft, x, y): +  private
-        self.tft = tft +    Adafruit_ST7735 *tft_ptr; 
-        self.x = x +    LittleFS_ImageReader *reader_ptr; 
-        self.y = y +    Pos pos; 
-        self.picture = 'gate.bmp+    String picture  "/gate.bmp";
-        self.draw()+
  
-    def draw(self)+  public
-        self.tft.draw_bmp(self.x 16,self.y 16self.picture)+    Gate(Adafruit_ST7735 *_tft_ptrLittleFS_ImageReader *_reader_ptrint x, int y
 +      tft_ptr = _tft_ptr; 
 +      reader_ptr = _reader_ptr; 
 +      pos.x = x; 
 +      pos.y = y; 
 +    } 
  
-    def getPos(self): +    void draw() const { 
-        return (self.x, self.y)+      reader_ptr->drawBMP(picture, *tft_ptr, pos.x * 16pos.y * 16)
 +    }  
 + 
 +    Pos getPos() const { 
 +      return pos; 
 +    } 
 +};
 </code> </code>
  
-Метод ''daraw'' служит для отрисовки спрайта цели в заданных координатах. Так как координаты цели задаются не в пикселях, а в клетках поля, необходимо пересчитать их в пиксели для отображения. Поэтому координаты в клетках умножаются на размер клетки — 16.+Метод ''draw()'' служит для отрисовки спрайта цели в заданных координатах. Так как координаты цели задаются не в пикселях, а в клетках поля, необходимо пересчитать их в пиксели для отображения. Поэтому координаты в клетках умножаются на размер клетки — 16.
  
 === Класс кладовщика === === Класс кладовщика ===
 Кладовщик также имеет координаты своего нахождения на поле и имеет свой спрайт. Кладовщик также имеет координаты своего нахождения на поле и имеет свой спрайт.
  
-<code python+<code arduino
-class Man: +class Man 
-    def __init__(self, tft, x, y): +  private
-        self.tft = tft +    Adafruit_ST7735 *tft_ptr; 
-        self.x = x +    LittleFS_ImageReader *reader_ptr; 
-        self.y = y +    Pos pos; 
-        self.picture = 'man.bmp+    String picture  "/man.bmp";
-        self.draw()+
  
-    def draw(self)+  public
-        self.tft.draw_bmp(self.x 16,self.y 16self.picture)+    Man(Adafruit_ST7735 *_tft_ptrLittleFS_ImageReader *_reader_ptrint x, int y) { 
 +      Serial.println("Man constructor")
 +      tft_ptr = _tft_ptr; 
 +      reader_ptr = _reader_ptr; 
 +      pos.x = x; 
 +      pos.y = y; 
 +    } 
  
-    def getPos(self): +    void draw() const { 
-        return (self.x, self.y)+      reader_ptr->drawBMP(picture, *tft_ptr, pos.x * 16pos.y * 16)
 +    }
  
-    def setPos(self, x, y): +    Pos getPos() const { 
-        self.tft.rect(self.x * 16, self.y * 16, 16, 16, tft.COLOR_BLACK+      return pos; 
-        self.x = x +    } 
-        self.y = y + 
-        self.draw()+    void setPos(Pos _pos 
 +      tft_ptr->fillRect(pos.x * 16, pos.y * 16, 16, 16, ST77XX_BLACK); 
 +      pos.x = _pos.x; 
 +      pos.y = _pos.y; 
 +      draw()
 +    } 
 +};
 </code> </code>
  
Строка 110: Строка 160:
 ==== Программный код эксперимента ==== ==== Программный код эксперимента ====
  
-<file python Exp53.py[enable_line_numbers="2", start_line_numbers_at="1"]> +<file arduino Exp53.ino[enable_line_numbers="2", start_line_numbers_at="1"]> 
-from machine import Pin, SPI +#include <SPI.h> 
-from tft import TFT_GREEN +#include <Adafruit_ST7735.h> 
-_init() +#include "LittleFS_ImageReader.h" 
-machine.freq(160000000)+
  
 +#define PIN_CS  2
 +#define PIN_DC  4
 +#define PIN_RST 5
  
-dc  Pin(4Pin.OUT) #a0 +Adafruit_ST7735 tft Adafruit_ST7735(PIN_CS,  PIN_DCPIN_RST); 
-cs  = Pin(2Pin.OUT+LittleFS_ImageReader reader;
-rst = Pin(5, Pin.OUT) +
-spi = SPI(1, baudrate=40000000, polarity=0, phase=0)+
  
-# TFT objectthis is ST7735R green tab version +bool Map[10][8] = { 
-tft = TFT_GREEN(128160spidccsrstrotate=0)+  {1,1,0,1,1,1,0,1}
 +  {0,1,1,1,1,1,1,0}, 
 +  {1,1,0,0,0,1,1,1}, 
 +  {0,1,0,1,0,1,0,1}, 
 +  {0,1,0,0,0,1,0,1}, 
 +  {1,1,1,1,0,0,0,1}, 
 +  {1,0,0,0,0,0,0,1}, 
 +  {1,0,0,0,1,0,0,1}, 
 +  {1,0,0,0,1,1,1,1}, 
 +  {1,1,1,1,1,0,0,0} 
 +};
  
-Map +struct Pos { 
-    [1,1,0,1,1,1,0,1], +  int x = 0; 
-    [0,1,1,1,1,1,1,0], +  int y = 0;
-    [1,1,0,0,0,1,1,1], +
-    [0,1,0,1,0,1,0,1], +
-    [0,1,0,0,0,1,0,1], +
-    [1,1,1,1,0,0,0,1], +
-    [1,0,0,0,0,0,0,1], +
-    [1,0,0,0,1,0,0,1], +
-    [1,0,0,0,1,1,1,1], +
-    [1,1,1,1,1,0,0,0] +
-]+
  
-Gates [] +  bool operator == (const Pos &pos) const { 
-Boxes []+    return x == pos.x && y == pos.y; 
 +  } 
 +};
  
-class Box: +class Box 
-    def __init__(self, tft, x, y): +  private
-        self.tft = tft +    Adafruit_ST7735 *tft_ptr; 
-        self.x = x +    LittleFS_ImageReader *reader_ptr; 
-        self.y = y +    Pos pos; 
-        self.picture = 'box.bmp' +    String picture = "/box.bmp"; 
-        self.picture_onGate 'boxngate.bmp' +    String picture_on_gate "/boxngate.bmp"; 
-        self.onGate False +    bool on_gate false;
-        self.draw()+
  
-    def draw(self)+  public
-        if (self.onGate): +    Box(Adafruit_ST7735 *_tft_ptr, LittleFS_ImageReader *_reader_ptr, int x, int y
-            self.tft.draw_bmp(self.x * 16,self.y * 16,  self.picture_onGate+      tft_ptr = _tft_ptr; 
-        else+      reader_ptr = _reader_ptr; 
-            self.tft.draw_bmp(self.x * 16,self.y * 16, self.picture)+      pos.x = x; 
 +      pos.y = y; 
 +    }   
 +     
 +    void draw() { 
 +      if (on_gate) reader_ptr->drawBMP(picture_on_gate, *tft_ptr, pos.x * 16, pos.y * 16); 
 +      else reader_ptr->drawBMP(picture, *tft_ptr, pos.x * 16, pos.y * 16);  
 +    } 
 +  
 +    void setOnGate(bool state) { 
 +      on_gate = state; 
 +    } 
 +         
 +    bool getOnGate() const { 
 +      return on_gate; 
 +    } 
 +  
 +    Pos getPos() const { 
 +      return pos; 
 +    } 
 +  
 +    void setPos(Pos _pos) {  
 +      pos.x = _pos.x; 
 +      pos.y = _pos.y; 
 +      draw()
 +    } 
 +};        
  
-    def setOnGate(self, state)+class Gate { 
-        self.onGate state+  private
 +    Adafruit_ST7735 *tft_ptr; 
 +    LittleFS_ImageReader *reader_ptr; 
 +    Pos pos; 
 +    String picture  "/gate.bmp";
  
-    def getOnGate(self): +  public: 
-        return self.onGate+    Gate(Adafruit_ST7735 *_tft_ptr, LittleFS_ImageReader *_reader_ptr, int x, int y{ 
 +      tft_ptr = _tft_ptr; 
 +      reader_ptr = _reader_ptr; 
 +      pos.x = x; 
 +      pos.y = y; 
 +    } 
  
-    def getPos(self): +    void draw() const { 
-        return (self.x, self.y)+      reader_ptr->drawBMP(picture, *tft_ptr, pos.x * 16pos.y * 16)
 +    } 
  
-    def setPos(self, x, y): +    Pos getPos() const { 
-        self.x = x +      return pos; 
-        self.y = y +    } 
-        self.draw()+};
  
-class Gate+class Man { 
-    def __init__(self, tft, x, y): +  private
-        self.tft = tft +    Adafruit_ST7735 *tft_ptr; 
-        self.x = x +    LittleFS_ImageReader *reader_ptr; 
-        self.y = y +    Pos pos; 
-        self.picture = 'gate.bmp+    String picture  "/man.bmp";
-        self.draw()+
  
-    def draw(self)+  public
-        self.tft.draw_bmp(self.x 16,self.y 16self.picture)+    Man(Adafruit_ST7735 *_tft_ptrLittleFS_ImageReader *_reader_ptrint x, int y) { 
 +      Serial.println("Man constructor")
 +      tft_ptr = _tft_ptr; 
 +      reader_ptr = _reader_ptr; 
 +      pos.x = x; 
 +      pos.y = y; 
 +    } 
  
-    def getPos(self): +    void draw() const { 
-        return (self.x, self.y)+      reader_ptr->drawBMP(picture, *tft_ptr, pos.x * 16pos.y * 16)
 +    }
  
-class Man: +    Pos getPos() const { 
-    def __init__(self, tft, x, y): +      return pos; 
-        self.tft = tft +    }
-        self.x = x +
-        self.y = y +
-        self.picture = 'man.bmp' +
-        self.draw()+
  
-    def draw(self): +    void setPos(Pos _pos 
-        self.tft.draw_bmp(self.x * 16,self.y * 16, self.picture)+      tft_ptr->fillRect(pos.x * 16, pos.y * 16, 16, 16, ST77XX_BLACK); 
 +      pos.x = _pos.x; 
 +      pos.y = _pos.y; 
 +      draw()
 +    } 
 +};
  
-    def getPos(self): +const int boxes_number = 3; 
-        return (self.xself.y)+Box boxes[boxes_number] = { 
 +  {&tft&reader, 3, 4}, 
 +  {&tft, &reader, 4, 6}, 
 +  {&tft, &reader, 2, 7},   
 +};
  
-    def setPos(selfxy): +const int gates_number = 3; 
-        self.tft.rect(self.x * 16self.y * 161616tft.COLOR_BLACK) +Gate gates[gates_number] = { 
-        self.x = x +  {&tft&reader, 6, 3}
-        self.y = y +  {&tft, &reader64}
-        self.draw()+  {&tft, &reader, 6, 5},   
 +};
  
-# init TFT +Man man(&tft, &reader56);
-tft.initr(tft.BGR) # tft.initr(tft.RGB) #Если вместо синего цвета отображается красныйа вместо красного синий +
-tft.clear(tft.COLOR_BLACK) #bgr+
  
-x = 0 +void setup() { 
-y = 0+  Serial.begin(9600); 
 +  Serial.println(); 
 +  Serial.println("Setup"); 
 +  LittleFS.begin(); 
 +  tft.initR(INITR_BLACKTAB); 
 +  tft.setRotation(2); 
 +  tft.fillScreen(ST77XX_BLACK); 
  
-for row in Map: +  for (int y = 0; y < 10; y++) { 
-    for col in row: +    for (int x = 0; x < 10; x++) { 
-        if col: +      if (Map[y][x]) reader.drawBMP("/brick.bmp", tft, x * 16, y * 16); 
-            tft.draw_bmp(x * 16, y * 16,'brick.bmp') +    
-        x+=1 +  }  
-    x=0 +   
-    y+=1+  for (int i = 0; i < boxes_number; i++) { 
 +    boxes[i].draw(); 
 +  }
  
-Boxes.append(Box(tft, 3,4)+  for (int i = 0; i < gates_number; i++{ 
-Boxes.append(Box(tft, 4,6)+    gates[i].draw(); 
-Boxes.append(Box(tft, 2,7))+  } 
 +   
 +  man.draw()
 +}
  
-Gates.append(Gate(tft, 6,3)+void loop() { 
-Gates.append(Gate(tft, 6,4)) +}
-Gates.append(Gate(tft, 6,5)) +
- +
-man = Man(tft, 5, 6)+
 </file> </file>
  
-Для хранения объектов целей и ящиков создаем массивы+Создаем массив объектов — ящиков c координатами: 3, 4; 4, 6; 2, 7.  
-<code python[enable_line_numbers="2", start_line_numbers_at="28"]> +<code arduino[enable_line_numbers="2", start_line_numbers_at="131"]> 
-Gates [] +const int boxes_number 3; 
-Boxes = []+Box boxes[boxes_number= { 
 +  {&tft, &reader, 3, 4}, 
 +  {&tft, &reader, 4, 6}, 
 +  {&tft, &reader, 2, 7},   
 +};
 </code> </code>
  
-Создаем три объекта ящиков с координатами 3,4; 4,и 2,7: +Создаем массив объектов — целей c координатами: 6, 3; 6, 4; 6, 5.  
-<code python[enable_line_numbers="2", start_line_numbers_at="110"]> +<code arduino[enable_line_numbers="2", start_line_numbers_at="138"]> 
-Boxes.append(Box(tft, 3,4)) +const int gates_number = 3; 
-Boxes.append(Box(tft, 4,6)) +Gate gates[gates_number] = { 
-Boxes.append(Box(tft, 2,7))+  {&tft, &reader, 6, 3}
 +  {&tft, &reader, 6, 4}, 
 +  {&tft, &reader6, 5},   
 +};
 </code> </code>
  
-Оператор ''append'' добавляет элементы в конец массива.  +Создаем кладовщика
- +<code arduino[enable_line_numbers="2", start_line_numbers_at="145"]> 
-Создаем объекты целей+Man man(&tft, &reader5, 6);
-<code python[enable_line_numbers="2", start_line_numbers_at="114"]> +
-Gates.append(Gate(tft, 6,3)) +
-Gates.append(Gate(tft, 6,4)) +
-Gates.append(Gate(tft, 6,5))+
 </code> </code>
  
-Создаем кладовщика: +Вызываем метод ''draw()'' для элементов массивов ящиков и целей, и для кладовщика. 
-<code python[enable_line_numbers="2", start_line_numbers_at="118"]> +<code arduino[enable_line_numbers="2", start_line_numbers_at="162"]> 
-man Man(tft, 5, 6)+  for (int i 0; i < boxes_number; i++) { 
 +    boxes[i].draw(); 
 +  } 
 + 
 +  for (int i = 0; i < gates_number; i++) { 
 +    gates[i].draw(); 
 +  } 
 +   
 +  man.draw();
 </code> </code>
  
 Теперь мы имеем игровое поле с лабиринтом, кладовщика, ящики и цели. В следующем эксперименте мы научим кладовщика двигаться при нажатиях на кнопки. Теперь мы имеем игровое поле с лабиринтом, кладовщика, ящики и цели. В следующем эксперименте мы научим кладовщика двигаться при нажатиях на кнопки.