Indholdsfortegnelse:

Network Rivalry: a Low-Latency Game for BBC Micro: bit: 10 trin (med billeder)
Network Rivalry: a Low-Latency Game for BBC Micro: bit: 10 trin (med billeder)

Video: Network Rivalry: a Low-Latency Game for BBC Micro: bit: 10 trin (med billeder)

Video: Network Rivalry: a Low-Latency Game for BBC Micro: bit: 10 trin (med billeder)
Video: The Power of Your Subconscious Mind (1963) by Joseph Murphy 2024, November
Anonim
Network Rivalry: a Low-Latency Game for BBC Micro: bit
Network Rivalry: a Low-Latency Game for BBC Micro: bit
Network Rivalry: a Low-Latency Game for BBC Micro: bit
Network Rivalry: a Low-Latency Game for BBC Micro: bit

I denne vejledning vil jeg forklare, hvordan man implementerer et grundlæggende multiplayer -spil på BBC micro: bit med følgende funktioner:

  • En enkel grænseflade
  • Lav latens mellem knap tryk og skærmopdateringer
  • Et fleksibelt antal deltagere
  • Nem kontrol over spillet ved hjælp af en master -fjernbetjening ("root")

Spillet er hovedsageligt en simulering af politik. Alle spillere starter uden tildeling til ethvert hold, undtagen to spillere. Den ene af disse spillere er tilknyttet hold A, og den anden er tilknyttet hold B.

Formålet med spillet for hver spiller at være på holdet med størstedelen af spillerne på det tidspunkt, hvor alle er konverteret.

Diagrammet ovenfor illustrerer en endelig tilstandsmaskine, dvs. en specifikation af de tilstande, som enheden kan være i, og overgangene mellem disse tilstande.

En tilstand kan betragtes som det aktuelle datasæt, der beskriver enhedens hukommelse, siden den blev tændt. Baseret på disse data kan enheden udføre bestemte handlinger eller reagere anderledes på brugerinput.

En overgang er en logisk tilstand, der, når den er sand, får enheden til at ændre sin tilstand. En overgang kan være fra en stat til en anden stat. En tilstand kan have flere overgange.

Diagrammet ovenfor angiver følgende tilstande:

  • Ikke tildelt
  • Lyt efter A.
  • Lyt efter B.
  • Hold A
  • Hold B

En enhed, der kører spilkoden, kan være i en af disse fem stater, men kun én ad gangen, og kun disse fem.

Jeg antager i hele guiden, at du bruger Microsofts MakeCode -editor, som kan findes på:

Den fulde implementering af spillet kan findes her:

makecode.microbit.org/_CvRMtheLbRR3 ("mikrobit-demo-bruger" er projektnavnet)

Og implementering af master ("root") netværkskontrolleren kan findes her:

makecode.microbit.org/_1kKE6TRc9TgE ("microbit-demo-root" er projektnavnet)

Jeg vil henvise til disse eksempler i hele min vejledning.

Trin 1: Overvejelser om design af store billeder

Inden vi skriver nogen kode, skal vi tænke over, hvordan vi vil have, at vores slutprodukt skal se ud. med andre ord, hvad er kravene til ansøgningen? Hvad skal vores kode fortælle enheden at gøre, når den er færdig? Jeg har opdelt funktionaliteten i hovedapplikationen i seks kategorier, der hver især kan betragtes fra et andet designperspektiv.

  1. Vi vil kontrollere enhedens handlinger baseret på dens aktuelle tilstand
  2. Vi ønsker, at enheden reagerer på brugerinput
  3. Vi vil måske vise animationer og grafik ved hjælp af 5 x 5 LED -skærmen
  4. Vi ønsker at initialisere dataværdier i enhedshukommelsen, når enheden starter op
  5. Vi ønsker at overføre data trådløst ved hjælp af enhedens radio
  6. Vi vil lytte efter og modtage data over enhedens radio og behandle dem i overensstemmelse hermed

Tillad mig at gå lidt mere i detaljer om hver enkelt.

