Электронная игра на базе платы Microbit

Электронная игра на базе платы  MicrobitБыло время, когда каждый ребенок СССР хотел портативную электронную игру типа «Ну погоди» или «Автогонки». Игра сочетала в себе очень простой ЖК-экран с очень простой игровой механикой.
В западных странах тоже были такие электронные игрушки. Выпускались они фирмой Nintendo Game & Watch. Одной из первых была игра Fire, где игрок перемещал страховочную сетку пожарных влево или вправо, чтобы перебросить жителей из горящего здания слева в ожидавшую его машину скорой помощи справа.
Свою игру он назвал Post (почта) и в ней нужно перебрасывать письма слева направо с помощью ракетки.
Инструменты и материалы:-Microbit;-Коммутационная плата;-Макетная плата с шинами питания;-1,3-дюймовый OLED-дисплей 128×64 с поддержкой I²C;-Тактовые кнопки — 2 шт;-Перемычки;-Батарейка 3V;-Держатель для батарейки;
Электронная игра на базе платы  MicrobitШаг первый: программирование
Редактор Mu — это редактор для Micro: bit, по сути — MicroPython для Micro: bit. После установки Mu открываем редактор и подключаем Micro: bit к компьютеру. В левом нижнем углу окна редактора Mu, в строке состояния, должно прописаться подтверждение, что он «обнаружил новое устройство BBC micro: bit».
Затем нужно убедиться, что код Python может быть записан на бит Micro :. В редакторе Mu нажимаем кнопку New, чтобы создать новый файл Python, и вводим следующий простой код:

Набор для быстрого ремонта стекла своими руками
10 часов назад
Съемная тонировка нового поколения - Каркасные шторки TROKOT
9 часов назад

from microbit import *    display.scroll("Hello, World!")

Нажимаем кнопку Flash в редакторе Mu. Желтый светодиод на бите Micro: должен начать мигать, указывая на то, что выполняется файловая операция. Когда операция закончится, Micro: bit должен прокрутить «Hello, World!» на его светодиодном дисплее 5×5.
Электронная игра на базе платы  MicrobitЧтобы Micro: bit отправлял инструкции на OLED-дисплей, нужно установить некоторые библиотеки Python на Micro: bit. Редактор Mu делает это очень просто.
Сначала находим домашний каталог для Mu.
Далее копируем все файлы Python (все файлы с расширением .py) из репозитория fizban на Github и помещаем копии в домашний каталог Mu.
В редакторе Mu нажимаем кнопку Files. Это действие откроет две панели внизу редактора. Слева находятся файлы на Micro: bit — может быть один или несколько файлов, в зависимости от того, что вы делалось ранее с Micro: bit. Справа находятся файлы .py в домашнем каталоге, в том числе файлы ssd1306, которые были скопированы из репозитория fizban.
Перетаскиваем следующие три файла с правой панели ( домашний каталог) на левую панель (бит Micro:), которая ssd1306.py
ssd1306_px.py
ssd1306_text.py
Для этого проекта нам нужны только эти три файла, остальные могут понадобиться в других проектах.
Нажимаем кнопку «Files» еще раз, чтобы удалить нижние панели и снова сделать кнопку «Flash» доступной.
Чтобы узнать, все ли по-прежнему работает нормально, нужно обновить программу Hello.

from ssd1306 import initialize, clear_oled, draw_screen  from ssd1306_px import set_px  from ssd1306_text import add_text  from microbit import *    display.scroll("Import Successful!") 

Загружаем код на Micro: bit. Если на экране прокручивается “Import Successful!”, можно перейти к следующему шагу.
Электронная игра на базе платы  MicrobitШаг второй: подключение коммутационной платы
Внизу Micro: bit находятся 25 контактов (золотая полоска). Пять из них имеют размер, чтобы их можно было использовать с зажимами. Чтобы использовать остальные 20 контактов, нужно вставить Micro: bit в коммутационную плату. Для данного проекта OLED нужна коммутационная плата, которая обеспечивает доступ к контактам 19 и 20, поскольку это контакты, которые реализуют протокол связи I²C.
Можно использовать простую программу Python, чтобы проверить, работает ли коммутационная плата. Ниже представлен код, который просто показывает, была ли нажата кнопка A или кнопка B на бите Micro :.

