Показаны сообщения с ярлыком игра. Показать все сообщения
Показаны сообщения с ярлыком игра. Показать все сообщения

суббота, 13 февраля 2016 г.

EV3 Саймон сказал

Что может быть лучше простых, но фановых проектов? Прошедшие пару недель мы работали над EV3-версией игры "Саймон сказал". В этой игре компьютер задумывает последовательность сущностей (действий, цветов, звуков), которые игрок должен повторить. Последовательность удлиняется при каждом правильном ходе игрока.


Если вы помните, ранее мы уже собирали "Саймона" из Arduino


Позднее мы добавляли возможность игры "Simon Says" в нашу волшебную лампу


Теперь пришла пора поиграть в игру и на платформе LEGO Mindstorms EV3. Поначалу мы планировали использовать кнопки для взаимодействия с игроком, но честно говоря результат получался скучноватым. Кнопки мы убрали и ограничились всего лишь тремя моторами, которые служат как для вывода последовательностей компьютером, так и для их ввода игроком. Плюсом этого решения можно считать возможность собрать проект как из домашней, так и из образовательной версии EV3.



Инструкцию по сборке (в форматах LDD и PDF) и программу к проекту можно скачать по ссылке

Программа написана на языке EV3 Basic, бесплатной среде программирования для EV3. О том где ее скачать и как установить можно прочитать здесь: Используя EV3 Explorer, входящий в состав EV3 Basic, создайте папку SimonSays и поместите в нее скачанные файлы проекта.

Интересной "фишкой", которую Вы можете рассмотреть в коде, является использование функции MyMotor(), которая реализует поворот мотора в нужную позицию с использованием кубического регулятора и контролем застревания. Так как EV3 Бейсик не поддерживает передачи параметров в функцию мы передаем параметры (какой мотор использовать и в какую позицию его установить) через переменные.

u = 1
M = "A"
P = 0
k = 1
For s = 1 To 20
  a = Math.GetRandomNumber(3)
  b[s] = Math.Round(a) 
EndFor   

Sub MyMotor
  t = EV3.Time
  regulator = "True"
  While regulator
    e = P - Motor.GetCount(M)
    v = e * k
    If M = "C" Then
      v = v * 0.75
    EndIf
    Motor.Start(M,v)
    If Math.Abs(Motor.GetCount(M) - P) < 5 Then
      regulator = "False"
    EndIf
    If  EV3.Time - t > 1000 Then
      regulator = "False"
    EndIf  
  EndWhile
  Motor.Stop(M,"True")
  Program.Delay(200)
  Motor.Stop(M,"False")
EndSub

While "True" 
  
  nextu:  
  
  For z = 1 To u
    If  b[z] = 1 Then
      M = "A"
      P = 50
      Speaker.Note(100, "C5", 150)
      MyMotor()
      M = "A"
      P = 0
      MyMotor()
    EndIf  
    If  b[z] = 2 Then
      M = "B"
      P = 50
      Speaker.Note(100, "D5", 150)
      MyMotor()
      M = "B"
      P = 0
      MyMotor()
    EndIf
    If  b[z] = 3 Then
      M = "C"
      P = -40
      Speaker.Note(100, "E5", 150)
      MyMotor()
      M = "C"
      P = 0
      MyMotor()
    EndIf    
  EndFor
  
  For w = 1 To u
    While Motor.GetCount("A") < 40 And Motor.GetCount("B") < 40 And Motor.GetCount("C") > -40
    EndWhile
    
    Program.Delay(200)
    
    If Motor.GetCount("A") > 40 Then
      If b[w] = 1 Then
        Speaker.Note(100, "C5", 150)
        Speaker.Wait()
      EndIf
      M = "A"
      P = 0
      MyMotor()      
      If b[w] <> 1 Then
        Speaker.Note(100, "C4", 300)
        M = "A"
        P = -50
        MyMotor()
        Speaker.Note(100, "C4", 300)
        M = "A"
        P = 0
        MyMotor()        
        Goto nextu
      EndIf        
    EndIf
    
    If Motor.GetCount("B") > 40 Then
      If b[w] = 2 Then
        Speaker.Note(100, "D5", 150)
        Speaker.Wait()
      EndIf
      M = "B"
      P = 0
      MyMotor()
      If b[w] <> 2 Then
        Speaker.Note(100, "C4", 300)
        M = "B"
        P = -50
        MyMotor()
        Speaker.Note(100, "C4", 300)
        M = "B"
        P = 0
        MyMotor()
        Goto nextu      
      EndIf
    EndIf 
    
    If Motor.GetCount("C") < -40 Then
      If b[w] = 3 Then
        Speaker.Note(100, "E5", 150)
        Speaker.Wait()
      EndIf
      M = "C"
      P = 0
      MyMotor()
      If b[w] <> 3 Then
        Speaker.Note(100, "C4", 300)
        M = "C"
        P = 50
        MyMotor()
        Speaker.Note(100, "C4", 300)
        M = "C"
        P = 0
        MyMotor()
        Goto nextu         
      EndIf        
    EndIf 
    
  EndFor
  
  u = u + 1    
  