1. Vi vil kontrollere enhedens handlinger baseret på dens aktuelle tilstand

Ligesom de fleste andre programmer sker udførelse af instruktionerne angivet af koden én linje ad gangen. Vi ønsker, at vores enhed skal udføre visse instruktioner baseret på dens interne tilstand, som illustreret af diagrammet øverst i denne vejledning. Vi kunne skrive en række betingelser efter hver kodeblok, der kontrollerer, at enheden skal udføre, men denne fremgangsmåde kan blive meget rodet meget hurtigt, så vi vil i stedet bruge en uendelig sløjfe, der blot kontrollerer en variabel og baseret på den variabel, udfører et specifikt sæt instruktioner eller slet ikke gør noget. Denne variabel identificeres med suffikset "_state" i både vores brugerprogram og vores root -applikation.

2. Vi ønsker, at enheden reagerer på brugerinput

På trods af normal udførelse af koden, der forekommer i rækkefølge, det vil sige en linje ad gangen, har vi brug for, at vores enhed reagerer på knappetryk, mens hovedtilstandsløkken bestemmer, hvad enheden skal gøre på et givet tidspunkt. Til dette formål har enheden mulighed for at sende signaler til softwaren på lavere niveau, der interagerer med hardwaren, hvilket udløser det, der kaldes en hændelse. Vi kan skrive kode, der fortæller enheden at gøre noget, når den registrerer en bestemt type hændelse.

3. Vi ønsker at vise animationer og grafik ved hjælp af 5 x 5 LED -displayet

Mekanismen til at gøre dette ser ud til at være enkel, men blokken viser et billede og tilføjer en skjult forsinkelse på 400 ms. Fordi vi vil have vores enhed til at fortsætte med at udføre sin tilstandsløjfe med så lidt latens som muligt, bliver vi nødt til at redigere javascript -koden for at minimere forsinkelsen.

4. Vi ønsker at initialisere dataværdier i enhedshukommelsen, når enheden starter op

Inden vores enhed gør noget, skal applikationen indlæse sine data i hukommelsen. Dette inkluderer konstante variabler, der er navngivet efter kodelæsbarhed, variabler, der indeholder billeder, som kan være en del af en animation, og modvariabler, der skal starte med 0 for at fungere korrekt. Vi ender med en lang liste med variabelnavne og deres nyligt tildelte værdier. Som et personligt stilvalg vil jeg betegne konstante værdier, dvs. værdier, som jeg aldrig skal ændre ved hjælp af ALL_CAPS. Jeg vil også præfiksere hovedvariabelidentifikatorer med et kategorienavn, der refererer til en slags objekt eller type, som identifikatoren falder ind under. Dette er et forsøg på at gøre koden lettere at følge. Jeg vil aldrig bruge et variabelnavn som "element" eller "x" på grund af den tvetydighed, der opstår, når jeg forsøger at dechiffrere koden.

5. Vi ønsker at overføre data trådløst ved hjælp af enhedens radio

Dette er faktisk en ret simpel opgave, når du bruger MakeCode -blokke -sproget. Vi indstiller simpelthen alle enheder til den samme radiogruppe ved opstartstidspunktet, og når vi vil sende et signal, kan vi sende et enkelt nummer til den "Radiosendnummer" -blok, der er givet til os. Det er vigtigt, at afsender og modtager arbejder på den samme radiogruppe, for hvis ikke, sender eller modtager de på forskellige frekvenser, og kommunikationen mislykkes.

6. Vi vil lytte efter og modtage data over enhedens radio og behandle dem i overensstemmelse hermed

Idet vi tager de samme overvejelser i betragtning som det forrige element, vil vi lytte efter indgående transmissioner på samme måde, som vi vil lytte efter brugerinput: med en event -handler. Vi skriver en kodeblok, der undersøger alle indgående signaler og kontrollerer, om der skal foretages nogen handling uden at forstyrre hovedtilstandsløkken.