from ssd1306 import initialize, clear_oled, draw_screen  from ssd1306_px import set_px  from ssd1306_text import add_text  from microbit import *    while True:      display.show('.')      if button_a.was_pressed():          display.show('A')          sleep(500)      elif button_b.was_pressed():          display.show('B')          sleep(500)

Нужно загрузить эту программу в Micro: bit, прежде чем подключать ее к коммутационной плате. При нажатии кнопки A на светодиодном дисплее должно отображается «A», а при нажатии кнопки B на светодиодном дисплее отображается «B».
Дальше устанавливаем Micro: бит в коммутационную плату. В зависимости от платы может загореться светодиод, показывая, что она подключена и получает питание от Micro: bit.
Если мы посмотрим на схему контактов Micro: bit , то увидим, что контакт 5 используется совместно с кнопкой A на Micro: bit, а контакт 11 используется совместно с кнопкой B. Чтобы проверить, работает ли коммутационная плата, вставляем одну перемычку к контакту 5, одну перемычку к контакту 11 и одну перемычку к GND. Если теперь прикоснутся к контакту 5 и проводам GND, мы увидим «A» на светодиодном дисплее, потому что контакт 5 был «сброшен на GND», что аналогично нажатию кнопки A. Прикосновение к контакту 11 и GND покажут на светодиодном дисплее букву B. Это значит, что Micro: bit и коммутационная плата подключены правильно.
Электронная игра на базе платы  MicrobitШаг третий: макетная плата
Хотя этот проект можно было бы реализовать без макетной платы, но ее использование упрощает монтаж.
Электронная игра на базе платы  MicrobitДля большинства проектов Micro: bit питание обеспечивается либо через USB-соединение с компьютером, либо, в качестве альтернативы, путем подключения батареи 3 В к разъему JST.
Для проекта, в котором плата Micro: bit работает с внешними компонентами, коммутационная плата может не обеспечивать достаточное количество соединений 3 В и GND для питания всех внешних компонентов. Можно решить эту проблему, подключив контакт 3V и контакт заземления (GND) к шинам питания макета. Сделать это просто.
-С помощью перемычки подключаем 3 В на коммутационной плате к + силовой шине на макетной плате.
-С помощью перемычки соединяем GND на коммутационной плате с шиной питания на макетной плате.
Электронная игра на базе платы  MicrobitТеперь есть коммутационная плата и макет, позволяющие подключать электронные компоненты к Micro: bit, сначала подключим наш OLED-дисплей.
Устанавливаем OLED-дисплей на макетную плату так, чтобы каждый из его контактов был подключен к отдельной пронумерованной строке. Например, вывод GND подключен к строке 10, а соседний вывод VCC подключен к строке 11 и так далее. Если все контакты OLED находятся в одном пронумерованном ряду, OLED вставлен неправильно и его необходимо повернуть на 90 градусов.
Затем нужно использовать перемычки для подключения каждого вывода OLED к определенным выводам Micro: bit на коммутационной плате:
OLED GND к Micro: бит GND
OLED VCC к Micro: бит 3 В
OLED SCL к Micro: бит, вывод 19
OLED SDA к Micro: бит, вывод 20
Дальше нужно загрузить следующий код Python на Micro: bit. Если все компоненты и все соединения работают, на дисплее будет отображаться “Hello!”.
from ssd1306 import initialize, clear_oled, draw_screen
from ssd1306_px import set_px
from ssd1306_text import add_text
from microbit import *
initialize()
clear_oled()
add_text(0, 0, «Hello!»)
Дальше можно загрузить небольшую программу для проверки отображения пикселей. Хотя OLED имеет разрешение дисплея 128 на 64 пикселя, каждый пиксель крошечный, поэтому библиотека Python ssd1306 использует четыре пикселя каждый раз, когда получает указание рисовать «пиксель» на дисплее. То есть только сетка 64×32. Вот почему в игре такая рудиментарная графика. (Тем не менее, он намного лучше, чем светодиодный дисплей 5×5, который есть у Micro: bit.)

Быстрая прохлада с Мини USB кондиционер AICOK
8 часов назад
Инновационное тональное средство с антивозрастным эффектом
9 часов назад

