Innehållsförteckning:
- Steg 1: Överväganden för storbildsdesign
- Steg 2: Signalprotokollet: ett enkelt språk för nätverkskommunikation
- Steg 3: Vi vill styra enhetens åtgärder baserat på dess nuvarande tillstånd
- Steg 4: Vi vill reagera på användarinmatning
- Steg 5: Vi vill initiera datavärden i enhetsminnet när enheten startar
- Steg 6: Vi vill visa animationer och grafik med hjälp av 5 X 5 LED -skärmen
- Steg 7: Vi vill överföra data trådlöst med enhetens radio
- Steg 8: Vi vill lyssna på och ta emot data över enhetens radio och bearbeta det i enlighet därmed
- Steg 9: Rootenhet: Vi vill kunna välja en signal
- Steg 10: Vi är klara
Video: Network Rivalry: a Low-Latency Game for BBC Micro: bit: 10 Steps (med bilder)
2024 Författare: John Day | [email protected]. Senast ändrad: 2024-01-30 12:44
I denna handledning kommer jag att förklara hur man implementerar ett grundläggande multiplayer -spel på BBC micro: bit med följande funktioner:
- Ett enkelt gränssnitt
- Låg latens mellan knapptryckningar och skärmuppdateringar
- Ett flexibelt antal deltagare
- Enkel kontroll över spelet med hjälp av en master remote ("root") enhet
Spelet är i huvudsak en simulering av politik. Alla spelare börjar utan tilldelning till något lag, förutom två spelare. En av dessa spelare tilldelas Lag A, och den andra tilldelas Lag B.
Målet med spelet för varje spelare att vara i laget med majoriteten av spelarna vid den tidpunkt då alla konverteras.
Diagrammet ovan illustrerar en maskin med ändligt tillstånd, det vill säga en specifikation av de tillstånd som enheten kan vara i och övergångarna mellan dessa tillstånd.
Ett tillstånd kan ses som den aktuella uppsättningen data som beskriver enhetens minne sedan den slogs på. Baserat på dessa data kan enheten utföra vissa åtgärder eller reagera annorlunda på användarinmatning.
En övergång är ett logiskt villkor som, när det är sant, får enheten att ändra sitt tillstånd. En övergång kan vara från en stat till en annan stat. Ett tillstånd kan ha flera övergångar.
Diagrammet ovan anger följande tillstånd:
- Ej tilldelad
- Lyssna på A.
- Lyssna på B.
- Lag A
- Lag B
En enhet som kör spelkoden kan vara i någon av dessa fem tillstånd, men bara en åt gången, och bara dessa fem.
Jag antar i hela guiden att du använder Microsofts MakeCode -editor, som finns på:
Hela implementeringen av spelet hittar du här:
makecode.microbit.org/_CvRMtheLbRR3 ("microbit-demo-user" är projektnamnet)
Och implementering av master ("root") nätverkskontrollern hittar du här:
makecode.microbit.org/_1kKE6TRc9TgE ("microbit-demo-root" är projektnamnet)
Jag kommer att hänvisa till dessa exempel under hela min handledning.
Steg 1: Överväganden för storbildsdesign
Innan vi skriver någon kod måste vi tänka på hur vi vill att vår slutprodukt ska se ut. med andra ord, vad är kraven för ansökan? Vad ska vår kod uppmana enheten att göra när den är klar? Jag har delat funktionaliteten för huvudapplikationen i sex kategorier, som alla kan betraktas ur ett annat designperspektiv.
- Vi vill kontrollera enhetens åtgärder baserat på dess nuvarande tillstånd
- Vi vill att enheten ska reagera på användarinmatning
- Vi kanske vill visa animationer och grafik med hjälp av 5 x 5 LED -skärmen
- Vi vill initiera datavärden i enhetens minne när enheten startar
- Vi vill överföra data trådlöst med enhetens radio
- Vi vill lyssna på och ta emot data över enhetens radio och bearbeta den därefter
Låt mig gå in på lite mer detaljer om var och en.
1. Vi vill kontrollera enhetens åtgärder baserat på dess nuvarande tillstånd
Liksom de flesta andra program sker utförandet av instruktionerna som anges av koden en rad i taget. Vi vill att vår enhet ska utföra vissa instruktioner baserat på dess interna tillstånd, som illustreras av diagrammet högst upp i denna handledning. Vi kan skriva en serie villkor efter varje kodblock som kontrollerar att enheten ska göra, men det här tillvägagångssättet kan bli väldigt rörigt mycket snabbt, så vi kommer istället att använda en oändlig slinga som helt enkelt kontrollerar en variabel och baserat på den variabeln, utför en specifik uppsättning instruktioner eller gör ingenting alls. Denna variabel identifieras med suffixet "_state" i både vår användarapplikation och vår rotapplikation.
2. Vi vill att enheten ska reagera på användarinmatning
Trots att normal körning av koden sker sekventiellt, det vill säga en rad i taget, behöver vi vår enhet för att reagera på knapptryckningar medan huvudtillståndsslingan bestämmer vad enheten ska göra vid ett givet tillfälle. För detta ändamål har enheten förmågan att skicka signaler till programvaran på lägre nivå som interagerar med hårdvaran, vilket utlöser vad som kallas en händelse. Vi kan skriva kod som säger till enheten att göra något när den upptäcker en specifik typ av händelse.
3. Vi vill visa animationer och grafik med hjälp av 5 x 5 LED -skärmen
Mekanismen för att göra detta verkar vara enkel, men blocket visar en bild som lägger till en dold fördröjning på 400 ms. Eftersom vi vill att vår enhet ska fortsätta att köra sin tillståndslinga med så lite latens som möjligt, måste vi redigera javascript -koden för att minimera fördröjningen.
4. Vi vill initiera datavärden i enhetens minne när enheten startar
Innan vår enhet gör något måste programmet ladda sina data i minnet. Detta inkluderar konstanta variabler som är uppkallade efter kodläsbarhet, variabler som innehåller bilder, som kan vara en del av en animering, och motvariabler som måste börja vid 0 för att fungera korrekt. Vi kommer att sluta med en lång lista med variabelnamn och deras nyligen tilldelade värden. Som ett personligt stilval kommer jag att beteckna konstanta värden, det vill säga värden som jag aldrig kommer att behöva ändra, med ALL_CAPS. Jag kommer också att prefixa huvudvariabelidentifierare med ett kategorinamn som refererar till ett slags objekt eller en typ som identifieraren faller under. Detta är ett försök att göra koden lättare att följa. Jag kommer aldrig att använda ett variabelnamn som "objekt" eller "x" på grund av den oklarhet som uppstår när jag försöker dechiffrera koden.
5. Vi vill överföra data trådlöst med enhetens radio
Detta är faktiskt en ganska enkel uppgift när du använder MakeCode -blockspråket. Vi ställer helt enkelt in alla enheter till samma radiogrupp vid starttiden och sedan när vi vill skicka en signal kan vi skicka ett enda nummer till blocket "Radiosändnummer" som vi får. Det är viktigt att avsändaren och mottagaren arbetar på samma radiogrupp, för om inte, kommer de att skicka eller ta emot på olika frekvenser, och kommunikationen kommer att misslyckas.
6. Vi vill lyssna på och ta emot data över enhetens radio och bearbeta den därefter
Med tanke på samma överväganden som det föregående objektet kommer vi att lyssna på inkommande sändningar på samma sätt som vi kommer att lyssna efter användarinmatning: med en händelsehanterare. Vi kommer att skriva ett kodblock som kommer att undersöka alla inkommande signaler och kontrollera om någon åtgärd ska vidtas utan att störa huvudslingan.
Dessutom bör vi kort överväga utformningen av det mycket enklare rotprogrammet, ett program som gör att en enhet kan styra hela nätverket. Jag kommer inte lägga mycket tid på detta eftersom det är mycket enklare än ovanstående design och mycket av det är helt enkelt upprepning. Jag har delat funktionaliteten hos roten i tre kategorier.
- Vi vill kunna välja en signal
- Vi vill kunna överföra en signal
--
1. Vi vill kunna välja en signal
Detta kan göras genom att helt enkelt låta en knapp iterera genom de möjliga signalerna. Eftersom det bara finns tre, kommer detta tillvägagångssätt att räcka. Samtidigt kan vi ha en loop som ständigt visar den valda signalen igen, så att användaren kan trycka på en knapp och se den valda signalen visas på LED -displayen med mycket liten latens.
2. Vi vill kunna överföra en signal
Eftersom det finns två knappar kan vi ange en för val och den andra för bekräftelse. Liksom användarprogrammet skickar vi helt enkelt signalen över nätverket som ett nummer. Det behövs ingen annan information.
Jag kommer att tala mer om det enkla signalprotokollet i nästa avsnitt.
Steg 2: Signalprotokollet: ett enkelt språk för nätverkskommunikation
Följande signaler kan ses som en uppsättning av alla möjliga ord som enheterna kan använda för att prata med varandra. Eftersom nätverket är så enkelt, finns det inte mycket att säga, och så kan vi representera dessa tre signaler med enkla heltalsvärden.
0. Återställ
- Identifierare i koden: SIG-R
- Heltal värde: 0
- Syfte: Berätta för alla enheter inom räckvidd att släppa vad de gör och agera som om de bara hade startats upp. Om denna signal når varje enhet i nätverket återställs hela nätverket och användarna kan starta ett nytt spel. Denna signal kan endast sändas av en rotenhet.
1. Omvandling A
- Identifierare i koden: SIG-A
- Heltal värde: 1
- Syfte: Berätta för alla enheter som är i tillståndet LISTEN_A, när de har mottagit omvandlingssignalen, att byta till tillstånd TEAM_A.
2. Konvertering B
- Identifierare i koden: SIG-B
- Heltal: 2
- Syfte: Berätta för alla enheter som är i tillståndet LISTEN_B, när de har mottagit omvandlingssignalen, att byta till tillstånd TEAM_B.
Steg 3: Vi vill styra enhetens åtgärder baserat på dess nuvarande tillstånd
Äntligen kan vi börja skriva kod.
Öppna först ett nytt projekt i Make Code
- Skapa en ny funktion. Jag kallade min loop eftersom det här är programmets kärnslinga
- Lägg till ett loopblock som kommer att upprepas på obestämd tid. Jag använde medan (true) eftersom en bokstavlig sanning aldrig kommer att vara falsk, därför kommer applikationens kontrollflöde aldrig att lämna slingan
- Lägg till tillräckligt med if-else-block för att kontrollera om enheten är i något av dess fem möjliga tillstånd
- Skapa en variabel för att hålla det aktuella enhetstillståndet
-
Skapa variabler för att representera vart och ett av de fem möjliga tillstånden
Obs: Det är OK att dessa variabler inte har några tilldelade värden ännu. Vi kommer till det. Vid denna tidpunkt är det viktigare att vi skriver ren, lättläst kod
- Ändra varje villkor i if-else-blocken för att jämföra det aktuella tillståndet med ett av de möjliga tillstånden
- Längst ner i if-else-blocken lägger du till en paus för ett antal millisekunder och skapar en variabel för att hålla det numret. Vi kommer att initiera det senare. Se till att variabeln har ett beskrivande namn, till exempel fästing eller hjärtslag. Eftersom detta är enhetens kärnslinga, kommer denna paus att avgöra med vilken hastighet enheten kör huvudslingan, så det är ett mycket viktigt värde och är för viktigt för att vara ett magiskt tal utan namn.
Obs: Oroa dig inte om de grå blocken i den tredje bilden. Jag kommer till dem senare.
Steg 4: Vi vill reagera på användarinmatning
Nu vill vi berätta för enheten hur man hanterar knapptryckningar. En första tanke kan vara att helt enkelt använda blocken "När du trycker på knappen" i inmatningskategorin, men vi skulle vilja ha mer detaljerad kontroll än så. Vi kommer att använda blocket "on event from (X) with value (Y)" från kontrollkategorin under det avancerade avsnittet, eftersom vi är avancerade i den här självstudien.
-
Skapa fyra "on event from …" block.
- Två av dessa bör kontrollera händelsekällan "MICROBIT_ID_BUTTON_A"
- Två av dessa bör kontrollera händelsekällan "MICROBIT_ID_BUTTON_B"
-
Av de två händelserna som riktar in sig på varje knapp:
- Man bör kolla efter händelsen av typen "MICROBIT_BUTTON_EVT_UP"
- Man bör kolla efter händelsen av typen "MICROBIT_BUTTON_EVT_DOWN"
- Obs! Dessa alternativ i alla stora bokstäver är etiketter som används i mikrokodbitskoden på lägre nivå. De är helt enkelt platshållare som senare ersätts av heltal när koden kompileras till en körbar binär. Det är lättare för människor att använda dessa etiketter än att slå upp vilket heltal som ska läggas in, men båda skulle fungera på samma sätt.
-
Jag valde, som en fråga om stil, att få varje "on event from …" block att ringa en funktion som beskriver den upphöjda händelsen. Även om det inte är absolut nödvändigt, förbättrar det enligt min mening läsbarheten. Om man vill göra det kan de lägga in händelseshanteringskoden i blocket "on event from …".
Obs! Kodblocket som hanterar enhetens svar på en händelse kallas intuitivt en "händelsehanterare"
- Lägg till i varje händelsehanterare samma if-else-struktur som används för att dela kontrollflödet baserat på enhetens tillstånd som strukturen i huvudtillståndsslingan.
-
Lägg till tilldelningsblock som ändrar enhetens tillstånd enligt specifikationen i vårt tillståndsdiagram
- Vi vet att när enheten är i tillståndet UNASSIGNED, ska enheten reagera på knapp A tryckt genom en övergång till status LISTEN_A, och till knapp B tryckt genom en övergång till status LISTEN_B
- Vi vet också att när enheten är i tillståndet LISTEN_A eller LISTEN_B, bör enheten reagera på knapp A släppt respektive knapp B släppt genom att gå tillbaka till tillståndet UNASSIGNED.
-
Slutligen vet vi att när enheten är i tillståndet TEAM_A eller TEAM_B, ska enheten reagera när knappen A trycks in och knappen B trycks in genom att sända SIG_A respektive SIG_B.
Det är inte nödvändigt att vid denna tidpunkt fylla i detaljerna för sändningssignaler. Vi kommer till det senare. Det som är viktigt är att vi instruerar dessa funktioner att använda koden som vi kommer att skriva genom att ge det blocket av åtgärder ett namn, som broadcastSignalSIG_A, som beskriver vad som ska göras vid den tidpunkten
Steg 5: Vi vill initiera datavärden i enhetsminnet när enheten startar
Vid denna tidpunkt har vi använt många variabler (namn för data), men vi har faktiskt inte tilldelat värden till dessa namn. Vi vill att enheten ska ladda värdena för alla dessa variabler i minnet när den startar, så vi placerar initialiseringen för dessa variabler i ett "på start" -block.
Det här är de värden vi måste initialisera:
-
Signalkonstanter enligt signalprotokollet. Värdena MÅSTE vara:
- SIG_R = 0
- SIG_A = 1
- SIG_B = 2
- Obs! Jag prefixade dessa konstanter med "EnumSignals" för att ange att dessa variabler ska bete sig som om de var en del av en uppräknad typ som kallas Signaler. Så kan dessa variabler implementeras på andra programmeringsspråk. Definitionen och förklaringen av uppräknade typer ligger utanför omfattningen av min handledning. Man kan googla det om de så önskar. Dessa prefix är helt enkelt stilistiska val och är inte alls nödvändiga för att programmet ska fungera korrekt.
-
Statskonstanter, som kan vara godtyckliga så länge de har ett värde. Jag gjorde ett stilval att helt enkelt använda heltal som stiger från 0, så här:
- Otilldelad = 0
- LISTEN_A = 1
- LISTEN_B = 2
- TEAM_A = 3
- TEAM_B = 4
- Obs: Jag fattade samma stilbeslut när det gäller prefix för dessa variabler också. Dessutom kommer jag att nämna att allt om dessa uppdrag, värdena och ordningen är helt godtyckligt. Det spelar ingen roll att dessa värden överensstämmer från enhet till enhet, eftersom de endast används internt och inte för kommunikation över nätverket. Det enda som spelar roll är att variablerna har ett värde och att de kan jämföras med varandra för att se om de är ekvivalenta eller inte.
- För läsbarhet, kallas en konstant BOOT_STATE och ställer den till UNASSIGNED. Detta gör det faktum att vi återställer till startläget, istället för ett mer godtyckligt tillstånd, mer tydligt när enheten får en återställningssignal, som vi kommer att implementera senare.
-
Animationskonstanter, används i följande steg för att skapa animationer som möjliggör extremt låg latensavbrott via användarinmatning. Vi har inte använt dessa hittills, men de kommer säkert att förklaras och användas i följande avsnitt. Betydelsen av några av dessa bör vara intuitiv på grund av deras namn.
- TICKS_PER_FRAME_LOADING_ANIMATION = 50
- MS_PER_DEVICE_TICK = 10
- MS_PER_FRAME_BROADCAST_ANIMATION = 500
- MICROSECONDS_PER_MILLISECOND = 1000
- NUMBER_OF_FRAMES_IN_LOADING_ANIMATION = 4
-
En annan variabel för animering, denna gång en räknare som definitivt inte är konstant. Liksom de flesta räknare initierar vi det till 0
iTickLoadingAnimation = 0
-
Skapa två serier av variabler för att rymma animationer. Den första, som jag kallar "laddningsanimationen", ska ha fyra bilder (som du kanske har gissat med den senaste konstanta initialiseringen), och den andra, som jag kallar "sändningsanimationen", som ska ha tre bilder. Jag rekommenderar att namnge variablerna för att motsvara animeringens ramar, t.ex. ringAnimation0, ringAnimation1 …
Skapa samma bildvärden som jag gjorde eller skapa mer original och svalare bilder
- Sist men inte minst måste vi ställa in enhetens radiogrupp till 0 med hjälp av blocket "radiogrupp (X)"
- Skriv eventuellt meddelandet "Initialisering klar" till seriell utmatning för att berätta för användaren att allt gick bra.
- Nu när vi är klara med att konfigurera enheten kan vi ringa vår tillståndslingfunktion.
Steg 6: Vi vill visa animationer och grafik med hjälp av 5 X 5 LED -skärmen
Och nu för något helt annat.
Vi vill visa några animationer och några tecken, men vi vill inte avbryta huvudtillståndsslingan. Tyvärr har blocken som visar bilder och textsträngar en fördröjning på 400 ms som standard. Det finns inget sätt att ändra detta utan att redigera JavaScript -representationen av koden. Så det här är vad vi kommer att göra.
- Skapa en funktion för varje bild. Detta gör att man kan använda ett enda block för att visa bilden istället för att redigera javascript varje gång. I detta specifika program används ingen bild mer än en gång, men jag tror fortfarande att den här stilen gör koden lättare att läsa.
- Lägg till, i varje ny funktion, ett "visa bild (X) vid offset 0" -block med motsvarande bildvariabelnamn som ersätter (X)
-
Lägg till i huvudtillståndsslingan. "Visa sträng (X)" -block till varje block förutom det som hanterar tillståndet UNASSIGNED. Lägg till ett tecken för enheten att visa för att indikera dess olika tillstånd. Här är vad jag gjorde:
- LISTEN_A: 'a'
- LISTEN_B: 'b'
- TEAM_A: 'A'
-
TEAM_B: 'B'
För tillståndet UNASSIGNED, ring ett samtal till en funktion som uppdaterar laddningsanimationen. Vi kommer att fylla i detaljerna för denna funktion nedan
- Byt till javascript -läge.
- Hitta varje samtal till X.showImage (0) och basic.showString (X)
-
Ändra var och en till antingen X.showImage (0, 0) eller basic.showString (X, 0)
- Om du lägger till detta extra argument kommer fördröjningen efter åtgärden att sättas till 0. Som standard utesluts detta, och enheten kommer att pausa i 400 ms efter utförandet av vart och ett av dessa block.
- Nu har vi en nästan latensfri mekanism för att visa våra bilder i våra animationsblock, som vi nu kan bygga
Först bygger vi den relativt enkla broadcast -animationsfunktionen. Det är enklare eftersom vi inte vill att användaren ska kunna göra någonting förrän funktionen är klar för att hindra dem från att skräpposta sändningsfunktionen. För att uppnå detta kan vi helt enkelt hålla kontrollflödet begränsat till blocket tills funktionen är klar, vilket är standardbeteende.
- Skapa en funktion som visar sändningsanimering.
- Inuti det blocket lägger du till tre funktionssamtal, ett till varje bildruta i animationen, i den ordning de ska visas
-
Lägg till ett "vänta (oss) (X)" -block efter varje samtal till en bildvisningsfunktion.
Obs! Detta block från den avancerade kontrolldelen kommer att gå ännu längre än "paus (ms)" genom att det kommer att frysa processorn helt tills den angivna tiden har gått. När pausblocket används är det möjligt att enheten utför andra uppgifter bakom kulisserna. Detta är omöjligt med väntblocket
- Ersätt (X) med (MS_PER_FRAME_BROADCAST_ANIMATION x MICROSECONDS_PER_MILLISECOND)
- Animationen ska nu fungera korrekt
För det andra kommer vi att bygga mekanismen för att visa laddningsanimationen. Tanken bakom detta är att uppdatera LED -displayen med ett specifikt intervall, som vi definierar i variabeln MS_PER_DEVICE_TICK. Detta värde, enhetens ticklängd, är antalet millisekunder som enheten pausar efter att varje iteration av tillståndslingan har slutförts. Eftersom det här värdet är tillräckligt litet kan vi uppdatera displayen en gång under varje iteration av displayslingan och det kommer att synas för användaren att animationen fortskrider sömlöst, och när tillståndet ändras kommer det att bli mycket liten latens mellan användarens inmatning displayen uppdateras. Genom att räkna fästingar, vilket vi gör med variabeln iTickLoadingAnimation, kan vi visa rätt ram för animationen.
- Skapa en funktion som uppdaterar laddningsanimationen
- Lägg till ett villkor för att kontrollera om fästingräknaren har nått sitt maximala värde. Detta villkor är sant om bockräknarens värde är större än antalet ramar i laddningsanimationen multiplicerat med antalet fästingar för att visa varje bildruta
Om villkoret är sant, återställ iTickLoadingAnimation till 0
-
Lägg till ett block med if-else-villkor. Dessa avgör vilken bildruta i animationen som ska visas.
För varje bildruta i animationen, om bockningsräknaren är mindre än antalet fästingar i varje animation multiplicerat med animeringens bildnummer (börjar med 1), visa sedan den ramen, annars kontrollera om nästa bild är den som ska visas
- Längst ner i blocket, öka iTickLoadingAnimation
- Animationen ska nu fungera korrekt
Obs! Alla de grå blocken som visas i mitt exempel genereras när man redigerar javascript -representationen för ett block. Det betyder helt enkelt att blocket representerar javascript -kod som inte kan representeras med hjälp av standardblocken och måste redigeras i textform.
Steg 7: Vi vill överföra data trådlöst med enhetens radio
Detta steg är mycket kortare än det föregående. Faktum är att det förmodligen är det kortaste steget i hela den här självstudien.
Kom ihåg att när vi programmerade enhetens svar på användarinmatning hade jag två block i skärmdumpen som inte förklarades i det avsnittet. Detta var samtal till funktioner som skickar signaler över radion. Mer specifikt:
-
På knapp A tryckt:
-
Om enheten är i tillståndet TEAM_A:
Sändningssignal SIG_A
-
-
På knappen B tryckt:
-
Om enheten är i tillståndet TEAM_B
Sändningssignal SIG_B
-
Skapa dessa funktioner om de inte redan finns.
I varje funktion:
- Ring sändningsanimationsfunktionen. Detta kommer att blockera allt annat som händer tills det är klart, vilket kommer att vara i MS_PER_FRAME_BROADCAST_ANIMATION * 3 = 1,5 sekunder. Konstanten multipliceras med tre eftersom det finns tre ramar i animationen. Detta är godtyckligt och mer kan läggas till om den estetiska uppgraderingen är tillräckligt stor. Ett andra syfte med denna animering är att förhindra att en användare spammar sändningsfunktionen.
- Lägg till ett "radiosändningsnummer (X)" -block, där är signalkonstanten som nämns i funktionsnamnet
Det är allt man behöver sända över radion.
Steg 8: Vi vill lyssna på och ta emot data över enhetens radio och bearbeta det i enlighet därmed
Detta är det sista steget för att skapa huvudapplikationen.
Vi ska berätta för enheten hur man behandlar inkommande radiosignaler. Först kommer vår enhet att namnge den mottagna signalen. Baserat på värdet på den signalen kommer den sedan att bestämma vilken åtgärd som ska vidtas, om någon.
Först:
- Skapa ett kodblock som börjar med ett "på radio mottaget (X)" block.
- Alternativt kan du tilldela det mottagna värdet till en annan variabel med ett mer beskrivande namn.
- Ring en funktion som kommer att behandla signalen
För det andra, i signalbehandlingsfunktionen:
- Skapa ett block av if-else-uttalanden som förgrenar kontrollflödet baserat på signalens värde.
-
Om signalen var SIG_R
Ställ in enhetens tillstånd till BOOT_STATE (det är därför vi skapade denna konstant tidigare)
- Om signalen var SIG_A och om det aktuella tillståndet är LISTEN_A
Ställ in enhetens tillstånd till TEAM_A
-
Om signalen var SIG_B och om det aktuella tillståndet är LISTEN_B
Ställ in enhetens tillstånd till TEAM_B
Det är allt. Ansökan är klar.
Steg 9: Rootenhet: Vi vill kunna välja en signal
Nu kommer vi att skriva en enkel applikation för en "root" -enhet, det vill säga en enhet som kommer att styra nätverket.
Denna enhet måste utföra två funktioner:
- Vi vill tillåta användaren att välja en av våra signaler
- Vi vill tillåta användaren att sända signalen
Eftersom specifikationen för denna applikation är en delmängd av den föregående, kommer jag att ge en översikt, men jag kommer inte att gå in på så mycket detaljer som jag hade tidigare. Bilden ovan innehåller den fullständiga koden för denna applikation.
För att låta användaren välja en signal:
-
Initiera 5 variabler i ett "på start" -block:
- De tre signalerna (0, 1, 2)
- Antal signaler (3)
- En variabel för att hålla den för närvarande valda signalen (initialt inställd på den första signalen, 0)
-
Hantera ett tryck på A -knappen:
- Öka den valda signalen
-
Kontrollera om den valda signalen är större än eller lika med antalet signaler
Ställ i så fall den valda signalen till 0
- Efter startblocket kör du en "forever" -slinga som visar det aktuella valda signalvärdet utan fördröjning
För att låta användaren sända en signal
- Ställ in radiogruppen på 0 i blocket "vid start"
-
Hantera ett tryck på B -knappen:
Sänd den valda signalen med hjälp av ett "radiosändningsnummer (X)" -block
Det är allt. Rotnodsprogrammet är extremt enkelt.
Steg 10: Vi är klara
Ovan är en bild av enheterna som kör programmet. De två till höger kör huvudprogrammet "användare", och den till vänster kör "root" -programmet.
Jag demonstrerade det här spelet på CS Connections 2018, en veckolång sommarkonferens för mellan- och gymnasielärare om datavetenskaplig utbildning. Jag gav ut cirka 40 enheter till lärarna och förklarade reglerna. De flesta tyckte att spelet var underhållande, och många tyckte att det var förvirrande tills de kom på hur de skulle spela. Demonstrationen var kort, men vi tyckte att spelet var roligt bland en ganska varierad publik.
Mer information om CS Connections 2018 hittar du här.
Rekommenderad:
BBC Micro: bit and Scratch - Interactive Rat & Driving Game: 5 Steps (med bilder)
BBC Micro: bit and Scratch - Interactive Steering Wheel & Driving Game: Ett av mina klassuppgifter den här veckan är att använda BBC Micro: bit för att ansluta till ett Scratch -program som vi har skrivit. Jag trodde att detta var det perfekta tillfället att använda mitt ThreadBoard för att skapa ett inbäddat system! Min inspiration till scratch p
[2020] Använda iPhone eller iPad och Micro: bit Game Pad -app för att styra en RC -bil: 23 steg
[2020] Använda iPhone eller iPad och Micro: bit Game Pad App för att styra en RC -bil: Har du tänkt använda din iPhone eller iPad för att styra din micro: bit? Vet du att Micro: bit Educational Foundation tillhandahåller iOS -appen i App store? Sök efter " micro: bit " i App Store och du kan ladda ner appen gratis. De
Väggfäste för iPad som kontrollpanel för hemautomation, med servostyrd magnet för att aktivera skärmen: 4 steg (med bilder)
Väggfäste för iPad Som kontrollpanel för hemautomation, med servostyrd magnet för att aktivera skärmen: På senare tid har jag ägnat ganska mycket tid åt att automatisera saker i och runt mitt hus. Jag använder Domoticz som min hemautomationsapplikation, se www.domoticz.com för mer information. I min sökning efter en instrumentpanelapplikation som visar all Domoticz -information tillsammans
LP-2010 AES17 1998 Switching Amplifier Low Pass (low-pass) Filter: 4 Steg
LP-2010 AES17 1998 Switching Amplifier Low Pass (low-pass) Filter: Detta är en stor förstärkare i D-klass mätning av lågpassfilter. Det fina utförandet, superiroprestanda, enkel anslutning gör denna produkt lätt att använda och mycket värd att äga med en hög kostnadsprestanda
Ljus- och färgmätningar Med Pimoroni Enviro: bit för Micro: bit: 5 steg
Ljus- och färgmätningar Med Pimoroni Enviro: bit för Micro: bit: Jag hade arbetat med några enheter som tillåter ljus- och färgmätningar tidigare och du kan hitta mycket om teorin bakom sådana mätningar som instruerbara här och här. Pimoroni har släppte nyligen enviro: bit, ett tillägg för m