Derudover bør vi kort overveje designet af den langt enklere rodapplikation, et program, der gør det muligt for en enhed at styre hele netværket. Jeg vil ikke bruge meget tid på dette, da det er langt enklere end ovenstående design, og meget af det er simpelthen gentagelse. Jeg har opdelt roddeisens funktionalitet i tre kategorier.

  1. Vi ønsker at kunne vælge et signal
  2. Vi ønsker at kunne sende et signal

-

1. Vi ønsker at kunne vælge et signal

Dette kan gøres ved blot at få en knap til at gentage sig gennem de mulige signaler. Da der kun er tre, er denne tilgang tilstrækkelig. På samme tid kan vi have en loop, der konstant genviser det valgte signal, så brugeren kan trykke på en knap og se det valgte signal vises på LED -displayet med meget lidt latency.

2. Vi ønsker at kunne sende et signal

Da der er to knapper, kan vi angive den ene til valg og den anden til bekræftelse. Ligesom brugerprogrammet sender vi simpelthen signalet over netværket som et tal. Der kræves ingen andre oplysninger.

Jeg vil tale mere om den simple signalprotokol i det næste afsnit.

Trin 2: Signalprotokollen: et simpelt sprog til netværkskommunikation

Følgende signaler kan betragtes som et sæt af alle mulige ord, som enhederne kan bruge til at tale med hinanden. Fordi netværket er så enkelt, er der ikke meget at sige, og derfor kan vi repræsentere disse tre signaler ved simple heltalsværdier.

0. Nulstil

  • Identifikator i koden: SIG-R
  • Heltal værdi: 0
  • Formål: Fortæl alle enheder inden for rækkevidde at droppe, hvad de laver, og handle som om de lige var startet op. Hvis dette signal når hver enhed på netværket, nulstilles hele netværket, og brugerne kan starte et nyt spil. Dette signal kan kun udsendes af en rodenhed.

1. Konvertering A

  • Identifikator i koden: SIG-A
  • Heltal værdi: 1
  • Formål: Fortæl enhver enhed, der er i tilstand LISTEN_A, når de modtager konverteringssignalet, at skifte til tilstand TEAM_A.

2. Konvertering B

  1. Identifikator i koden: SIG-B
  2. Heltal værdi: 2
  3. Formål: Fortæl enhver enhed, der er i tilstand LISTEN_B, når de modtager konverteringssignalet, at skifte til tilstand TEAM_B.

Trin 3: Vi vil kontrollere enhedens handlinger baseret på dens aktuelle tilstand

Vi vil kontrollere enhedens handlinger baseret på dets aktuelle tilstand
Vi vil kontrollere enhedens handlinger baseret på dets aktuelle tilstand
Vi vil kontrollere enhedens handlinger baseret på dets aktuelle tilstand
Vi vil kontrollere enhedens handlinger baseret på dets aktuelle tilstand
Vi vil kontrollere enhedens handlinger baseret på dens aktuelle tilstand
Vi vil kontrollere enhedens handlinger baseret på dens aktuelle tilstand

Endelig kan vi begynde at skrive kode.

Først skal du åbne et nyt projekt i Make Code

  • Opret en ny funktion. Jeg kaldte min loop, fordi dette er applikationens kernesløkke
  • Tilføj en loop -blok, der gentages på ubestemt tid. Jeg brugte mens (true), fordi en bogstavelig sandhed aldrig vil være falsk, derfor vil applikationens kontrolflow aldrig forlade sløjfen
  • Tilføj nok if-else-blokke til at kontrollere, om enheden er i en af sine fem mulige tilstande
  • Opret en variabel for at holde den aktuelle enhedstilstand
  • Opret variabler, der repræsenterer hver af de fem mulige tilstande

    Bemærk: Det er OK, at disse variabler endnu ikke har nogen tildelte værdier. Det kommer vi til. På dette tidspunkt er det mere vigtigt, at vi skriver ren, letlæselig kode

  • Skift hver betingelse i if-else-blokke for at sammenligne den aktuelle tilstand med en af de mulige tilstande
  • I bunden af if-else-blokkerne skal du tilføje en pause i et antal millisekunder og oprette en variabel for at holde dette nummer. Vi vil initialisere det senere. Sørg for, at variablen har et beskrivende navn, f.eks. Kryds eller hjerteslag. Fordi dette er enhedens kernesløjfe, vil denne pause bestemme den hastighed, hvormed enheden udfører hovedsløjfen, så det er en meget vigtig værdi og er for vigtig til at være et magisk tal uden navn.