EndWhile


суббота, 30 января 2016 г.

EV3 НУ ПОГОДИ

Появление EV3 Basic пришлось для нас весьма кстати, наши последние EV3-проекты  стали слишком сложными для того, чтобы получать удовольствие от программирования в EV3-G. И, раз уж мы взялись за текстовое программирование, мы решили сделать что-нибудь стоящее, показывающее явные преимущества данной среды программирования. На глаза попалась электронная игра "Ну, погоди!", в которой волк ловит яйца и мы подумали - почему нет?

Для справки: «Ну, погоди!» («Электроника ИМ-02») —электронная игра, самая известная и популярная из серии первых советских портативных электронных игр с жидкокристаллическим экраном, производимых под торговой маркой «Электроника». Является неофициальным клоном Nintendo EG-26 Egg из серии Nintendo Game & Watch. Производилась с 1984 года





Инструкцию по сборке в двух форматах (LDD и PDF) можно скачать по ссылке. Для работы игры нужен только блок EV3, ИК-датчик и ИК-маяк - все остальное - не обязательные детали корпуса, который Вы можете собрать по своему вкусу.

Все файлы игры нужно скопировать с помощью EV3 Explorer (который входит в состав среды EV3 Basic) в память блока, в предварительно созданную папку volk.

Мы реализовали две версии игры, оригинальную "Волк яйца ловит" (запускать файл volk):



И версию с переработанной графикой, где Самоделкин ловит шестеренки:(запускать файл ks):


На видео ниже можно посмотреть, как работает наша игра:



В программе, которую Вы видите ниже мы используем массивы и параллельные процессы, которые обмениваются между собой информацией. Возможно вам захочется не только скачать и поиграть в нашу игру, но и изучить - как же она устроена:

player = 1
trigger = "True"
last = 0
Speed = 350  
score = 0
game_over = "False"
over = "True"
life = 3
level = 0
LCD.Clear()

Sensor.SetMode(4,2)

Speaker.Play(100,"/home/root/lms2012/prjs/volk/0")
LCD.BmpFile(1,0,0,"/home/root/lms2012/prjs/volk/1")
Speaker.Wait()

' заполняем массивы нужными значениями
For i = 0 To 4
  m1[i] = 0
  m2[i] = 0
  m3[i] = 0
  m4[i] = 0
EndFor

x1[0] = 26
y1[0] = 44
x1[1] = 34
y1[1] = 49
x1[2] = 42
y1[2] = 54
x1[3] = 52
y1[3] = 61
x1[4] = 52
y1[4] = 120

x2[0] = 26
y2[0] = 72
x2[1] = 34
y2[1] = 77
x2[2] = 42
y2[2] = 82
x2[3] = 52
y2[3] = 89
x2[4] = 52
y2[4] = 120

x3[0] = 151
y3[0] = 44
x3[1] = 143
y3[1] = 49
x3[2] = 135
y3[2] = 54
x3[3] = 126
y3[3] = 61
x3[4] = 126
y3[4] = 120

x4[0] = 150
y4[0] = 73
x4[1] = 143
y4[1] = 77
x4[2] = 136
y4[2] = 82
x4[3] = 126
y4[3] = 89
x4[4] = 126
y4[4] = 120

