Hvordan bygge en Python Bot som kan spille Web Games

How bygge en Python Bot som kan spille Web Games
86
Del
63
Share < .no> Dette Cyber ​​mandag Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av.

I denne opplæringen vil vi utforske ins og outs av å bygge en Computer Vision-basert spill bot i Python, som vil være i stand til å spille den populære Flash spillet Sushi Go Round. Du kan bruke teknikker lært i denne opplæringen for å lage roboter for automatisk å teste dine egne web-spill.



Endelig resultat Forhåndsvisning

La oss ta en titt på det endelige resultatet vi skal jobbe mot:



Forutsetninger

Denne opplæringen, og all koden i det, krever at noen flere Python bibliotekene skal installeres. De gir en fin Python innpakning til en haug med lavt nivå C-kode som i stor grad forenkler prosessen og hastigheten på bot scripting.

Noen av koden og biblioteker er Windows-spesifikke. Det kan være Mac- eller Linux-ekvivalenter, men vi vil ikke dekke dem i denne opplæringen

Du må laste ned og installere følgende biblioteker.

  • Python Imaging Bibliotek

    Numpy

    PyWin

    Alle de ovennevnte har selv installatører; Kjører dem vil automatisk installere modulene i din \\ lib \\ site-pakker katalogen og i teorien justere PYTHONPATH tilsvarende. Men i praksis er dette ikke alltid skjer. Skulle du begynne å motta noen Import Feilmeldinger etter installasjon, vil du sannsynligvis trenger å justere Miljøvariabler manuelt. Mer informasjon om justering Sti Variabler kan bli funnet her.

    Det siste verktøyet vi trenger er en anstendig tegneprogram. Jeg foreslår Paint.NET som et utmerket gratis alternativ, men et program med herskere som viser sine målinger i piksler kan brukes.

    Vi vil bruke et par spill som eksempler underveis



    Innledning

    Denne veiledningen er skrevet for å ga en grunnleggende innføring i ferd med å bygge roboter som spiller nettleserbaserte spill. Tilnærmingen vi kommer til å ta er trolig litt annerledes enn hva de fleste forventer når de tenker på en bot. Snarere enn å lage et program som sitter mellom klient og server injisere kode (som en Quake eller C /S bot), vil vår bot sitte utelukkende på "utenfor". Vi skal stole på Computer Vision-esque teknikker og Windows API-kall for å samle nødvendig informasjon og generere bevegelse.

    Med denne tilnærmingen mister vi litt av raffinert detalj og kontroll, men gjør opp for det i forkortet dev tid og brukervennlighet. Automatisere en bestemt spill funksjon kan gjøres i noen korte linjer med kode, og en fullverdig, start-til-avslutning bot (for et enkelt spill) kan sveives ut i et par timer.

    Gleden av denne raske tilnærmingen er slik at når du blir kjent med hva maskinen kan lett "se", vil du begynne å se spill litt annerledes. Et godt eksempel er funnet i puzzle-spill. En vanlig konstruksjon innebærer å utnytte menneskelige hastighetsbegrensninger for å tvinge deg til en mindre enn optimal løsning. Det er morsomt (og ganske lett) å "pause" i disse spillene av scripting i bevegelser som aldri kunne oppnås ved et menneske

    Disse botene er også svært nyttig for å teste enkle spill -. Motsetning et menneske, en bot won 't bli lei å spille samme scenario om og om igjen.

    Kildekode for alle opplæringen eksempler, samt for en av de ferdige eksempel roboter, kan bli funnet her.

    Ha det gøy



    Trinn 1: Opprett en ny Python Prosjekt

    I en ny mappe, høyreklikk og velg Ny > Tekstdokument.

    Når gjort, endre navn på filen fra "New Tekstdokument" til "quickGrab.py" (uten anførselstegn) og bekrefter at du ønsker å endre filtypen.

    Til slutt, høyreklikker du på vår nyopprettede filen og velg "Edit with IDLE" fra hurtigmenyen for å starte redaktør



    Trinn 2: Sette opp din første Screen Grab

    vil begynne arbeidet med vår bot ved å utforske grunnskjermen grab funksjon. Når oppe og går, vil vi gå gjennom det linje for linje, som denne funksjonen (og dens mange iterasjoner) vil fungere som ryggraden i vår kode

    I quickgrab.py skriv inn følgende kode:.
    import ImageGrabimport osimport timedef screengrab (): boks = () im = ImageGrab.grab () im.save (os.getcwd () + '\\\\ full_snap__' + str (int (time.time ())) + ". png ',' PNG ') def main (): screengrab () hvis __name__ ==' __main__ ': main ()

    Kjøre dette programmet skal gi deg en full snapshot av skjermen området:

    gjeldende koden griper hele bredden og høyden på skjermen området og lagrer den som en PNG i din nåværende arbeidskatalog.

    La oss nå gå gjennom koden for å se nøyaktig hvordan det fungerer.

    tre første linjene:
    import ImageGrabimport osimport tid

    ... er de treffende navnet "import uttalelser". Disse forteller Python å laste i de nevnte modulene under kjøring. Dette gir oss tilgang til deres metoder via module.attribute syntaks.

    Den første modulen er en del av Python Bildearkiv vi installert tidligere. Som navnet antyder, det gir oss den grunnleggende skjermen gabbing funksjonalitet vår bot vil stole på.

    Den andre linjen importerer OS (Operating System) Module. Dette gir oss muligheten til enkelt å navigere rundt vår operativsystemet kataloger. Det vil komme godt med når vi begynne å organisere eiendeler i ulike mapper.

    Dette siste import er den innebygde tids modulen. Godt bruke dette hovedsakelig for stempling gjeldende tid på øyeblikksbilder, men det kan være svært nyttig som en timer for roboter som trenger hendelser utløst over et gitt antall sekunder.

    De neste fire linjene utgjør hjertet av vår screengrab () -funksjonen
    def screengrab (). boks = () im = ImageGrab.grab () im.save (os.getcwd () + '\\\\ full_snap__' + str (int (time.time ()) ) + 'PNG', 'PNG')

    Den første linjen def screengrab () definerer navnet på funksjonen. De tomme parentes betyr det forventer ingen argumenter.

    Linje 2, boks = () tildeler en tom tuppel til en variabel som heter "boksen". Vi vil fylle dette med argumenter i neste trinn.

    Linje 3, im = ImageGrab.grab () oppretter en full skjermbilde og returnerer et RGB-bilde til forekomsten im

    Linje 4 kan være litt vanskelig hvis du ikke er kjent med hvordan Time modulen fungerer. Den første delen im.save (kaller "redde" metoden fra bilde klassen. Det forventer to
    argumenter. Den første er stedet der du vil lagre filen, og den andre er filformatet.

    Her har vi satt plasseringen ved først å ringe os.getcwd (). Dette blir den gjeldende katalogen koden blir kjørt fra og returnerer det som en streng. Vi neste legge et +. Dette vil bli brukt i mellom hver nytt argument for å sette sammen alle strengene sammen.

    Det neste stykket '\\\\ full_snap__ gi vår fil en enkel beskrivende navn. (Fordi skråstrek er en flukt karakter i Python, må vi legge til to av dem til unngå avbryter ut en av våre bokstaver)

    Neste er hårete bit:.. str (int (time.time ())) Dette tar nytte av Python innebygde type metoder Vi skal forklare dette stykket. ved å jobbe fra innsiden og ut:

    time.time () returnerer antall sekunder siden Epoch, som er gitt som en type Float Siden vi skaper et filnavn vi kan ikke ha desimal i. der, så vi først konvertere den til et heltall ved å pakke den i int (). Dette får oss nær, men Python kan ikke sette sammen typen Int med type String, så det siste trinnet er å pakke alt i str () -funksjonen til å gi oss en fin brukbare tidsstempel for filnavnet. Herfra er alt som gjenstår å legge utvidelsen som en del av strengen: + '.png' og passerer det andre argumentet som er igjen forlengelsen type. "PNG"

    Den siste delen av vår kode definerer funksjonen main (), og forteller det til å ringe screengrab () -funksjonen når det kjøres.

    Og her, på slutten, er en Python konvensjon som sjekker om manuset er øverste nivå, og i så fall kan det å kjøre. Oversatt, betyr det bare at at det bare utfører main () hvis det er drevet av seg selv. Ellers - hvis, for eksempel, er det lastet som en modul av en annen Python-skript - den bare leverer sine metoder i stedet for å gjennomføre sin kode
    def main (): screengrab () hvis __name__ == '__main__': main. ()



    Trinn 3: The markeringsramme

    ImageGrab.grab () -funksjonen godtar ett argument som definerer en markeringsrammen. Dette er et tuppel av koordinater etter mønster av (x, y, x, y) der, etter


      Det første paret med verdier (x, y .. definerer øvre venstre hjørne av boksen

      Det andre paret ..x, y) definerer nederst til høyre.

      Ved å kombinere disse tillater oss å bare kopiere den delen av skjermen vi trenger.

      La oss sette dette ut i praksis.

      I dette eksemplet skal vi bruke et spill som heter Sushi Go Round. (.. Ganske
      addicting Du har blitt advart) Åpne spillet i en ny fane, og ta et stillbilde med vår eksisterende screengrab () kode:

      Et øyeblikksbilde av hele skjermområdet.



      Trinn 4: Få Koordinater

      Nå er det på tide å begynne gruvedrift noen koordinater for vår markeringsrammen

      Åpne opp din siste bilde i et bilderedigeringsprogram..

      (0,0) posisjon er alltid plassert øverst i venstre hjørne av bildet. Vi ønsker å pad x- og y-koordinater slik at våre nye snapshot funksjonssett (0,0) til den nest siste hjørnet av spillets lekeområde.

      Årsakene til dette er todelt. Først, det gjør funn i spillet koordinerer mye lettere når vi trenger bare å justere verdier i forhold til lekeområde versus hele området av skjermoppløsningen. Sekund, flytte en mindre del av skjermen reduserer behandlings overhead kreves. Full skjermen griper produsere ganske mye data, noe som kan gjøre det vanskelig å krysse det flere ganger per sekund.

      Hvis ikke gjort allerede, aktivere linjal skjerm i editor og zoome inn på den øverste hjørne av lekeområde til du kan se pikslene i detalj:

      Hold markøren over den første piksel av lekeområdet og kontrollere koordinatene som vises på linjalen. Disse vil være de to første verdiene av vår Box tuppel. På min bestemt maskin disse verdiene er 157, 162.

      Naviger til underkant av lekeområdet for å få bunnen par koordinater.

      Dette viser koordinatene til 796 og 641. Ved å kombinere disse . med vår forrige paret gir en boks med koordinatene (157162796641)

      La oss legge denne til vår kode
      import ImageGrabimport osimport timedef screengrab (). boks = (157346796825) im = ImageGrab.grab ( boks) im.save (os.getcwd () + '\\\\ full_snap__' + str (int (time.time ())) + 'PNG', 'PNG') def main (): screengrab () hvis __name__ = = '__main__': main ()

      I linje 6 har vi oppdatert tuppel å holde koordinatene til lekeområdet

      Lagre og kjøre koden.. Åpne opp den nylig lagrede bildet og du skal se:

      Suksess! En perfekt grip av lekeområdet. Vi vil ikke alltid trenger å gjøre denne typen intensiv jakt på koordinater. Når vi kommer inn i Win32API vi vil gå over noen raskere metoder for å sette koordinatene når vi ikke trenger pixel perfekt nøyaktighet



      Trinn 5:. Planlegging fremover for Fleksibilitet

      Som det står nå, vi har hardkodet koordinatene i forhold til vår nåværende oppsett, forutsatt at vår
      nettleser, og vår
      oppløsning. Det er generelt en dårlig idé å hard-kode koordinater på denne måten. Hvis, for eksempel, vi ønsker å kjøre kode på en annen datamaskin - eller si, en ny annonse på nettstedet skifter posisjon av lekeområdet litt - vi måtte manuelt og møysommelig fikse alle våre koordinere samtaler

      Så vi kommer til å opprette to nye variabler: x_pad og y_pad. Disse vil bli brukt til å lagre forholdet mellom spillområdet og resten av skjermen. Dette vil gjøre det svært enkelt å port koden fra sted til sted siden hver ny koordinat vil være i forhold til de to globale variabler vi skal skape, og å justere for endringer i skjermområdet, er alt som kreves for å tilbakestille disse to variabler.

      Siden vi allerede har gjort målingene, sette putene for vårt nåværende system er veldig grei. Vi kommer til å sette pads å lagre plasseringen av den første piksel utsiden av lekeområdet. Fra første par x, koordinerer y i vår boks tuppel, trekke en en fra hver verdi. Så 157 blir 156, og 346 blir 345.

      La oss legge denne til vår kode.
      # Globals # ------------------ x_pad = 156y_pad = 345

      Nå som disse er satt, vil vi begynne å justere boksen tuppel å være i forhold til disse verdiene
      def screengrab (). boks = (x_pad + 1, y_pad + 1, 796, 825 ) im = ImageGrab.grab () im.save (os.getcwd () + '\\\\ full_snap__' + str (int (time.time ())) + 'PNG', 'PNG')

      For andre paret, skal vi først trekke verdiene av pads (156 og 345) fra koordinatene (796, 825), og deretter bruke disse verdiene i samme Pad + Verdi format
      def screengrab ().: box = (x_pad + 1, y_pad + 1, x_pad + 640, y_pad + 479) im = ImageGrab.grab () im.save (os.getcwd () + '\\\\ full_snap__' + str (int (time.time ( ))) + 'PNG', 'PNG')

      Her x koordinat blir 640 (769-156), og y blir 480 (825-345)

      Det kan virke litt overflødig i starten, men å gjøre dette ekstra trinnet sikrer enkelt vedlikehold i fremtiden



      Trinn 6:. Opprette en Docstring

      Før vi går videre, vi kommer til å lage en docstring på toppen av vårt prosjekt. Siden de fleste av våre kode vil være basert rundt spesifikke skjermkoordinater og relasjoner til
      koordinater, er det viktig å vite under hvilke omstendigheter alt blir riktig. For eksempel ting som gjeldende oppløsning, nettleser, verktøylinjer aktivert (siden de endrer nettleser området), og eventuelle justeringer som trengs for å sentrere lekeområdet på skjermen, alle påvirke den relative plasseringen av koordinatene. Å ha alt dette dokumentert sterkt
      hjelper feilsøkingsprosessen når du kjører koden din på tvers av flere nettlesere og datamaskiner.

      En siste ting å være klar over er den stadig skiftende annonseplass på populære spillsider . Hvis alle dine grab samtaler plutselig slutte å oppføre seg som forventet, en ny legge litt skiftende ting på skjermen er en god innsats

      Som et eksempel, jeg har som regel følgende kommentarer på toppen av min Python-kode:.
      "" "Alle koordinatene anta en skjermoppløsning på 1280x1024, og Chrome maksimert med bokmerker enabled.Down nøkkelen har blitt truffet 4 ganger for å sentrere lekepark i browser.x_pad = 156y_pad = 345Play areal = x_pad + 1, y_pad + 1, 796, 825 "" "

      Slippe all denne informasjonen i begynnelsen av Python-filen gjør det raskt og enkelt å dobbeltsjekke alle dine innstillinger og skjermen justering uten å måtte pore over koden din prøver å huske hvor du lagres som én bestemt x-koordinat



      Trinn 7:. Slå quickGrab.py Into et nyttig verktøy

      Vi kommer til å punge vårt prosjekt på dette punktet, og skaper to filer: en til å holde alle våre bot kode, og den andre til å fungere som en generell skjermbilde verktøyet. Vi kommer til å ta mye av skjermbilder som vi jakte på koordinatene, så har en egen modul klar til å gå vil gjøre ting mye Raskere.

      Lagre og lukk vårt nåværende prosjekt.
      < p> I mappen, høyreklikker du på quickGrab.py og velg "kopier" fra menyen.

      Nå høyreklikk og velg "lime" fra menyen

      Velg den kopierte filen og endre navnet til "code.py '

      Fra nå av skal alle nye kode tilføyelser og endringer vil bli gjort i code.py. quickGrab.py vil nå fungere som en ren snapshot verktøy. Vi trenger bare å gjøre en siste modifikasjon.

      Endre filtypen fra .py, til .pyw og bekrefte endringene

      Denne utvidelsen forteller Python å kjøre skriptet uten å lansere konsollen. Så nå lever quickGrab.pyw opp til navnet sitt. Dobbeltklikk på filen og det vil stille utføre sin kode i bakgrunnen og lagre et øyeblikksbilde til din arbeidsmappen.

      Hold spillet åpent i bakgrunnen (husk å dempe den før loopet musikk driver deg til galskap); vi vil komme tilbake til det om kort tid. Vi har noen flere konsepter /verktøy for å innføre før vi kommer inn i styre ting på skjermen



      Trinn 8:. Win32API - En kort oversikt

      Arbeide med Win32API kan være en litt skremmende i starten. Det brytes lavnivå Windows C-kode - som er heldigvis veldig
      godt dokumentert her, men litt som en labyrint å navigere gjennom første par go-arounds

      Før vi starter. skripting noen nyttige handlinger, skal vi ta en nærmere titt på noen av API-funksjoner hvorpå vi skal stole. Når vi har en klar forståelse av hver parameter vil det være lett å justere dem for å tjene det formål vi trenger i spillet

      win32api.mouse_event ().
      Win32api.mouse_event (dwFlags, dx, dy, dwData)

      Den første parameteren dwFlags definerer "action" på musen. Den styrer ting som bevegelse, klikke, rulle, etc ..

      Følgende liste viser de vanligste parametrene brukes mens scripting movement.

      dwFlags:


      win32con.MOUSEEVENTF_LEFTDOWN

      win32con.MOUSEEVENTF_LEFTUP

      win32con.MOUSEEVENTF_MIDDLEDOWN

      win32con.MOUSEEVENTF_MIDDLEUP

      win32con.MOUSEEVENTF_RIGHTDOWN

      win32con.MOUSEEVENTF_RIGHTUP

      win32con.MOUSEEVENTF_WHEEL

      Each Navnet er selvforklarende. Hvis du ønsket å sende en virtuell høyreklikk, du ville passere win32con.MOUSEEVENTF_RIGHTDOWN til dwFlags parameter.

      Den neste to parametre, dx og dy, beskrive musens absolutte posisjon langs x og y-aksen. Mens vi kunne bruke disse parametrene for skripting musen bevegelse, de bruker et koordinatsystem annerledes enn den vi har brukt. Så vil vi la dem satt til null og stole på en annen del av API for vår musen beveger behov.

      Den fjerde parameter er dwData. Denne funksjonen brukes hvis (og bare hvis) dwFlags inneholder MOUSEEVENTF_WHEEL. Ellers er kan utelates eller satt til null. dwData angir hvor mye bevegelse på musens rullehjul

      Et raskt eksempel å stivne disse teknikkene:.

      Hvis vi tenker oss et spill med et utvalg våpen system som ligner på Half-Life 2 - hvor våpen kan velges ved å rotere musehjulet - vi ville komme opp med følgende funksjon å sile gjennom listen med våpen:
      def browseWeapons (): weaponList = ['brekkjern', 'gravitasjon pistol', 'pistol' .. .] for jeg i weaponList: win32api.mouse_event (win32con.MOUSEEVENTF_MOUSEEVENTF_WHEEL, 0,0,120)

      Her er vi ønsker å simulere rulle musehjulet til å navigere vår teoretiske våpen notering, så vi passerte ... MOUSEEVENTF_WHEEL handlingen 'til den dwFlag. Vi trenger ikke dx eller dy, posisjonsdata, slik at vi igjen de som er satt til null, og vi ønsket å bla ett klikk i retning fremover for hver "våpen" i listen, så vi passerte heltallet 120 til dwData (hver hjulet klikk lik 120).

      Som du kan se, som arbeider med mouse_event er bare et spørsmål om å koble de riktige argumentene til rett sted. La oss nå flytte inn på noen mer brukbare funksjoner



      Trinn 5: Basic Mouse Klikker

      Vi kommer til å lage tre nye funksjoner. En generell venstreklikk funksjon, og to som håndterer den spesifikke ned og opp statene

      Åpne code.py med IDLE og legge til følgende til vår liste over import uttalelser.
      Import Win32API, win32con

      Som før, dette gir oss tilgang til modulens innhold via module.attribute syntaks

      Neste vi vil gjøre vårt første museklikk funksjon
      def leftClick ():.. win32api.mouse_event (win32con.MOUSEEVENTF_LEFTDOWN , 0,0) time.sleep (0,1) win32api.mouse_event (win32con.MOUSEEVENTF_LEFTUP, 0,0) print "Klikk". #completely valgfritt. Men hyggelig for debugging formål.

      Husk at alt vi gjør her er å tildele en "handling" til det første argumentet mouse_event. Vi trenger ikke å passere noen posisjonsinformasjon, så vi drar koordinatsystemet parametre (0,0), og vi trenger ikke å sende noen ekstra info, så dwData blir utelatt. Den time.sleep (0,1) -funksjonen forteller Python å stanse henrettelsen for tiden angitt i parentes. Vi vil legge til disse gjennom vår kode, vanligvis for svært kort tid. Uten disse, kan den "klikke" komme i forkant av seg selv og brann før menyer har en sjanse til å oppdatere.

      Så det vi har gjort her er en generell venstreklikk. Ett trykk, en utgivelse. Vi vil tilbringe mesteparten av vår tid med dette, men vi kommer til å gjøre to flere varianter.

      Den neste to er akkurat det samme, men nå hvert trinn er delt inn i sin egen funksjon. Disse vil bli brukt når vi trenger å holde nede muse for en lang tid (for å dra, skyting, etc ..)
      def leftDown (). Win32api.mouse_event (win32con.MOUSEEVENTF_LEFTDOWN, 0,0) tid. søvn (0,1) print "venstre Down 'def leftUp (): win32api.mouse_event (win32con.MOUSEEVENTF_LEFTUP, 0,0) time.sleep (0,1) print" venstre release "



      Trinn 9: Basic Mouse . bevegelse

      Med klikke ut av veien alt som er igjen er å bevege musen rundt på skjermen

      Legg følgende funksjoner til code.py:
      def mousePos (cord): Win32API. SetCursorPos ((x_pad + ledningen [0], y_pad + ledningen [1]) def get_cords (): x, y = win32api.GetCursorPos () x = x - x_pad y = y - y_pad print x, y

      Disse to funksjoner tjene distinkt forskjellige formål. Den første vil bli brukt for skripting bevegelse i programmet. Takket være gode navnekonvensjoner, gjør kroppen av funksjon akkurat som SetCursorPos () tilsier. Calling denne funksjonen setter musen til koordinatene sendes til den som . en x, y tuppel Legg merke til at vi har lagt til i vår x og y pads; det er viktig å gjøre dette hvor som helst et koordinatsystem kalles.

      Den andre er et enkelt verktøy som vi bruker når du kjører Python interaktivt. Den skriver til konsollen den aktuelle posisjonen til musen som en x, y tuppel. Dette gjør sterkt opp prosessen med å navigere gjennom menyene uten å måtte ta et øyeblikksbilde og bryte ut en linjal. Vi vil ikke alltid være i stand til å bruke den, som noen mus aktiviteter må være pixel-spesifikke, men når vi kan, det er en fantastisk tid saver.

      I neste trinn vil vi sette noen av disse nye teknikker for å bruke og begynne å navigere i spillet menyer. Men før vi gjør det, slette det gjeldende innholdet i main () i code.py og erstatte den med pass. Vi kommer til å jobbe med interaktiv teksten for neste steg, så vi vil ikke være behov screengrab () -funksjonen



      Trinn 10:. Navigere Spill Menyer

      I denne og de neste trinnene, skal vi forsøke å samle så mange arrangement koordinater som vi kan bruke våre get_cords () metoden. Ved hjelp av det vil vi være i stand til å raskt bygge opp koden for ting som du navigerer menyer, rydde bord, og lager mat. Når vi har disse sett, vil det bare være et spørsmål om å hekte dem i bot logikk.

      La oss komme i gang. Lagre og kjøre koden din for å få opp Python skallet. Siden vi erstattet kroppen av main () med pass i det siste trinnet, bør du se en tom skall på løping.

      Nå, før vi selv komme til spillbare delen av spillet er det fire innledende menyer vi trenger for å komme gjennom. De er som følger:


        Første "play" -knappen

        iPhone "fortsette" -knappen

        Tutorial "Skip" -knappen

        Dagens mål " Fortsett "knappen

        Vi må få koordinatene for hver av disse og legge dem til en ny funksjon kalt startGame (). Plasser IDLE skallet slik at du kan se både den og lekeområde. Skriv inn get_cords () funksjon, men ikke trykk retur ennå; bevege musen over knappen som du trenger koordinater. Pass på å ikke klikke ennå, så vi vil fokusere å forbli i skallet. Hold musen over menyvalget og
        trykk på returtasten. Dette vil ta tak i nåværende plassering av musen og skrive til konsollen et tuppel som inneholder x, y-verdiene. Gjenta dette for de resterende tre menyer.

        La skallet åpen og ordne det slik at du kan se det i tillegg til IDLE redaktør. Vi nå kommer til å nå legge vår startGame () funksjon og fylle den med våre nyervervede koordinater
        def startGame (). #location Av første meny mousePos ((182, 225)) leftClick () time.sleep ( 0,1) #location av andre meny mousePos ((193, 410)) leftClick () time.sleep (0,1) #location av tredje meny mousePos ((435, 470)) leftClick () time.sleep (0,1) # Plasseringen av fjerde meny mousePos ((167, 403)) leftClick () time.sleep (0,1)

        Vi har nå en fin kompakt funksjon for å ringe ved starten av hvert spill. Det setter markøren til hver av meny steder vi tidligere definerte, og så forteller musen til å klikke. time.sleep (0,1) forteller Python å stanse henrettelsen for 1/10 av et sekund mellom hvert klikk, noe som gir menyene nok tid til å oppdatere i mellom.

        Lagre og kjøre koden din, og du skal se en resultere ligner på dette:

        Som en svak menneske det tar meg litt lengre enn et sekund å navigere alle menyene for hånd, men vår bot kan nå gjøre det i ca 0,4 sekunder. Ikke verst i det hele tatt



        Trinn 11: Får Mat Koordinater

        Nå er vi kommer til å gjenta den samme prosessen for hver av disse knappene:

        Nok en gang i Python skallet, skriv i get_cords (), holder du musepekeren over maten boksen du trenger, og trykk på Enter-tasten for å utføre kommandoen.

        Som et alternativ til ytterligere fart på sakene sammen, hvis du har en ekstra skjerm, eller er i stand til å arrangere den python shell på en måte som du kan se det, så vel som spillområdet, i stedet for å skrive inn og kjører get_cords () hver gang vi trenger det, kan vi sette opp en enkel for loop . Bruk en time.sleep () metoden for å stanse henrettelsen akkurat lenge nok for deg å flytte musen til neste lokasjon trenger koordinater

        Her er det for loop i aksjon.

        Vi kommer å opprette en ny klasse kalt Cord og bruke den til å lagre alle koordinatverdiene vi samles. Å kunne kalle Cord.f_rice tilbyr et stort lesbarhet fordel over passerer koordinatene direkte til mousePos (). Som et alternativ, kan du også lagre alt i en ordbok, men jeg synes den klassen syntaks morsommere
        klasse Cord. F_shrimp = (54700) f_rice = (119 701) f_nori = (63 745) f_roe = (111 749 ) f_salmon = (54 815) f_unagi = (111 812)

        Vi kommer til å lagre mye av våre koordinater i denne klassen, og det vil være noe overlapping, så legger den "F_ 'prefiks forteller oss at vi henvise til maten steder, heller enn, si, en plassering i telefonmenyen.

        Vi kommer tilbake til disse i en bit. Det er litt mer koordinere jakt å gjøre



        Trinn 12: Får Empty Plate Koordinater

        Hver gang en kunde er ferdig å spise, etterlater de seg en plate som må klikket på som skal fjernes. Så vi trenger å få plasseringen av tomme plater også.

        Jeg har lagt merke til deres posisjon med en gigantisk rød "X". Gjenta samme mønster som i de to siste trinnene for å få sine koordinater. . Lagre dem i kommentarfeltet streng for nå
        "" "plate snorer: 108, 573 212, 574 311, 573 412, 574 516, 575 618, 573" ""

        Vi får tett. Bare et par skritt av foreløpige oppsettet før vi kommer inn i virkelig morsomme ting



        Trinn 13:. Får Phone Koordinater

        Ok, dette blir det siste settet med koordinater vi har til meg i denne bestemt måte.

        Denne har mye mer å holde styr på, så det kan være lurt å gjøre det manuelt ved å ringe get_cords () -funksjonen i stedet for den tidligere brukte for loop-metoden. Uansett, vi kommer til å gå gjennom alle telefonmenyene for å få koordinatene for hvert element.

        Dette er litt mer involvert som å nå en av de innkjøps skjermene vi trenger, må du har nok penger til å faktisk kjøpe noe. Så du trenger å gjøre et par stykker av sushi før du går om virksomheten Koordinasjon jakt. På det meste, må du gjøre to sushi ruller, tror jeg. Som vil få deg nok til å kjøpe litt ris, som vil få oss til skjermen vi trenger

        Det er seks menyer vi har å komme gjennom.


          The Phone Anmeldelser
          Første Meny

          Topping

          Rice

          Shipping

          Vi trenger å få koordinatene for alt, men Sake (selv om du kan hvis du . ønsker jeg fant bot fungerte fint uten det jeg var villig til å ofre en og annen dårlig i spillet anmeldelse for ikke å måtte kode i logikken)

          Å få koordinatene:..

          're kommer til å legge alle disse til vår Cord klasse. Vi vil bruke prefikset 'T_ "for å betegne at typer mat er telefon > elementer fyllinger eller meny
          klasse Cord. F_shrimp = (54700) f_rice = (119 701) f_nori = (63 745) f_roe = (111 749) f_salmon = (54 815) f_unagi = (111 812) # ----------------------------------- telefonen = (601, 730) menu_toppings = (567, 638) t_shrimp = (509, 581) t_nori = (507, 645) t_roe = (592, 644) t_salmon = (510, 699) t_unagi = (597, 585) t_exit = ( 614, 702) menu_rice = (551, 662) buy_rice = 564, 647 delivery_norm = (510, 664)

          Alright! Vi har endelig minelagt alle koordinatverdiene vi trenger. Så la oss begynne å gjøre noe nyttig



          Trinn 14:!. Rydde bord

          Vi kommer til å ta våre tidligere innspilte koordinater og bruke dem til å fylle en funksjon som heter clear_tables ()
          def clear_tables (): mousePos ((108, 573)) leftClick () mousePos ((212, 574)) leftClick () mousePos ((311, 573)) leftClick () mousePos ((412, 574)) leftClick ( ) mousePos ((516, 575)) leftClick () mousePos ((618, 573)) leftClick () time.sleep (1)

          Som du kan se, dette ser mer eller mindre akkurat som vår tidligere startGame () -funksjonen . Noen små forskjeller:

          Vi har ingen time.sleep () funksjoner mellom de forskjellige klikk hendelser. Vi trenger ikke å vente på noen menyer for å oppdatere, så vi trenger ikke å strupe våre klikk hastigheter.

          Vi gjør imidlertid ha en lang time.sleep () helt på slutten. Selv om ikke strengt nødvendig, er det fint å legge til disse sporadiske pauser i kjøringen til vår kode, noe akkurat lenge nok gi oss tid til å manuelt bryte ut av bot hoved sløyfe om nødvendig (som vi vil komme til). Ellers vil ting fortsette å stjele musen posisjon igjen og igjen, og du vil ikke være i stand til å skifte fokus til skallet lenge nok til å stoppe skriptet - som kan morsomt de første to eller tre ganger så du kjempe mot en mus , men den mister fort sin sjarm

          Så sørg for å legge inn noen pålitelige pauser i dine egne roboter



          Trinn 15:.! ​​Making Sushi

          Den første ting vi trenger å gjøre er å lære å lage sushi. Klikk på oppskriftsbok for å åpne bruksanvisningen. Alle sushi typer oppstått gjennom hele spillet vil bli funnet innenfor sine sider. Jeg vil merke de første tre under, men jeg la det til deg å katalog resten
          '' 'oppskrifter. Onigiri to ris, en nori caliroll: 1 ris, en nori, en rogn gunkan: 1 ris, en nori, 2 rogn '' '

          Nå skal vi sette opp en funksjon som vil akseptere et argument for "sushi type" og deretter sette sammen de riktige ingredienser basert på passert verdien.
          def makeFood (mat) : Hvis mat == 'caliroll': print 'Making en caliroll' mousePos (Cord.f_rice) leftClick () time.sleep (.05) mousePos (Cord.f_nori) leftClick () time.sleep (.05) mousePos (Cord available'mousePos(Cord.buy_rice)time.sleep(.1)leftClick()mousePos(Cord.delivery_norm)time.sleep(.1)leftClick()time.sleep(2.5)

          Providing