Bemærk: Du skal ikke bekymre dig om de grå blokke i det tredje billede. Dem kommer jeg senere til.

Trin 4: Vi vil reagere på brugerinput

Vi vil reagere på brugerinput
Vi vil reagere på brugerinput
Vi vil reagere på brugerinput
Vi vil reagere på brugerinput

Nu vil vi fortælle enheden, hvordan man håndterer knappetryk. Den første tanke er måske blot at bruge "Når der trykkes på knappen" -blokkene i inputkategorien, men vi vil gerne have mere detaljeret kontrol end det. Vi vil bruge blokken "on event from (X) with value (Y)" fra kontrolkategorien under den avancerede sektion, fordi vi er avancerede i denne tutorial.

  • Opret fire "on event from …" blokke.

    • To af disse bør kontrollere hændelseskilden "MICROBIT_ID_BUTTON_A"
    • To af disse bør kontrollere hændelseskilden "MICROBIT_ID_BUTTON_B"
    • Af de to begivenheder, der er målrettet mod hver knap:

      • Man bør kontrollere for hændelsen af typen "MICROBIT_BUTTON_EVT_UP"
      • Man bør kontrollere for hændelsen af typen "MICROBIT_BUTTON_EVT_DOWN"
    • Bemærk: Disse indstillinger i alle store bogstaver er etiketter, der bruges i micro: bit-koden på lavere niveau. De er simpelthen pladsholdere, der senere erstattes af heltal, når koden kompileres til en eksekverbar binær. Det er lettere for mennesker at bruge disse etiketter end at slå op, hvilket heltal der skal indsættes, selvom begge ville fungere på samme måde.
  • Jeg valgte, som et spørgsmål om stil, at få hver "on event from …" blok til at kalde en funktion, der beskriver den hævede begivenhed. Selvom det ikke er strengt nødvendigt, forbedrer det efter min mening læsbarheden. Hvis man ønsker at gøre det, kan de lægge hændelseshåndteringskoden inde i blokken "on event from …".

    Bemærk: Kodeblokken, der håndterer enhedens svar på en begivenhed, kaldes intuitivt en "hændelseshåndterer"

  • Tilføj i hver hændelseshandler den samme if-else-struktur, der bruges til at opdele kontrolstrøm baseret på enhedstilstand som strukturen i hovedtilstandsløkken.
  • Tilføj tildelingsblokke, der ændrer enhedens tilstand som angivet i vores tilstandsdiagram

    • Vi ved, at når enheden er i tilstand UMÆRKET, skal enheden reagere på knap A, der trykkes ved en overgang til tilstand LISTEN_A, og til knap B trykkes ved en overgang til tilstand LISTEN_B
    • Vi ved også, at når enheden er i tilstand LISTEN_A eller LISTEN_B, skal enheden reagere på henholdsvis knap A frigivet og knap B frigivet ved at gå tilbage til tilstand UMÆRKET.
    • Endelig ved vi, at når enheden er i tilstanden TEAM_A eller TEAM_B, skal enheden reagere på knappen A, der trykkes ned, og knappen B trykkes ved at udsende henholdsvis SIG_A og ved at sende SIG_B.

      Det er ikke nødvendigt på dette tidspunkt at udfylde detaljerne i udsendelsessignaler. Det kommer vi til senere. Det, der er vigtigt, er, at vi instruerer disse funktioner til at bruge den kode, vi vil skrive ved at give denne blok af handlinger et navn, som broadcastSignalSIG_A, som beskriver, hvad der skal gøres på det tidspunkt