' Запускаем подпроцесы
Thread.Run = logic
Thread.Run = screen
' отрисовка экрана
Sub screen
  While over
    If trigger = "True" Then    
      If player = 1 Then
        LCD.BmpFile(1,0,0,"/home/root/lms2012/prjs/volk/vl1")
      EndIf
      
      If player = 2 Then
        LCD.BmpFile(1,0,0,"/home/root/lms2012/prjs/volk/vl2")
      EndIf
      
      If player = 3 Then
        LCD.BmpFile(1,0,0,"/home/root/lms2012/prjs/volk/vl3")
      EndIf
      
      If player = 4 Then
        LCD.BmpFile(1,0,0,"/home/root/lms2012/prjs/volk/vl4")
      EndIf
      
      
      For i = 0 To 4
        If m1[i] > 0 Then
          LCD.FillCircle(1,x1[i],y1[i],3)
        EndIf
        
        If m2[i] > 0 Then
          LCD.FillCircle(1,x2[i],y2[i],3)
        EndIf
        
        If m3[i] > 0 Then
          LCD.FillCircle(1,x3[i],y3[i],3)
        EndIf
        
        If m4[i] > 0 Then
          LCD.FillCircle(1,x4[i],y4[i],3)
        EndIf  
      EndFor
      
      LCD.Text(1,40,34,1,"Life-" + life + "   " + score)
      
      If game_over = "True" Then
        LCD.BmpFile(1,0,0,"/home/root/lms2012/prjs/volk/GO")
        Speaker.Note(100,"E4",3000)
        Speaker.Wait()
        Speaker.Note(100,"D4",3000)
        Speaker.Wait()
        Speaker.Note(100,"C4",3000)
        Speaker.Wait()
        Program.End()
      EndIf
      
      trigger = "False"
    EndIf
    
  EndWhile
EndSub
' процедура обработки яйца
Sub logic
  While over
    ' процедура увеличивания сложности игры
    Speed = 1000 / (0.03*score+1)
    
    ' процедура рождения яйца
    If EV3.Time > (last + (Speed*2)) Then
      If m1[0] = 0 And m1[1] = 0 And Math.Round(Math.GetRandomNumber(100)) = 10 Then
        m1[0] = EV3.Time
        last = m1[0]
        trigger = "True"
      EndIf
    EndIf
    
    If EV3.Time > (last + (Speed*2)) Then
      If m2[0] = 0 And m2[1] = 0  And Math.Round(Math.GetRandomNumber(100)) = 20 Then
        m2[0] = EV3.Time
        last = m2[0]
        trigger = "True"
      EndIf 
    EndIf
    
    If EV3.Time > (last + (Speed*2)) Then    
      If m3[0] = 0 And m3[1] = 0  And Math.Round(Math.GetRandomNumber(100)) = 30 Then
        m3[0] = EV3.Time
        last = m3[0]
        trigger = "True"
      EndIf 
    EndIf
    
    If EV3.Time > (last + (Speed*2)) Then      
      If m4[0] = 0 And m4[1] = 0  And Math.Round(Math.GetRandomNumber(100)) = 40 Then
        m4[0] = EV3.Time
        last = m4[0]
        trigger = "True"
      EndIf  
    EndIf
    
    ' цикл для перемещения яйца
    For i = 0 To 4
      If m1[i]  <> 0 And m1[i] + (Speed*(i+1)) < EV3.Time Then
        m1[i+1] = m1[i]
        m1[i] = 0 
        trigger = "True"
        Speaker.Note(100,"C4",150)
      EndIf
      
      If m2[i]  <> 0 And m2[i] + (Speed*(i+1)) < EV3.Time Then
        m2[i+1] = m2[i]
        m2[i] = 0
        trigger = "True"
        Speaker.Note(100,"C4",150)
      EndIf
      
      If m3[i]  <> 0 And m3[i] + (Speed*(i+1)) < EV3.Time Then
        m3[i+1] = m3[i]
        m3[i] = 0
        trigger = "True"
        Speaker.Note(100,"C4",150)
      EndIf
      
      If m4[i]  <> 0 And m4[i] + (Speed*(i+1)) < EV3.Time Then
        m4[i+1] = m4[i]
        m4[i] = 0
        trigger = "True"
        Speaker.Note(100,"C4",150)
      EndIf
    EndFor
    ' Проверка на забирание яйца
    
    If m1[3] > 0 And player = 1 And m1[3] + (Speed*3.5) < EV3.Time Then
      score = score+1
      m1[3] = 0
      trigger = "True"
      Speaker.Note(100,"C5",250)
    EndIf
    
    If m2[3] > 0 And player = 2 And m2[3] + (Speed*3.5) < EV3.Time Then
      score = score+1
      m2[3] = 0
      trigger = "True"
      Speaker.Note(100,"C5",250)
    EndIf
    
    If m3[3] > 0 And player = 3 And m3[3] + (Speed*3.5) < EV3.Time Then
      score = score+1
      m3[3] = 0
      trigger = "True"
      Speaker.Note(100,"C5",250)
    EndIf
    
    If m4[3] > 0 And player = 4 And m4[3] + (Speed*3.5) < EV3.Time Then
      score = score+1
      m4[3] = 0
      trigger = "True"
      Speaker.Note(100,"C5",250)
    EndIf
    ' Проверяем не упалоли яйцо
    
    If m1[4] > 0 Then
      Program.Delay(1500)
      Speaker.Note(100,"E4",500)
      Speaker.Wait()
      Speaker.Note(100,"D4",250)
      Speaker.Wait()
      Speaker.Note(100,"C4",250)
      Speaker.Wait()
      
      life = life - 1
      If life = 0 Then
        game_over = "True"
      EndIf
      m1[4] = 0
      trigger = "True"
      Program.Delay(1500)
    EndIf
    
    If m2[4] > 0 Then
      Program.Delay(1500)
      Speaker.Note(100,"E4",500)
      Speaker.Wait()
      Speaker.Note(100,"D4",250)
      Speaker.Wait()
      Speaker.Note(100,"C4",250)
      Speaker.Wait()
      
      life = life - 1
      If life = 0 Then
        game_over = "True"
      EndIf
      m2[4] = 0
      trigger = "True"
      Program.Delay(1500)
    EndIf
    
    If m3[4] > 0 Then
      Program.Delay(1500)
      Speaker.Note(100,"E4",500)
      Speaker.Wait()
      Speaker.Note(100,"D4",250)
      Speaker.Wait()
      Speaker.Note(100,"C4",250)
      Speaker.Wait()
      
      life = life - 1
      If life = 0 Then
        game_over = "True"
      EndIf
      m3[4] = 0
      trigger = "True"
      Program.Delay(1500)
    EndIf
    
    If m4[4] > 0 Then
      Program.Delay(1500)
      Speaker.Note(100,"E4",500)
      Speaker.Wait()
      Speaker.Note(100,"D4",250)
      Speaker.Wait()
      Speaker.Note(100,"C4",250)
      Speaker.Wait()
      
      life = life - 1
      If life = 0 Then
        game_over = "True"
      EndIf
      m4[4] = 0
      trigger = "True"
      Program.Delay(1500)
    EndIf
  EndWhile