from ssd1306 import initialize, clear_oled, draw_screen  from ssd1306_px import set_px  from ssd1306_text import add_text  from microbit import *    initialize()  clear_oled()  for y in range(31):      for x in range(63):          set_px(x, y, 1, 0)          draw_screen()

Электронная игра на базе платы  MicrobitДальше переходим к кнопкам. Здесь можно использовать отдельные тактовые кнопки или кнопки на плате Micro: bit. Тактовые кнопки сделают игру более естественной, потому что их можно разместить по обе стороны от OLED-дисплея.
Располагаем каждую кнопку на макетной плате так, чтобы две ножки находились ниже среднего разделителя, а две ножки — выше среднего разделителя. Ножки под средним разделителем не имеют электрического контакта — они для того, чтобы кнопка аккуратно стояла на плате. Ножки над перегородкой подключаются следующим образом:
Для левой кнопки подключаем одну ногу к контакту 5, а другую — к GND;
Для правой кнопки подключаем одну ногу к контакту 11, а другую — к GND.
Если нажата левая кнопка, она закрывает соединение между контактом 5 и GND, что сигнализирует биту Micro: о том, что кнопка A была нажата. При нажатии правой кнопки соединение между контактом 11 и GND замыкается, что сигнализирует биту Micro: о том, что кнопка B была нажата.
Для тестирования используем следующий код.

from ssd1306 import initialize, clear_oled, draw_screen  from ssd1306_px import set_px  from ssd1306_text import add_text  from microbit import *    initialize()    while True:      clear_oled()      add_text(0, 0, "...")      if button_a.was_pressed():          clear_oled()          add_text(0, 0, "LEFT button")          add_text(0, 1, "was pressed")      elif button_b.was_pressed():          clear_oled()          add_text(0, 0, "RIGHT button")          add_text(0, 1, "was pressed")      sleep(1000)

Электронная игра на базе платы  MicrobitШаг четвертый: код
Изначально на экране отображаются два конверта, которые необходимо ловить. Конверты падают с определенной скорость. По мере игры, интервал между падением конвертов уменьшается и наступает момент, когда на экране находятся три конверта одновременно.
За каждый пойманный конверт начисляются очки, если пропустить три конверта, то игра заканчивается.
Электронная игра на базе платы  MicrobitИзначально предполагалось, что игра должна иметь гораздо более богатую графику. Какой бы объект ни отскакивал слева направо по экрану, он менял бы форму в каждой точке траектории — точно так же, как в оригинальных играх Nintendo Game & Watch.
Реализация такой графики усложнила код и в итоге мастер решил оставить одну форму.
Электронная игра на базе платы  MicrobitПолный код можно скачать ниже.