Trin 5: Vi vil initialisere dataværdier i enhedshukommelsen, når enheden starter op

Vi ønsker at initialisere dataværdier i enhedshukommelsen, når enheden starter op
Vi ønsker at initialisere dataværdier i enhedshukommelsen, når enheden starter op
Vi ønsker at initialisere dataværdier i enhedshukommelsen, når enheden starter op
Vi ønsker at initialisere dataværdier i enhedshukommelsen, når enheden starter op
Vi ønsker at initialisere dataværdier i enhedshukommelsen, når enheden starter op
Vi ønsker at initialisere dataværdier i enhedshukommelsen, når enheden starter op

På dette tidspunkt har vi brugt mange variabler (navne til data), men vi har faktisk ikke tildelt værdier til disse navne. Vi vil have enheden til at indlæse værdierne for alle disse variabler i hukommelsen, når den starter, så vi placerer initialiseringen for disse variabler i en "på start" -blok.

Dette er de værdier, vi skal initialisere:

  • Signalkonstanter i henhold til signalprotokollen. Værdierne SKAL være:

    • SIG_R = 0
    • SIG_A = 1
    • SIG_B = 2
    • Bemærk: Jeg præfikserede disse konstanter med "EnumSignals" for at angive, at disse variabler skal opføre sig som om de var en del af en opregnet type kaldet Signaler. Sådan kan disse variabler implementeres på andre programmeringssprog. Definitionen og forklaringen på opregnede typer ligger uden for omfanget af min tutorial. Man kan Google det, hvis de ønsker det. Disse præfikser er simpelthen stilistiske valg og er slet ikke afgørende for, at programmet fungerer korrekt.
  • Statskonstanter, som kan være vilkårlige, så længe de har en værdi. Jeg foretog et stilvalg til simpelthen at bruge heltal stigende fra 0, sådan:

    • UTILSIGTET = 0
    • LISTEN_A = 1
    • LISTEN_B = 2
    • TEAM_A = 3
    • TEAM_B = 4
    • Bemærk: Jeg tog også den samme stilbeslutning vedrørende præfikser til disse variabler. Derudover vil jeg nævne, at alt om disse opgaver, værdierne og rækkefølgen er fuldstændig vilkårligt. Det gør ikke engang noget, at disse værdier er konsistente fra enhed til enhed, fordi de kun bruges internt og ikke til kommunikation over netværket. Det eneste, der betyder noget, er, at variablerne har en værdi, og at de kan sammenlignes med hinanden for at se, om de er ækvivalente eller ej.
  • For læsbarhed kaldes en konstant BOOT_STATE og indstiller den til UNASSIGNED. Dette gør det faktum, at vi nulstiller til boot -tilstanden i stedet for en mere vilkårlig tilstand, mere eksplicit, når enheden modtager et nulstillingssignal, som vi vil implementere senere.
  • Animationskonstanter, der bruges i det følgende trin til at oprette animationer, der muliggør ekstremt lav latensafbrydelse via brugerinput. Vi har ikke brugt disse hidtil, men de vil helt sikkert blive forklaret og brugt i det følgende afsnit. Betydningen af nogle af disse burde være intuitiv på grund af deres navne.

    • 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 anden variabel til animation, denne gang en tæller, der bestemt ikke er konstant. Som de fleste tællere initialiserer vi det til 0

    iTickLoadingAnimation = 0

  • Opret to serier af variabler for at indeholde rammer for animationer. Den første, som jeg kalder "loading animation", skal have fire billeder (som du måske har gættet ved den sidste konstante initialisering), og den anden, som jeg kalder "broadcast animationen", som skal have tre billeder. Jeg anbefaler at navngive variablerne, så de svarer til animationens rammer, f.eks. ringAnimation0, ringAnimation1 …

    Opret de samme billedværdier som jeg gjorde, eller opret mere originale og sejere billeder

  • Sidst men ikke mindst skal vi indstille enhedens radiogruppe til 0 ved hjælp af blokken "radio sæt gruppe (X)"
  • Du kan eventuelt skrive meddelelsen "Initialisering fuldført" til seriel output for at fortælle brugeren, at alt gik svimlende.
  • Nu hvor vi er færdige med at konfigurere enheden, kan vi kalde vores state loop -funktion.