EndSub
' процедура считывания покозаний ИК-датчика

Speaker.Note(100,"E4",1000)
Speaker.Wait()
Speaker.Note(100,"D4",1000)
Speaker.Wait()        

While over
  If Sensor.ReadRawValue(4,0) = 1 Then
    If player <> 1 Then
      player = 1
      trigger = "True"
    EndIf
  EndIf
  
  If Sensor.ReadRawValue(4,0) = 2 Then
    If player <> 2 Then
      player = 2
      trigger = "True"
    EndIf
  EndIf
  
  If Sensor.ReadRawValue(4,0) = 3 Then
    If player <> 3 Then
      player = 3
      trigger = "True"
    EndIf
  EndIf
  
  If Sensor.ReadRawValue(4,0) = 4 Then
    If player <> 4 Then
      player = 4
      trigger = "True"
    EndIf
  EndIf

EndWhile

суббота, 26 декабря 2015 г.

"Охота на Вампуса" из EV3 Home #31313

Мы переработали программу и конструкцию в нашем проекте EV3 "Охота на Вампуса" и теперь его можно собрать из домашнего набора EV3.


Скачать инструкцию по сборке и программу можно здесь.

Датчики подключаются следующим образом:
  • Порт 1. ИК-датчик отслеживает включенный маяк, это "направление вашего взгляда" в мире игры, поворот разворачивает персонажа
  • Порт 3. Датчик-кнопка используется для выстрела (для указания команды выстрела и последующего спуска тетивы после указания маршрута стрелы)
  • Порт 2. Цвето-световой датчик в режиме кнопки служит для перемещения "в направлении взгляда"

Мотор для спуска тетивы - порт А.




суббота, 19 декабря 2015 г.

EV3 Hunt the Wumpus. Игра "Охота на Вампуса"


Кто такой Вампус и зачем на него охотиться?




Hunt the Wumpus («Охота на Вампуса») — классическая текстовая компьютерная игра, написанная Грегори Йобом в 1972 году. Цель этой игры заключалась в том, чтобы, путешествуя по лабиринту, найти Вампуса и застрелить его. Часто саму игру называют просто «Вампусом». Вампус — фантастический большой и опасный монстр, обитающий в пещерах. Вампус источает отвратительный запах, имеет крайне чувствительный слух и питается людьми. Известно также, что Вампус очень тяжёл, ноги его имеют присоски, а сам он большую часть времени проводит в спячке.