import math  import music  import random  from ssd1306 import initialize, clear_oled, draw_screen  from ssd1306_px import set_px  from ssd1306_text import add_text  from microbit import reset, button_a, button_b, display, sleep, i2c, Image    version = 0     # set to positive to show on title screen  limitX = 63     # the last visible pixel location at the right  limitY = 31     # the last visible pixel location at the bottom  letterW = 12    # the width of the letter sprite  letterH = 8     # the height of the letter sprite  delay = 150     # the delay after each play loop ... slowly decreases  min_delay = 40  # the minimum delay after each play loop  paddle = 2      # the position of the paddle, either 0, 1, or 2  fails = 0       # the number of times the letter fell to the floor  score = 0       # the number of times the paddle hit a letter  chance = 40     # the 'range' of chances to launch a letter  traj = []       # the list of trajectory positions  bottoms = []    # the index of each bottom-of-trajectory positions  letter = ""     # will hold the binary values for the letter sprite  lett_pos = []   # the list of positions of the three letters  titleI = 0      # Y position index of bouncing letter on title screen    # Expands each hex value into a single array of bits.  # Example: expand "909" into array of 100100001001  def hex_to_bits(definition):      bits = []      for line in definition:          for hex in line:              for char in '{:0>{w}}'.format(bin(int(hex, 16))[2:], w=4):                  bit = 1 if char == '1' else 0                  bits.append( bit )      return bits    # Shows or hides the letter sprite.  def update_sprite(sprite, x, y, width, height, visible):      for offy in range(height):          for offx in range(width):              if sprite[offy*letterW + offx] == 1:                  if x+offx <= limitX and y+offy <= limitY:                      set_px(x+offx, y+offy, visible, 0)    # Shows or hides the paddle.  def update_paddle(index, visible):      x = [ 8, 28, 48 ][index]      y = limitY - 6      for offx in range(letterW+4):          set_px(x + offx, y, visible, 0)          set_px(x + offx, y+1, visible, 0)    # Builds the trajectory of bounces, and records bottom positions  # (where the player's paddle will need to be).  def build_traj():      global traj, bottoms, traj_count      append_bounce(-4)      bottoms.append(len(traj)-1)      append_bounce(6)      bottoms.append(len(traj)-1)      append_bounce(16)      bottoms.append(len(traj)-1)      append_bounce(26)      traj_count = len(traj)    # Adds an up and down arc to the trajectory.  def append_bounce(x):      if x >= 0:          traj.extend( [ [x, 10], [x+1, 6], [x+2, 2] ] )      traj.extend( [ [x+4, 0], [x+6, 2], [x+7, 6], [x+8, 10], [x+9, 16] ] )    # To launch a new letter, the following must be true:  #    1) The letters at pos1 and pos2 are either:  #         a) not launched, or  #         b) are at least 8 steps away, and not at the top of the arc  #            (so no two letters at the same pos in the arc)  #    2) The number 2 is chosen randomly from within a range.  #       The range decreases from 40 to 3, so the game starts launching  #       letters slowly, a later launches letters more often.  def can_launch(pos1, pos2):      global chance      if is_away(pos1) and is_away(pos2):          if chance > 3.2:              chance = chance - .2          return random.randrange(0, math.floor(chance)) == 2      return False    # Determines if the position means another letter can be launched.  def is_away(pos):      if pos < 0:          return True      if pos >= 100:          return False      if pos > 8:          return traj[pos][1] != 0 # not at top of bounce      return False    # Shows or hides the title screen  def set_title(state):      title = "POST"      left = 2      if version > 0:          title = title + " v." + str(version)          left = 0      add_text(left, 2, title)      update_paddle(2, 1)    def update_title(y):      bounce = [16,10,6,2,0,2,6,10]      last = y-1      if last < 0:          last = len(bounce) - 1      update_sprite(letter, 50, bounce[last], letterW, letterH, 0)      update_sprite(letter, 50, bounce[y], letterW, letterH, 1)      next = y + 1      if next > len(bounce) - 1:          return 0      return next    # Shows or hides the message to "Get ready".  def set_ready(state):      if state == 1:          add_text(2, 0, "Get ready")      else:          for x in range(64):              for y in range(10):                  set_px(x, y, 0, 0)    # Moves the player's paddle either left or right.  def move_paddle(offset):      global paddle      update_paddle(paddle, 0)      paddle = paddle + offset      update_paddle(paddle, 1)    # Called when the player misses a letter.  def on_fail():      global fails      music.pitch(200, 500, wait=False)      fails = fails + 1      show_fails(fails)      if fails >= 3:          game_over()          return True      return False    # Called when the player has missed three letters.  def game_over():      clear_oled()      add_text(2, 0, "GAME OVER!")      add_text(2, 2, "Score: " + str(score))    # Called when a letter hits the player's paddle.  def on_success():      global score, delay      score = score + 1      if delay > min_delay:          delay = delay - 2      music.stop()      music.pitch(600, 1)    # Uses Microbit's LED to show the number of fails.  def show_fails(count):      leds = "00000:00000:0"      for i in range (count):          leds = leds + "9"      for i in range (count, 3):          leds = leds + "0"      leds = leds + "0:00000:00000"      display.show(Image(leds))    # Shows a dotted line when the player misses a letter  def show_splat(pos):      x = traj[pos-100][0] * 2      for i in range (0, letterW, 2):          set_px(x+i, limitY, 1, 0)    # Removes any dotted lines indicating a missed letter  def hide_splats():      for i in range (64):          set_px(i, limitY, 0, 0)    # Moves the letter to the next position in the trajectory  def move_letter(index):      global lett_pos      index1 = get_index(index, -1)      index2 = get_index(index, 1)      if lett_pos[index] >= 0 and lett_pos[index] < 100:          lett_pos[index] = get_next(lett_pos[index])    # Gets the next position in the trajectory.  def get_next(t):      if t >= 0 and t < traj_count-1:          return t + 1      return -1    # If the letter is not in a trajectory, it may be launched  def launch_letter(index):      global lett_pos, started      index1 = get_index(index, -1)      index2 = get_index(index, 1)      if lett_pos[index] < 0 or lett_pos[index] >= 100:          if can_launch(lett_pos[index1], lett_pos[index2]):              lett_pos[index] = 0              if not started:                  set_ready(0)                  started = True    # Gets the index of the previous or next letter.  def get_index(index, offset):      index = index + offset      if index < 0:          return 2      if index > 2:          return 0      return index    # Restarts the program, returning to the title screen  def restart():      a = button_a.was_pressed()      b = button_b.was_pressed()      sleep(200)      reset()    # Initialize the game  letter = hex_to_bits( "fff:a05:909:891:861:801:801:fff".split(':'))  lett_pos = [ -1, -1, -1 ]  build_traj()  initialize()  clear_oled()  set_title(1)  opened = False        # has the user pressed a button on the title screen?  started = False       # has the game started? (used to clear "Get ready" prompt)  playing = True        # is the game underway; if not, the game has finished  move_letters = False  # do we move the letters in the current game turn?    # Show the title screen  while not opened:      titleI = update_title(titleI)      draw_screen()      sleep(delay)      if button_a.was_pressed() or button_b.was_pressed():          opened = True  clear_oled()  set_ready(1)  update_paddle(paddle, 1)  draw_screen()    # Start playing the game, where the player can move the paddle each turn,  # whereas the letters move every second turn.  (The paddle must move twice  # as fast as the letters, so the player can save every letter.)  while playing:      refresh = False # whether a screen redraw is needed        if button_a.was_pressed():          if paddle > 0:              move_paddle(-1)              refresh = True;      elif button_b.was_pressed():          if paddle < 2:              move_paddle(1)              refresh = True;        if move_letters:          for i in range(len(lett_pos)):              pos = lett_pos[i]              if pos >= 100: # indicates that the letter was missed by the player                  lett_pos[i] = -1 # available to be launched again later                  update_sprite(letter, traj[pos-100][0] * 2, traj[pos-100][1], letterW, letterH, 0)                  refresh = True                  if on_fail():                      playing = False                      refresh = False                  else:                      show_splat(pos)              else:                  if pos > 0:  # the sprite needs to be 'removed' from its last position                      update_sprite(letter, traj[pos-1][0] * 2, traj[pos-1][1], letterW, letterH, 0)                      refresh = True                  if pos >= 0: # the sprite needs to be drawn on the screen                      refresh = True                      update_sprite(letter, traj[pos][0] * 2, traj[pos][1], letterW, letterH, 1)                      if pos in bottoms: # is the letter at the bottom?                          if bottoms.index(pos) == paddle: # is the paddle at the same position?                              on_success()                          else:                              lett_pos[i] = 100 + pos # player missed the letter        if playing:            if refresh:              draw_screen()            if move_letters:              move_letter(0)              move_letter(1)              move_letter(2)              launch_letter(0)              launch_letter(1)              launch_letter(2)            sleep(delay)            if not move_letters:              hide_splats()              draw_screen()            move_letters = move_letters == False        else:            while not button_a.was_pressed() and not button_b.was_pressed():              sleep(150)          restart()

microbit-post-game.py
Электронная игра на базе платы  MicrobitШаг пятый: печатная плата и корпус
Макетная плата позволяет очень легко монтировать и тестировать схему, но она не идеальна для готового продукта. Чтобы получить меньший форм-фактор с большей стабильностью, можно сделать схему на макете печатной платы (PCB).
Для этого необходимо припаять компоненты и провода к плате. На изображении ниже, слева показана исходная макетная версия, а справа — версия печатной платы.
Электронная игра на базе платы  MicrobitПоследнее что нужно сделать — это корпус. Для корпуса можно приспособить любую подходящую коробку или сделать ее самому.
Электронная игра на базе платы  Microbit

Умные часы Smart Watch V8 + Power Bank и наушники в подарок
7 часов назад
Инновационное тональное средство с антивозрастным эффектом
8 часов назад

Читайте также