Trin 6: Vi vil vise animationer og grafik ved hjælp af 5 x 5 LED -skærmen

Vi vil vise animationer og grafik ved hjælp af 5 x 5 LED -skærmen
Vi vil vise animationer og grafik ved hjælp af 5 x 5 LED -skærmen
Vi vil vise animationer og grafik ved hjælp af 5 x 5 LED -skærmen
Vi vil vise animationer og grafik ved hjælp af 5 x 5 LED -skærmen
Vi vil vise animationer og grafik ved hjælp af 5 x 5 LED -skærmen
Vi vil vise animationer og grafik ved hjælp af 5 x 5 LED -skærmen

Og nu til noget helt andet.

Vi vil vise et par animationer og et par tegn, men vi ønsker ikke at afbryde hovedtilstandsløkken. Desværre har de blokke, der viser billeder og tekststrenge, som standard en forsinkelse på 400 ms. Der er ingen måde at ændre dette uden at redigere javascript -repræsentationen af koden. Så det er hvad vi vil gøre.

  • Opret en funktion for hvert billede. Dette giver en mulighed for at bruge en enkelt blok til at vise billedet i stedet for at redigere javascript hver gang. I dette specifikke program bruges intet billede mere end én gang, men jeg synes stadig, at denne stil gør koden lettere at læse.
  • Tilføj i hver ny funktion en "vis billede (X) ved offset 0" -blok med det tilsvarende billedvariabelnavn, der erstatter (X)
  • Tilføj, i hovedtilstandsløkken. "Vis streng (X)" -blokke til hver blok udover den, der håndterer tilstand UMÆRKET. Tilføj et tegn, som enheden skal vise for at angive dens forskellige tilstande. Her er hvad jeg gjorde:

    • LISTEN_A: 'a'
    • LISTEN_B: 'b'
    • TEAM_A: 'A'
    • TEAM_B: 'B'

      For tilstand UMÆRKET skal du foretage et opkald til en funktion, der opdaterer indlæsningsanimationen. Vi udfylder detaljerne for denne funktion nedenfor

  • Skift til javascript -tilstand.
  • Find hvert opkald til X.showImage (0) og basic.showString (X)
  • Skift hver enkelt til enten X.showImage (0, 0) eller basic.showString (X, 0)

    • Tilføjelse af dette ekstra argument sætter forsinkelsen efter handlingen til 0. Som standard er dette udeladt, og enheden standser i 400 ms efter udførelsen af hver af disse blokke.
    • Nu har vi en næsten latensfri mekanisme til at vise vores billeder i vores animationsblokke, som vi nu kan bygge

Først bygger vi den relativt enkle broadcast -animationsfunktion. Det er enklere, fordi vi ikke ønsker, at brugeren skal være i stand til at gøre noget, før funktionen er fuldført, for at forhindre dem i at spamme udsendelsesfunktionen. For at opnå dette kan vi simpelthen holde kontrolstrømmen begrænset til blokken, indtil funktionen er fuldført, hvilket er standardadfærd.

  • Opret en funktion, der viser broadcast -animation.
  • Inde i den blok skal du tilføje tre funktionsopkald, et til hver ramme i animationen, i den rækkefølge de skal vises
  • Tilføj en "vent (os) (X)" blok efter hvert opkald til en billedvisning funktion.

    Bemærk: Denne blok fra sektionen avanceret kontrol vil gå endnu længere end "pause (ms)", idet den vil fryse processoren fuldstændigt, indtil den angivne tid er gået. Når pauseblokken bruges, er det muligt, at enheden udfører andre opgaver bag kulisserne. Dette er umuligt med venteblokken

  • Erstat (X) med (MS_PER_FRAME_BROADCAST_ANIMATION x MICROSECONDS_PER_MILLISECOND)
  • Animationen skal nu fungere korrekt