Мир «Hunt the Wumpus» — это пещера из 20 пронумерованных комнат, каждая из которых соединена тоннелями с тремя другими, т. е. пещера представляет собой расплющенный додекаэдр.



В начале игры персонаж случайным образом оказывается в одной из комнат пещеры. В какой-то из комнат спит Вампус. Задача игрока — найти Вампуса и убить его. За ход он может либо выстрелить в одну из трёх соседних комнат, либо перейти в какую-нибудь из них.

Игрок имеет арбалет с пятью стрелами. Для убийства Вампуса достаточно и одной стрелы. Если стрела попала в Вампуса, то игрок победил и игра окончена. Стрелы у игрока не простые, а волшебные — они могут делать повороты во время полёта. Каждая стрела может пролететь 5 соседних комнат.

Путешествуя по лабиринту, игрок в ходе игры составляет представление о том, как связаны друг с другом комнаты в пещере. 




Стреляя, игрок должен указать номера комнат, через которые пролетит его стрела. Если он ошибётся с номерами комнат и, к примеру, укажет комнаты, не связанные общим тоннелем, то стрела начнёт летать по пещере случайным образом и может даже попасть в самого игрока. Если это произошло, то он проиграл.

Игрок проигрывает и в том случае, если он истратит все 5 стрел, но так и не убьёт Вампуса. Попав в какую-либо комнату, игрок мог почувствовать отвратительный запах, услышать шум или почувствовать сквозняк.


Источником отвратительного запаха является спящий Вампус. Запах чувствуется, если Вампус находится в какой-то из соседних комнат. Сквозняк и шум всегда доносятся из соседней комнаты, но неизвестно, из какой именно. В комнатах, откуда идёт сквозняк, находятся бездонные ямы, попав в которые, игрок погибает и, соответственно, проигрывает. Из 20 комнат в пещере две имеют ямы.

В комнатах, откуда доносится шум (таких комнат в пещере тоже две), обитают гигантские летучие мыши(«super bats»). Если игрок зашёл в комнату к этим мышам, то они хватают его и случайным образом переносят в любую другую комнату в пещере. В том числе, не исключён вариант, что мыши перенесут игрока в комнату с ямой или сбросят его на голову Вампусу.

Вампуса можно разбудить только двумя способами: войдя в комнату, где он спит, или выстрелив из лука в любой из комнат в пещере.

Если игрок окажется в одной комнате с Вампусом, то он проиграл — Вампус съедает его. Если же Вампус проснулся от звуков выстрела в пещере, то у игрока ещё есть шансы.
Проснувшись, Вампус может либо заснуть снова (с вероятностью 0,25), либо перейти спать в одну из соседних комнат. Кстати, комнаты с ямами и летучими мышами Вампусу не страшны. У него на ногах есть присоски, с помощью которых он выбирается из любой ямы, а его огромный вес не даёт гигантским летучим мышам его переносить. Если Вампус отправляется спать в комнату, где находится игрок, то игрок проигрывает, а Вампус получает обед.

Из истории игры


«Охота на Вампуса» — первая в истории текстовая, а также первая приключенческая игра. Она была чрезвычайно популярна в 1970—1980-е годы. Программистам эта игра так полюбилась, что, пользуясь её размером (около 200 строк кода, половину из которых занимают вывод на экран и комментарии), они встраивали её в различные программы. Известно, что в корпоративной операционной системе R&D была системная команда «to Wumpus», запускавшая игру.



Позже появились и графические версии этой игры, отличающиеся от оригинальной другими лабиринтами и ловушками. В настоящее время версии «Hunt the Wumpus» доступны в Интернете для большинства операционных систем и устройств, включая GNU/Linux, Commodore, Sinclair ZX Spectrum,SunOS, Macintosh, Palm Pilot и мобильные телефоны.



EV3 версия игры


Во всех существующих версиях игрок взаимодействует с миром игры посредством экрана, вводя команды с клавиатуры или мышью (стилусом, тачпадом). Наша команда разработала игровой манипулятор в форме арбалета, с помощью которого можно играть в игру непосредственно взаимодействуя с пространством. К примеру, чтобы развернуться в мире игры игрок должен развернуться в нужную сторону в реальном мире, чтобы выстрелить - нужно указать арбалетом направление и спустить тетиву.



Для сборки мы использовали робототехническую платформу LEGO Mindstorms EV3 в ее образовательной версии. Вам понадобятся все 4 датчика из набора и большой мотор. Датчики используются следующим образом:

  • Порт 1. Гироскоп отслеживает "направление вашего взгляда" в мире игры и разворачивает персонажа
  • Порт 3. Датчик-кнопка используется для выстрела (для указания команды выстрела и последующего спуска тетивы после указания маршрута стрелы)
  • Порт 2. Датчик-кнопка служит для перемещения "в направлении взгляда"
  • Порт 4. Цвето-световой датчик подсвечивает события в игре (синий - все спокойно, красный - рядом опасность)


Для того, чтобы вы смогли собрать игру мы подготовили пошаговую инструкцию по сборке, ее можно скачать по ссылке. Для просмотра необходима программа LEGO Digital Designer или Adobe Reader. Не иатягивайте тетиву слишком туго, детали LEGO могут не выдержать такой нагрузки. Для тетивы арбалета лучше использовать эластичную нитку.


Программу вы также можете скачать по ссылке. Озвучка игры произведена генератором голоса с сайта www.ivona.com



Обратите внимание, что игра достаточно объемна и Вам возможно придется очистить всю память блока, чтобы она смогла в ней уместиться, либо использовать карту microSD.

В момент запуска программы рекомендуем расположить арбалет на ровной горизонтальной поверхности и не трогать его в первые 2-3 секунды. В это время производится устранение дрейфа гироскопа.

Карта пещеры взята нами из классической игры и имеет следующий вид:


Для удобства ориентации на карте Вы можете склеить себе 3D-модель додекаэдра и подписать на нем номера комнат.




Как играть в игру?


После того, как арбалет собран, программа закачана в блок и запущена, Вы услышите 3-х минутное вступление, из которого узнаете о мире игры и ее целях. Прервать болтовню можно в любой момент, нажав на выстрел.

После этого происходит расстановка персонажей на карте и начинается игра. Первый ход - игрока. Вы оказываетесь в одной из комнат пещеры, номер комнаты Вы  услышите и увидите на экране. Кроме этого появится и будет произнесена информация о номерах комнат, в которые Вы видите проходы и о возможных опасностях.
На каждом из ходов Вы должны выбрать - на что потратите свой ход - на движение или выстрел. Чтобы перейти в соседнюю комнату - однократно нажмите на кнопку под большим пальцем. После этого нужно выбрать в какую из трех соседних комнат вы пойдете. Для этого нужно развернуться на нее (вы услышите и увидите на экране подсказки, в какую комнату ведет проход перед вами) и снова нажать кнопк движения.
Если вместо движения Вы решите выстрелить - нужно нажать на кнопку выстрела. После этого нужно указать 5 последовательных комнат, через которые полетит стрела, разворачиваясь на них и нажимая движение. Затем нажать на выстрел. Можно выстрелить ближе, чем на 5 комнат, нажав ан выстрел на любом из 5 шагов планирования маршрута стрелы.
Вы можете выиграть только одним способом - попасть стрелой в Вампуса, а вот погибнуть у игрока - целых семь способов:
1) зайдя в комнату, где спит Вампус
2) от неудачного выстрела Вампус может проснуться и пойти Вас искать - если он зайдет в комнату, где вы сейчас находитесь - Вы проиграли
3) Вы можете провалиться в одну из двух бездонных ям
4) Летучие мыши могут схватить Вас и сбросить в комнате, где спит Вампус
5) У Вас могут закончиться стрелы
6) Летучие мыши могут сбросить Вас в бездонную яму
7) Вы можеет попасть стрелой сами в себя

Как выглядит наша программа?


Программу мы написали в среде LEGO EV3-G. Так как EV3-G не поддерживает многомерные массивы, нам пришлось сделать "эмуляцию" двумерного массива с помощью пользовательских блоков. При желании вы можете посмотреть в программе как это реализовано.


Голосовое вступление, как и прочая игровая озвучка, записано с помощью генератора голоса IVONA-MAXIM:



В массиве L мы храним начальное (и последующее на время игры) положение игрока (ячейка 1), Вампуса (ячейка 2_, бездонных ям (3 и 4) и летучих мышей (5 и 6).
В "двумерном" массиве S - карту пещеры, каждая строка содержит три номера комнат, с которыми связана комната с номером, соответствующим номеру данной строки.
В массиве arrows будем хранить маршрут стрелы во время планирования выстрела.



В начале игры мы случайным образом выбираем номера комнат, в которых будут располагаться игрок, Вампус, две ямы и две летучие мыши. В одной комнате на старте не может быть более одной сущности одновременно



Блок INFO оповещает игрока об опасностях - наличии в соседних комнатах Вампуса, бездонных ям и летучих мышей: выводом на экран, голосом и цветом подсветки датчика.



Во время хода игрока он выбирает, на что потратит свой ход. Выбрав команду "идти" он попадает в блок движения, с помощью которого он перемещается в соседнюю комнату. Этот блок также проверяет ход игрока на игровые ситуации, допустимые в моменты передвижений по карте.



Выбрав команду "выстрел" игрок запускает блок планирования маршрута стрелы. Полет стрелы может пролегать через 1..5 комнат, в которых проверяется совпадение с комнатами Вампуса и игрока.



Упрощенно, на псевдокоде наша программа выглядит следующим образом:

// массив S содержит карту пещеры
МАССИВ S(20,3) = {2,5,8,
                  1,3,10,
                  2,4,12,
                  3,5,14,
                  1,4,6,
                  5,7,15,
                  6,8,17,
                  1,7,9,
                  8,10,18,
                  2,9,11,
                  10,12,19,
                  3,11,13,
                  12,14,20,
                  4,13,15,
                  6,14,16,
                  15,17,20,
                  7,16,18,
                  9,17,19,
                  11,18,20,
                  13,16,19}

// массив L с номерами комнат 1я ячейка игрок , 2 = Вампус, 3 & 4 = ямы, 5 & 6 = летучие мыши
МАССИВ L(6) 

// выбираем случайным образом номера комнат, в которых будут располагаться в начале игры игрок, Вампус, две ямы и две летучие мыши, в одной комнате на старте не может быть более одной сущности

ПЕЩЕРА = 0  - начальная пещера
ЦИКЛ_ПОКА ПЕЩЕРА < 6
  НОМЕР = СЛУЧАЙНОЕ_ЧИСЛО(20) 
  // проверяем, нет ли в ней кого-то
  // триггер 1=комната открыта, 0=комната используется
  ОК = 1  
  СЧЕТЧИК i ОТ 1 ДО ПЕЩЕРА
    // если истина - комната используется
    ЕСЛИ НОМЕР=L(i) ТОГДА ОК = 0 
  СЛЕДУЮЩИЙ i
  // если комната свободна, заполняем ее
  ЕСЛИ ОК=1 ТОГДА   
    ПЕЩЕРА = ПЕЩЕРА + 1
    L(ПЕЩЕРА) = НОМЕР    
КОНЕЦ_ЦИКЛА_ПОКА

// количество стрел у игрока
A=5 
// номер комнаты, где сейчас игрок
L=L(1) 
// F - исход игры
F = 0   

// НАЧАЛО ОСНОВНОГО ИГРОВОГО ЦИКЛА

ЦИКЛ_ПОКА (F=0)

  БЛОК(ИНФО)
  ЖДАТЬ НАЖАТИЯ КНОПКИ (2 ИЛИ 3)
  // Выбор Идти или стрелять
  ЕСЛИ НАЖАТА КНОПКА(2) ТОГДА БЛОК (ВЫСТРЕЛ)
  ЕСЛИ НАЖАТА КНОПКА(3) ТОГДА БЛОК (ИДТИ)

КОНЕЦ_ЦИКЛА_ПОКА

// КОНЕЦ ОСНОВНОГО ИГРОВОГО ЦИКЛА

ЕСЛИ F=1 ТОГДА СКАЗАТЬ "Вы победили!"
ЕСЛИ F=-1 ТОГДА СКАЗАТЬ "Вы вошли в комнату Вампуса и он Вас съел"
ЕСЛИ F=-2 ТОГДА СКАЗАТЬ "Вы попали стрелой сами в себя и проиграли"
ЕСЛИ F=-3 ТОГДА СКАЗАТЬ "Вы потратили все стрелы, но так и не убили Вампуса, Вы проиграли"
ЕСЛИ F=-4 ТОГДА СКАЗАТЬ "Вы провалились в бездонную яму и проиграли"
ЕСЛИ F=-5 ТОГДА СКАЗАТЬ "Ваш выстрел разбудил Вампуса, он пошел Вас искать, нашел и съел"
ЕСЛИ F=-6 ТОГДА СКАЗАТЬ "Летучие мыши сбросили Вас прямо на Вампуса и он Вами пообедал"
ЕСЛИ F=-7 ТОГДА СКАЗАТЬ "Летучие мыши сбросили Вас прямо в бездоннуя яму. Вы проиграли"

КОНЕЦ_ПРОГРАММЫ

// далее - подпрограммы

БЛОК (ИНФО)
  СЧЕТЧИК J ОТ 2 ДО 6
    СЧЕТЧИК K ОТ 1 to 3
      ЕСЛИ S(L(1),K)=L(J) ТОГДА
        ЕСЛИ J = 2 ТОГДа СКАЗАТЬ "Я чувствую запах Вампуса!"
        ЕСЛИ J = 3 ИЛИ J = 4 ТОГДА СКАЗАТЬ "Я чувствую сквозняк!"
        ЕСЛИ J = 5 ИЛИ J = 6 ТОГДА СКАЗАТЬ  "Я слsшу летучих мышей!"      
    СЛЕДУЮЩИЙ K
  СЛУДУЮЩИЙ J
  СКАЗАТЬ "Вы находитесь в комнате ";L(1)
  СКАЗАТЬ "Туннели ведут к комнаты " S(L,1),S(L,2),S(L,3)
  Print

БЛОК (ВЫСТРЕЛ)
  L=L(1)
  СКАЗАТЬ "У Вас осталось", A, "стрел"
  СКАЗАТЬ "Выберите 5 комнат, связанных общим тоннелем"

  // массив с маршрутом стрелы
  Arrow = {0,0,0,0,0,0}

  Arrow(1) = L(1)

  P = 1
  ЦИКЛ_ПОВТОРЕНИЯ (5)
    ЕСЛИ НЕ (F = 0) ТОГДА ВЫХОД_ИЗ_ЦИКЛА
    P = P + 1
    ЖДАТЬ НАЖАТИЯ КНОПКИ (2 ИЛИ 3)
    // Выбор маршрут или стрелять
    ЕСЛИ НАЖАТА КНОПКА(2) ТОГДА ВЫХОД_ИЗ_ЦИКЛА
    ЕСЛИ НАЖАТА КНОПКА(3) ТОГДА 
      Arrow(P) = S(Arrow(P-1),БЛОК (ГИРОСКОП))
    // вы можте попасть стрелой в себя
    ЕСЛИ Arrow(P) = L(1) ТОГДА F=-2
    ЕСЛИ Arrow(P) = L(2) ТОГДА F=1
  КОНЕЦ_ЦИКЛА
    А = А - 1
    ЕСЛИ F=0 ТОГДА СКАЗАТЬ "Выстрел был неудачный, Вы не попали в Вампуса"
    ЕСЛИ СЛУЧАЙНОЕ_ЧИСЛО(100) > 75 ТОГДА
      L(2) = S(L(2),СЛУЧАЙНОЕ_ЧИСЛО(3))
      ЕСЛИ L(2) = L(1) ТОГДА F=-5
    ЕСЛИ А = 0 ТОГДА F=-3

БЛОК (ИДТИ)

  ЦИКЛ (ВСЕГДА)
    СКАЗАТЬ "Вы можете перейти в комнаты с номерами" S(L(1),1), S(L(1),2), S(L(1),3)
    ЕСЛИ НАЖАТА КНОПКА(3) ТОГДА ВЫХОД_ИЗ_ЦИКЛА
  КОНЕЦ_ЦИКЛА

  L(1) = S(L(1),БЛОК (ГИРОСКОП))

  ЕСЛИ L(1) = L(2) ТОГДА F=-1
  ЕСЛИ L(1) = L(3) ИЛИ L(1) = L(4) ТОГДА F=-4
  ЕСЛИ L(1) = L(5) ИЛИ L(1) = L(6) ТОГДА
    L(1) = СЛУЧАЙНОЕ_ЧИСЛО(20)
    СКАЗАТЬ "Летучие мыши схватили Вас и перенесли в комнату", L(!)
    ЕСЛИ L(1) = L(2) ТОГДА F = -6
    ЕСЛИ L(1) = L(3) ИЛИ L(1) = L(4) ТОГДА F = -7

БЛОК (ГИРОСКОП)
  G = СЕНСОР(ГИРОСКОП) + 36000 % 360
  ЕСЛИ G >= 0 И G <=120 ТОГДА ВЕРНУТЬ(1)
  ЕСЛИ G > 120 И G <=240 ТОГДА ВЕРНУТЬ(2)
  ЕСЛИ G > 240 И G <=359 ТОГДА ВЕРНУТЬ(3)




Самое популярное