Показаны различия между двумя версиями страницы.
| Следующая версия | Предыдущая версия | ||
| products:laboratory_iot_c:exp55 [2024/12/15 17:45] – создано labuser30 | products:laboratory_iot_c:exp55 [2024/12/15 18:04] (текущий) – [Программный код эксперимента] labuser30 | ||
|---|---|---|---|
| Строка 14: | Строка 14: | ||
| ==== Программный код эксперимента ==== | ==== Программный код эксперимента ==== | ||
| - | < | + | < |
| - | from machine import Pin, SPI | + | #include <SPI.h> |
| - | from tft import TFT_GREEN | + | #include < |
| - | _init() | + | #include " |
| - | machine.freq(160000000) | + | |
| - | dc = Pin(4, Pin.OUT) | + | #define PIN_CS |
| - | cs = Pin(2, Pin.OUT) | + | #define PIN_DC |
| - | rst = Pin(5, Pin.OUT) | + | #define PIN_RST |
| - | spi = SPI(1, baudrate=40000000, | + | |
| - | tft = TFT_GREEN(128, 160, spi, dc, cs, rst, rotate=0) | + | Adafruit_ST7735 |
| + | LittleFS_ImageReader reader; | ||
| - | Map = [ | + | bool Map[10][8] = { |
| - | | + | {1, |
| - | [0, | + | {0, |
| - | [1, | + | {1, |
| - | [0, | + | {0, |
| - | [0, | + | {0, |
| - | [1, | + | {1, |
| - | [1, | + | {1, |
| - | [1, | + | {1, |
| - | [1, | + | {1, |
| - | [1, | + | {1, |
| - | ] | + | }; |
| - | Gates = [] | + | struct Pos { |
| - | Boxes = [] | + | int x = 0; |
| + | int y = 0; | ||
| - | class Box: | + | bool operator == (const Pos &pos) const { |
| - | | + | |
| - | self.tft | + | } |
| - | self.x = x | + | }; |
| - | self.y = y | + | |
| - | self.picture | + | |
| - | | + | |
| - | | + | |
| - | self.draw() | + | |
| - | def draw(self): | + | class Box { |
| - | if (self.onGate): | + | |
| - | | + | |
| - | else: | + | LittleFS_ImageReader |
| - | self.tft.draw_bmp(self.x * 16,self.y * 16, self.picture) | + | Pos pos; |
| + | | ||
| + | String picture_on_gate = "/ | ||
| + | bool on_gate = false; | ||
| - | def setOnGate(self, state): | + | public: |
| - | | + | Box(Adafruit_ST7735 *_tft_ptr, LittleFS_ImageReader *_reader_ptr, |
| + | tft_ptr = _tft_ptr; | ||
| + | reader_ptr = _reader_ptr; | ||
| + | pos.x = x; | ||
| + | pos.y = y; | ||
| + | } | ||
| + | |||
| + | void draw() { | ||
| + | if (on_gate) reader_ptr-> | ||
| + | else reader_ptr-> | ||
| + | } | ||
| + | |||
| + | void setOnGate(bool | ||
| + | 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 getOnGate(self): | + | class Gate { |
| - | | + | private: |
| + | | ||
| + | LittleFS_ImageReader *reader_ptr; | ||
| + | Pos pos; | ||
| + | String picture | ||
| - | def getPos(self): | + | public: |
| - | | + | Gate(Adafruit_ST7735 *_tft_ptr, LittleFS_ImageReader *_reader_ptr, |
| + | tft_ptr = _tft_ptr; | ||
| + | reader_ptr = _reader_ptr; | ||
| + | pos.x = x; | ||
| + | pos.y = y; | ||
| + | } | ||
| - | | + | |
| - | self.x = x | + | reader_ptr-> |
| - | self.y = y | + | |
| - | | + | |
| - | class Gate: | + | Pos getPos() const { |
| - | def __init__(self, tft, x, y): | + | |
| - | | + | } |
| - | | + | }; |
| - | | + | |
| - | self.picture = ' | + | |
| - | self.draw() | + | |
| - | def draw(self): | + | class Man { |
| - | | + | private: |
| + | | ||
| + | LittleFS_ImageReader | ||
| + | Pos pos; | ||
| + | String | ||
| - | def getPos(self): | + | public: |
| - | | + | Man(Adafruit_ST7735 *_tft_ptr, LittleFS_ImageReader *_reader_ptr, |
| + | | ||
| + | tft_ptr = _tft_ptr; | ||
| + | reader_ptr = _reader_ptr; | ||
| + | pos.x = x; | ||
| + | pos.y = y; | ||
| + | } | ||
| - | class Man: | + | void draw() const { |
| - | def __init__(self, tft, x, y): | + | |
| - | | + | } |
| - | self.x = x | + | |
| - | self.y = y | + | |
| - | self.picture = ' | + | |
| - | self.draw() | + | |
| - | | + | |
| - | | + | |
| + | } | ||
| - | | + | |
| - | | + | |
| + | pos.x = _pos.x; | ||
| + | pos.y = _pos.y; | ||
| + | draw(); | ||
| + | } | ||
| + | }; | ||
| - | def setPos(self, x, y): | + | class Button { |
| - | | + | private: |
| - | | + | int pin; |
| - | | + | bool pressState; |
| - | | + | bool oldState; |
| + | |||
| + | public: | ||
| + | Button(int _pin, bool _pressState) { | ||
| + | pin = _pin; | ||
| + | setPinMode(); | ||
| + | | ||
| + | oldState = not _pressState; | ||
| + | } | ||
| + | |||
| + | bool onPress() { | ||
| + | bool state = digitalRead(pin); | ||
| + | if (state != oldState){ | ||
| + | | ||
| + | | ||
| + | } | ||
| + | return false; | ||
| + | } | ||
| - | class Button: | + | void setPinMode() const { |
| - | def __init__(self, p, pressSate): | + | |
| - | self.pin = Pin(p, Pin.IN) | + | |
| - | self.pressSate = pressSate | + | }; |
| - | self.oldState = 0 | + | |
| - | + | ||
| - | def onPress(self): | + | |
| - | state = self.pin.value() | + | |
| - | if state != self.oldState: | + | |
| - | self.oldState = state | + | |
| - | if state == self.pressSate: | + | |
| - | return True | + | |
| - | return False | + | |
| - | tft.initr(tft.BGR) # tft.initr(tft.RGB) #Если вместо синего цвета отображается красный, а вместо красного синий | + | const int boxes_number = 3; |
| - | tft.clear(tft.COLOR_BLACK) | + | Box boxes[boxes_number] = { |
| + | {&tft, & | ||
| + | {&tft, & | ||
| + | | ||
| + | }; | ||
| - | x = 0 | + | const int gates_number |
| - | y = 0 | + | Gate gates[gates_number] |
| + | {&tft, & | ||
| + | {&tft, & | ||
| + | {&tft, & | ||
| + | }; | ||
| - | for row in Map: | + | Man man(&tft, &reader, 5, 6); |
| - | for col in row: | + | |
| - | if col: | + | |
| - | tft.draw_bmp(x * 16, y * 16,' | + | |
| - | x+=1 | + | |
| - | x=0 | + | |
| - | y+=1 | + | |
| - | Boxes.append(Box(tft, 3,4)) | + | Button btn_up(16, HIGH); |
| - | Boxes.append(Box(tft, 4,6)) | + | Button btn_down(15, HIGH); |
| - | Boxes.append(Box(tft, 2,7)) | + | Button btn_left(12, HIGH); |
| + | Button btn_right(0, LOW); | ||
| - | Gates.append(Gate(tft, 6,3)) | + | bool canMove(Pos pos) { |
| - | Gates.append(Gate(tft, 6,4)) | + | if (Map[pos.y][pos.x]) return false; |
| - | Gates.append(Gate(tft, 6,5)) | + | else return true; |
| + | } | ||
| + | |||
| + | int feelBox(Pos pos) { | ||
| + | for (int i = 0; i < boxes_number; | ||
| + | if (boxes[i].getPos() == pos) return i; | ||
| + | } | ||
| + | return -1; | ||
| + | } | ||
| + | |||
| + | bool boxOnGate(Pos pos) { | ||
| + | for (int i = 0; i < gates_number; | ||
| + | if (gates[i].getPos() == pos) return true; | ||
| + | } | ||
| + | return false; | ||
| + | } | ||
| - | man = Man(tft, 5, 6) | + | void setup() { |
| + | Serial.begin(9600); | ||
| + | Serial.println(); | ||
| + | Serial.println(" | ||
| + | LittleFS.begin(); | ||
| + | | ||
| + | tft.setRotation(2); | ||
| + | tft.fillScreen(ST77XX_BLACK); | ||
| - | btnUp = Button(16, 1) | + | for (int y = 0; y < 10; y++) { |
| - | btnDown | + | for (int x = 0; x < 10; x++) { |
| - | btnLeft = Button(12, 1) | + | |
| - | btnRight = Button(0, 0) | + | } |
| + | } | ||
| - | def canMove(x,y): | + | for (int i = 0; i < boxes_number; |
| - | | + | |
| - | return False | + | } |
| - | else: | + | |
| - | | + | |
| - | def feelBox(x,y): | + | for (int i = 0; i < gates_number; |
| - | | + | |
| - | if B.getPos() == (x,y): | + | } |
| - | return B | + | |
| - | return False | + | man.draw(); |
| - | def boxFeelGate(x, | + | btn_left.setPinMode(); |
| - | for G in Gates: | + | } |
| - | if G.getPos() == (x,y): | + | |
| - | return True | + | |
| - | | + | |
| - | while True: | + | void loop() { |
| - | | + | Pos man_pos |
| - | | + | Pos new_pos |
| + | Pos new_pos_next = {-1, -1}; | ||
| - | | + | |
| - | | + | |
| - | | + | |
| + | } | ||
| - | | + | |
| - | | + | |
| - | | + | |
| + | } | ||
| - | | + | |
| - | | + | |
| - | | + | |
| + | } | ||
| - | | + | |
| - | | + | |
| - | | + | |
| + | } | ||
| - | if newPos != (-1,-1): | + | Pos not_pos |
| - | B = feelBox(newPos[0], | + | |
| - | if B and canMove(newPosNext[0], | + | |
| - | if boxFeelGate(newPosNext[0], | + | |
| - | B.setOnGate(True) | + | |
| - | else: | + | |
| - | B.setOnGate(False) | + | |
| - | B.setPos(newPosNext[0], | + | |
| - | man.setPos(newPos[0], | + | |
| - | if not B and canMove(newPos[0], | + | |
| - | man.setPos(newPos[0], | + | |
| - | for G in Gates: | + | if (!(new_pos == not_pos)) { |
| - | | + | int box = feelBox(new_pos); |
| - | if not (feelBox(gPos[0], gPos[1])) and gPos != man.getPos(): | + | if (box >= 0 && canMove(new_pos_next)) { |
| - | G.draw() | + | if (boxOnGate(new_pos_next)) boxes[box].setOnGate(true); |
| + | else boxes[box].setOnGate(false); | ||
| - | win = 1 | + | boxes[box].setPos(new_pos_next); |
| - | for B in Boxes: | + | man.setPos(new_pos); |
| - | if (not B.getOnGate()): | + | } |
| - | win = 0 | + | |
| - | break | + | if (box == -1 && canMove(new_pos)) man.setPos(new_pos); |
| - | + | ||
| - | if (win): | + | for (int i = 0; i < gates_number; |
| - | tft.draw_bmp(0, 16, 'win.bmp') | + | if (feelBox(gates[i].getPos()) == -1 and !(man.getPos() == gates[i].getPos())) { |
| - | raise SystemExit | + | |
| + | } | ||
| + | } | ||
| + | |||
| + | } | ||
| + | |||
| + | bool win = true; | ||
| + | |||
| + | | ||
| + | { | ||
| + | if (!boxes[i].getOnGate()){ | ||
| + | win = false; | ||
| + | break; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | | ||
| + | } | ||
| </ | </ | ||
| Строка 220: | Строка 306: | ||
| '' | '' | ||
| - | < | + | < |
| - | def canMove(x,y): | + | bool canMove(Pos pos) { |
| - | if (Map[y][x]): | + | if (Map[pos.y][pos.x]) return |
| - | | + | else return |
| - | else: | + | } |
| - | | + | |
| </ | </ | ||
| - | Функция '' | + | Функция '' |
| - | < | + | |
| - | def feelBox(x,y): | + | < |
| - | for B in Boxes: | + | int feelBox(Pos pos) { |
| - | if B.getPos() == (x,y): | + | for (int i = 0; i < boxes_number; |
| - | return | + | if (boxes[i].getPos() == pos) return i; |
| - | | + | } |
| + | | ||
| + | } | ||
| </ | </ | ||
| - | Функция '' | + | Функция '' |
| - | < | + | |
| - | def boxFeelGate(x,y): | + | < |
| - | for G in Gates: | + | bool boxOnGate(Pos pos) { |
| - | if G.getPos() == (x,y): | + | for (int i = 0; i < gates_number; |
| - | | + | if (gates[i].getPos() == pos) return |
| - | return | + | } |
| + | | ||
| + | } | ||
| </ | </ | ||
| Строка 249: | Строка 338: | ||
| Если нажатие было и новая координата определена, | Если нажатие было и новая координата определена, | ||
| - | < | + | < |
| - | | + | |
| </ | </ | ||
| - | Если ящик есть, значит мы должны двигаться вместе с ящиком. Но для этого нужно проверить может ли передвинуться ящик (нет ли стены перед ящиком). | + | Если ящик есть |
| - | <code python[enable_line_numbers=" | + | <code python[enable_line_numbers=" |
| - | if B and canMove(newPosNext[0], | + | if (box >= 0 && |
| </ | </ | ||
| - | Если все в порядке и ящик может передвинуться, | + | Если все в порядке и ящик может передвинуться, |
| После чего передвигаем ящик и кладовщика в новую координату. | После чего передвигаем ящик и кладовщика в новую координату. | ||
| Строка 265: | Строка 354: | ||
| Далее идет вспомогательная логика. В частности мы перерисовываем цели, если на них нет ящика или кладовщика. Это нужно, чтобы после прохождения ящика или кладовщика по цели они прорисовывались заново, | Далее идет вспомогательная логика. В частности мы перерисовываем цели, если на них нет ящика или кладовщика. Это нужно, чтобы после прохождения ящика или кладовщика по цели они прорисовывались заново, | ||
| - | < | + | < |
| - | for G in Gates: | + | for (int i = 0; i < gates_number; |
| - | gPos = G.getPos() | + | if (feelBox(gates[i].getPos()) == -1 and !(man.getPos() |
| - | if not (feelBox(gPos[0], gPos[1])) and gPos != man.getPos(): | + | |
| - | G.draw() | + | } |
| + | } | ||
| </ | </ | ||
| - | Далее идет проверка условия выигрыша. Игра считается выигранной когда все ящики установлены на свои цели. Для этого мы проверяем условие нахождения ящика на цели для каждого ящика. Если у всех ящиков соблюдается данное условие, | + | Далее идет проверка условия выигрыша. Игра считается выигранной когда все ящики установлены на свои цели. Для этого мы проверяем условие нахождения ящика на цели для каждого ящика. Если у всех ящиков соблюдается данное условие, |
| - | < | + | < |
| - | win = 1 | + | |
| - | for B in Boxes: | + | |
| - | if (not B.getOnGate()): | + | |
| - | win = 0 | + | { |
| - | break | + | |
| - | + | win = false; | |
| - | if (win): | + | break; |
| - | tft.draw_bmp(0, 16, 'win.bmp') | + | } |
| - | raise SystemExit | + | } |
| + | |||
| + | | ||
| </ | </ | ||