For det andet vil vi opbygge mekanismen til visning af indlæsningsanimationen. Ideen bag dette er at opdatere LED -displayet med et bestemt interval, som vi definerer i variablen MS_PER_DEVICE_TICK. Denne værdi, enhedens krydslængde, er antallet af millisekunder, som enheden sætter på pause, efter at hver iteration af tilstandsløjfen er fuldført. Fordi denne værdi er lille nok, kan vi opdatere displayet én gang under hver iteration af displaysløjfen, og det vil vise sig for brugeren, at animationen skrider problemfrit frem, og når tilstanden ændres, vil der være meget lidt latenstid mellem brugerens input displayet opdateres. Ved at tælle flåter, som vi gør med iTickLoadingAnimation -variablen, kan vi vise den passende ramme for animationen.

  • Opret en funktion, der opdaterer indlæsningsanimationen
  • Tilføj en betingelse for at kontrollere, om flåttælleren har nået sin maksimale værdi. Denne betingelse vil være sand, hvis tællertællerens værdi er større end antallet af rammer i indlæseranimationen ganget med antallet af kryds for at få vist hver ramme

    Hvis betingelsen er sand, skal du nulstille iTickLoadingAnimation til 0

  • Tilføj en blok med if-else-betingelser. Disse bestemmer hvilken ramme i animationen der skal vises.

    Hvis hvert kryds i tælleren er mindre end antallet af kryds i hver animation ganget med animationens billednummer (startende ved 1), skal du derefter vise rammen for hvert billede i animationen og derefter kontrollere, om den næste ramme er den blive vist

  • I bunden af blokken øges iTickLoadingAnimation
  • Animationen skal nu fungere korrekt

Bemærk: Alle de grå blokke, der vises i mit eksempel, genereres, når man redigerer javascript -repræsentationen af en blok. Det betyder ganske enkelt, at blokken repræsenterer javascript -kode, der ikke kan repræsenteres ved hjælp af standardsættet af blokke og skal redigeres i tekstform.

Trin 7: Vi ønsker at overføre data trådløst ved hjælp af enhedens radio

Vi ønsker at overføre data trådløst ved hjælp af enhedens radio
Vi ønsker at overføre data trådløst ved hjælp af enhedens radio

Dette trin er langt kortere end det foregående. Faktisk er det nok det korteste trin i hele denne vejledning.

Husk, at da vi programmerede enhedens svar på brugerinput, havde jeg to blokke i skærmbilledet, der ikke blev forklaret i dette afsnit. Det var opkald til funktioner, der sender signaler over radioen. Mere specifikt:

  • På knappen A trykkes:

    • Hvis enheden er i tilstanden TEAM_A:

      Broadcast -signal SIG_A

  • Tryk på knappen B:

    • Hvis enheden er i tilstanden TEAM_B

      Udsendelsessignal SIG_B

Opret disse funktioner, hvis de ikke allerede findes.

I hver funktion:

  • Ring til broadcast -animationsfunktionen. Dette blokerer alt andet for at ske, indtil det er fuldført, hvilket vil være i MS_PER_FRAME_BROADCAST_ANIMATION * 3 = 1,5 sekunder. Konstanten ganges med tre, fordi der er tre rammer i animationen. Dette er vilkårligt og mere kan tilføjes, hvis den æstetiske opgradering er stor nok. Et andet formål med denne animation er at forhindre en bruger i at spamme udsendelsesfunktionen.
  • Tilføj en "radiosend nummer (X)" blok, hvor er signalkonstanten nævnt i funktionsnavnet

Det er alt, hvad man har brug for at sende over radioen.

Trin 8: Vi vil lytte efter og modtage data via enhedens radio og behandle det i overensstemmelse hermed

Vi vil lytte efter og modtage data over enhedens radio og behandle det i overensstemmelse hermed
Vi vil lytte efter og modtage data over enhedens radio og behandle det i overensstemmelse hermed
Vi vil lytte efter og modtage data over enhedens radio og behandle det i overensstemmelse hermed
Vi vil lytte efter og modtage data over enhedens radio og behandle det i overensstemmelse hermed

Dette er det sidste trin for at oprette hovedapplikationen.

Vi vil fortælle enheden, hvordan man behandler indgående radiosignaler. For det første vil vores enhed navngive det modtagne signal. Derefter vil det, baseret på værdien af det signal, beslutte, hvilken handling der eventuelt skal foretages.

Først:

  1. Opret en kodeblok, der starter med en "on radio received (X)" blok.
  2. Du kan eventuelt tildele den modtagne værdi til en anden variabel med et mere beskrivende navn.
  3. Ring til en funktion, der behandler signalet

For det andet i signalbehandlingsfunktionen:

  1. Opret en blok med if-else-sætninger, der forgrener kontrolflowet baseret på signalets værdi.
  2. Hvis signalet var SIG_R

    Indstil enhedens tilstand til BOOT_STATE (derfor har vi oprettet denne konstant tidligere)

  3. Hvis signalet var SIG_A, og hvis den aktuelle tilstand er LISTEN_A

    Indstil enhedens tilstand til TEAM_A

  4. Hvis signalet var SIG_B, og hvis den aktuelle tilstand er LISTEN_B

    Indstil enhedens tilstand til TEAM_B

Det er det. Ansøgningen er færdig.

Trin 9: Rootenhed: Vi vil være i stand til at vælge et signal

Rootenhed: Vi vil være i stand til at vælge et signal
Rootenhed: Vi vil være i stand til at vælge et signal

Nu skriver vi en simpel applikation til en "root" -enhed, det vil sige en enhed, der styrer netværket.

Denne enhed skal udføre to funktioner:

  • Vi ønsker at give brugeren mulighed for at vælge et af vores signaler
  • Vi ønsker at give brugeren mulighed for at udsende signalet

Fordi specifikationen af denne applikation er en delmængde af den foregående, vil jeg give et overblik, men jeg vil ikke gå så meget i detaljer som jeg havde før. Billedet ovenfor indeholder den komplette kode til denne applikation.

Sådan tillader brugeren at vælge et signal:

  1. Initialiser 5 variabler i en "på start" -blok:

    1. De tre signaler (0, 1, 2)
    2. Antal signaler (3)
    3. En variabel til at holde det aktuelt valgte signal (oprindeligt indstillet til det første signal, 0)
  2. Håndter et tryk på A -knappen:

    1. Forøg det valgte signal
    2. Kontroller, om det valgte signal er større end eller lig med antallet af signaler

      Indstil i så fald det valgte signal til 0

  3. Efter startblokken skal du køre en "forever" -sløjfe, der viser den aktuelle valgte signalværdi uden forsinkelse

For at give brugeren mulighed for at udsende et signal

  1. Indstil radiogruppen til 0 i blokken "on start"
  2. Håndter et tryk på B -knappen:

    Udsend det valgte signal ved hjælp af en "radiosend nummer (X)" blok

Det er det. Rodnodeprogrammet er ekstremt enkelt.

Trin 10: Vi er færdige

Vi er færdige
Vi er færdige

Ovenfor er et billede af de enheder, der kører applikationen. De to til højre kører hoved "bruger" applikationen, og den til venstre kører "root" applikationen.

Jeg demonstrerede dette spil på CS Connections 2018, en ugelang sommerkonference for mellem- og gymnasielærere om datalogiuddannelse. Jeg gav omkring 40 enheder ud til lærerne og forklarede reglerne. De fleste syntes, at spillet var underholdende, og mange fandt det forvirrende, indtil de fandt ud af, hvordan de skulle spille. Demonstrationen var kort, men vi syntes spillet var sjovt blandt en temmelig forskelligartet skare.

Flere oplysninger om CS Connections 2018 findes her.

Anbefalede: